xref: /haiku/src/apps/webpositive/SettingsWindow.cpp (revision 6c4a44e36ba846c54467103f884d65dfa13e7fcb)
1 /*
2  * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include "SettingsWindow.h"
28 
29 #include <Button.h>
30 #include <CheckBox.h>
31 #include <ControlLook.h>
32 #include <GridLayoutBuilder.h>
33 #include <GroupLayout.h>
34 #include <GroupLayoutBuilder.h>
35 #include <Locale.h>
36 #include <MenuItem.h>
37 #include <MenuField.h>
38 #include <Message.h>
39 #include <PopUpMenu.h>
40 #include <ScrollView.h>
41 #include <SeparatorView.h>
42 #include <SpaceLayoutItem.h>
43 #include <TabView.h>
44 #include <TextControl.h>
45 #include <debugger.h>
46 
47 #include <stdio.h>
48 #include <stdlib.h>
49 
50 #include "BrowserApp.h"
51 #include "BrowsingHistory.h"
52 #include "BrowserWindow.h"
53 #include "FontSelectionView.h"
54 #include "SettingsKeys.h"
55 #include "SettingsMessage.h"
56 #include "WebSettings.h"
57 
58 
59 #undef B_TRANSLATION_CONTEXT
60 #define B_TRANSLATION_CONTEXT "Settings Window"
61 
62 enum {
63 	MSG_APPLY									= 'aply',
64 	MSG_CANCEL									= 'cncl',
65 	MSG_REVERT									= 'rvrt',
66 
67 	MSG_START_PAGE_CHANGED						= 'hpch',
68 	MSG_SEARCH_PAGE_CHANGED						= 'spch',
69 	MSG_DOWNLOAD_FOLDER_CHANGED					= 'dnfc',
70 	MSG_NEW_WINDOWS_BEHAVIOR_CHANGED			= 'nwbc',
71 	MSG_NEW_TABS_BEHAVIOR_CHANGED				= 'ntbc',
72 	MSG_HISTORY_MENU_DAYS_CHANGED				= 'digm',
73 	MSG_TAB_DISPLAY_BEHAVIOR_CHANGED			= 'tdbc',
74 	MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED	= 'ahic',
75 	MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED		= 'ahpc',
76 	MSG_SHOW_HOME_BUTTON_CHANGED				= 'shbc',
77 
78 	MSG_STANDARD_FONT_CHANGED					= 'stfc',
79 	MSG_SERIF_FONT_CHANGED						= 'sefc',
80 	MSG_SANS_SERIF_FONT_CHANGED					= 'ssfc',
81 	MSG_FIXED_FONT_CHANGED						= 'ffch',
82 
83 	MSG_STANDARD_FONT_SIZE_SELECTED				= 'sfss',
84 	MSG_FIXED_FONT_SIZE_SELECTED				= 'ffss',
85 
86 	MSG_USE_PROXY_CHANGED						= 'upsc',
87 	MSG_PROXY_ADDRESS_CHANGED					= 'psac',
88 	MSG_PROXY_PORT_CHANGED						= 'pspc',
89 };
90 
91 static const int32 kDefaultFontSize = 14;
92 
93 
94 SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings)
95 	:
96 	BWindow(frame, B_TRANSLATE("Settings"), B_TITLED_WINDOW_LOOK,
97 		B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS
98 			| B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
99 	fSettings(settings)
100 {
101 	SetLayout(new BGroupLayout(B_VERTICAL));
102 
103 	fApplyButton = new BButton(B_TRANSLATE("Apply"), new BMessage(MSG_APPLY));
104 	fCancelButton = new BButton(B_TRANSLATE("Cancel"),
105 		new BMessage(MSG_CANCEL));
106 	fRevertButton = new BButton(B_TRANSLATE("Revert"),
107 		new BMessage(MSG_REVERT));
108 
109 	float spacing = be_control_look->DefaultItemSpacing();
110 
111 	BTabView* tabView = new BTabView("settings pages", B_WIDTH_FROM_LABEL);
112 
113 	AddChild(BGroupLayoutBuilder(B_VERTICAL, spacing)
114 		.Add(tabView)
115 		.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
116 			.Add(fRevertButton)
117 			.AddGlue()
118 			.Add(fCancelButton)
119 			.Add(fApplyButton)
120 		)
121 		.SetInsets(spacing, spacing, spacing, spacing)
122 	);
123 
124 	tabView->AddTab(_CreateGeneralPage(spacing));
125 	tabView->AddTab(_CreateFontsPage(spacing));
126 	tabView->AddTab(_CreateProxyPage(spacing));
127 
128 	_SetupFontSelectionView(fStandardFontView,
129 		new BMessage(MSG_STANDARD_FONT_CHANGED));
130 	_SetupFontSelectionView(fSerifFontView,
131 		new BMessage(MSG_SERIF_FONT_CHANGED));
132 	_SetupFontSelectionView(fSansSerifFontView,
133 		new BMessage(MSG_SANS_SERIF_FONT_CHANGED));
134 	_SetupFontSelectionView(fFixedFontView,
135 		new BMessage(MSG_FIXED_FONT_CHANGED));
136 
137 	fApplyButton->MakeDefault(true);
138 
139 	if (!frame.IsValid())
140 		CenterOnScreen();
141 
142 	// load settings from disk
143 	_RevertSettings();
144 	// apply to WebKit
145 	_ApplySettings();
146 
147 	// Start hidden
148 	Hide();
149 	Show();
150 }
151 
152 
153 SettingsWindow::~SettingsWindow()
154 {
155 	RemoveHandler(fStandardFontView);
156 	delete fStandardFontView;
157 	RemoveHandler(fSerifFontView);
158 	delete fSerifFontView;
159 	RemoveHandler(fSansSerifFontView);
160 	delete fSansSerifFontView;
161 	RemoveHandler(fFixedFontView);
162 	delete fFixedFontView;
163 }
164 
165 
166 void
167 SettingsWindow::MessageReceived(BMessage* message)
168 {
169 	switch (message->what) {
170 		case MSG_APPLY:
171 			_ApplySettings();
172 			break;
173 		case MSG_CANCEL:
174 			_RevertSettings();
175 			PostMessage(B_QUIT_REQUESTED);
176 			break;
177 		case MSG_REVERT:
178 			_RevertSettings();
179 			break;
180 
181 		case MSG_STANDARD_FONT_SIZE_SELECTED:
182 		{
183 			int32 size = _SizesMenuValue(fStandardSizesMenu->Menu());
184 			fStandardFontView->SetSize(size);
185 			fSerifFontView->SetSize(size);
186 			fSansSerifFontView->SetSize(size);
187 			_ValidateControlsEnabledStatus();
188 			break;
189 		}
190 		case MSG_FIXED_FONT_SIZE_SELECTED:
191 		{
192 			int32 size = _SizesMenuValue(fFixedSizesMenu->Menu());
193 			fFixedFontView->SetSize(size);
194 			_ValidateControlsEnabledStatus();
195 			break;
196 		}
197 
198 		case MSG_START_PAGE_CHANGED:
199 		case MSG_SEARCH_PAGE_CHANGED:
200 		case MSG_DOWNLOAD_FOLDER_CHANGED:
201 		case MSG_NEW_WINDOWS_BEHAVIOR_CHANGED:
202 		case MSG_NEW_TABS_BEHAVIOR_CHANGED:
203 		case MSG_HISTORY_MENU_DAYS_CHANGED:
204 		case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED:
205 		case MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED:
206 		case MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED:
207 		case MSG_SHOW_HOME_BUTTON_CHANGED:
208 		case MSG_STANDARD_FONT_CHANGED:
209 		case MSG_SERIF_FONT_CHANGED:
210 		case MSG_SANS_SERIF_FONT_CHANGED:
211 		case MSG_FIXED_FONT_CHANGED:
212 		case MSG_USE_PROXY_CHANGED:
213 		case MSG_PROXY_ADDRESS_CHANGED:
214 		case MSG_PROXY_PORT_CHANGED:
215 			// TODO: Some settings could change live, some others not?
216 			_ValidateControlsEnabledStatus();
217 			break;
218 
219 		default:
220 			BWindow::MessageReceived(message);
221 			break;
222 	}
223 }
224 
225 
226 bool
227 SettingsWindow::QuitRequested()
228 {
229 	if (!IsHidden())
230 		Hide();
231 	return false;
232 }
233 
234 
235 void
236 SettingsWindow::Show()
237 {
238 	// When showing the window, the this is always the
239 	// point to which we can revert the settings.
240 	_RevertSettings();
241 	BWindow::Show();
242 }
243 
244 
245 // #pragma mark - private
246 
247 
248 BView*
249 SettingsWindow::_CreateGeneralPage(float spacing)
250 {
251 	fStartPageControl = new BTextControl("start page",
252 		B_TRANSLATE("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED));
253 	fStartPageControl->SetModificationMessage(
254 		new BMessage(MSG_START_PAGE_CHANGED));
255 	fStartPageControl->SetText(
256 		fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL));
257 
258 	fSearchPageControl = new BTextControl("search page",
259 		B_TRANSLATE("Search page:"), "",
260 		new BMessage(MSG_SEARCH_PAGE_CHANGED));
261 	fSearchPageControl->SetModificationMessage(
262 		new BMessage(MSG_SEARCH_PAGE_CHANGED));
263 	fSearchPageControl->SetText(
264 		fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL));
265 
266 	fDownloadFolderControl = new BTextControl("download folder",
267 		B_TRANSLATE("Download folder:"), "",
268 		new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED));
269 	fDownloadFolderControl->SetModificationMessage(
270 		new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED));
271 	fDownloadFolderControl->SetText(
272 		fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath));
273 
274 	fNewWindowBehaviorOpenHomeItem = new BMenuItem(
275 		B_TRANSLATE("Open start page"),
276 		new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
277 	fNewWindowBehaviorOpenSearchItem = new BMenuItem(
278 		B_TRANSLATE("Open search page"),
279 		new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
280 	fNewWindowBehaviorOpenBlankItem = new BMenuItem(
281 		B_TRANSLATE("Open blank page"),
282 		new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
283 
284 	fNewTabBehaviorCloneCurrentItem = new BMenuItem(
285 		B_TRANSLATE("Clone current page"),
286 		new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
287 	fNewTabBehaviorOpenHomeItem = new BMenuItem(
288 		B_TRANSLATE("Open start page"),
289 		new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
290 	fNewTabBehaviorOpenSearchItem = new BMenuItem(
291 		B_TRANSLATE("Open search page"),
292 		new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
293 	fNewTabBehaviorOpenBlankItem = new BMenuItem(
294 		B_TRANSLATE("Open blank page"),
295 		new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
296 
297 	fNewWindowBehaviorOpenHomeItem->SetMarked(true);
298 	fNewTabBehaviorOpenBlankItem->SetMarked(true);
299 
300 	BPopUpMenu* newWindowBehaviorMenu = new BPopUpMenu("New windows");
301 	newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenHomeItem);
302 	newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem);
303 	newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem);
304 	fNewWindowBehaviorMenu = new BMenuField("new window behavior",
305 		B_TRANSLATE("New windows:"), newWindowBehaviorMenu);
306 
307 	BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs");
308 	newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem);
309 	newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenHomeItem);
310 	newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem);
311 	newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem);
312 	fNewTabBehaviorMenu = new BMenuField("new tab behavior",
313 		B_TRANSLATE("New tabs:"), newTabBehaviorMenu);
314 
315 	fDaysInHistoryMenuControl = new BTextControl("days in history",
316 		B_TRANSLATE("Number of days to keep links in History menu:"), "",
317 		new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED));
318 	fDaysInHistoryMenuControl->SetModificationMessage(
319 		new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED));
320 	BString maxHistoryAge;
321 	maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge();
322 	fDaysInHistoryMenuControl->SetText(maxHistoryAge.String());
323 	for (uchar i = 0; i < '0'; i++)
324 		fDaysInHistoryMenuControl->TextView()->DisallowChar(i);
325 	for (uchar i = '9' + 1; i <= 128; i++)
326 		fDaysInHistoryMenuControl->TextView()->DisallowChar(i);
327 
328 	fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page",
329 		B_TRANSLATE("Show tabs if only one page is open"),
330 		new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED));
331 	fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON);
332 
333 	fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface",
334 		B_TRANSLATE("Auto-hide interface in full screen mode"),
335 		new BMessage(MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED));
336 	fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF);
337 
338 	fAutoHidePointer = new BCheckBox("auto-hide pointer",
339 		B_TRANSLATE("Auto-hide mouse pointer"),
340 		new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED));
341 	fAutoHidePointer->SetValue(B_CONTROL_OFF);
342 
343 	fShowHomeButton = new BCheckBox("show home button",
344 		B_TRANSLATE("Show home button"),
345 		new BMessage(MSG_SHOW_HOME_BUTTON_CHANGED));
346 	fShowHomeButton->SetValue(B_CONTROL_ON);
347 
348 	BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2)
349 		.Add(BGridLayoutBuilder(spacing / 2, spacing / 2)
350 			.Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0)
351 			.Add(fStartPageControl->CreateTextViewLayoutItem(), 1, 0)
352 
353 			.Add(fSearchPageControl->CreateLabelLayoutItem(), 0, 1)
354 			.Add(fSearchPageControl->CreateTextViewLayoutItem(), 1, 1)
355 
356 			.Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 2)
357 			.Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 2)
358 
359 			.Add(fNewWindowBehaviorMenu->CreateLabelLayoutItem(), 0, 3)
360 			.Add(fNewWindowBehaviorMenu->CreateMenuBarLayoutItem(), 1, 3)
361 
362 			.Add(fNewTabBehaviorMenu->CreateLabelLayoutItem(), 0, 4)
363 			.Add(fNewTabBehaviorMenu->CreateMenuBarLayoutItem(), 1, 4)
364 		)
365 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
366 		.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
367 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
368 		.Add(fShowTabsIfOnlyOnePage)
369 		.Add(fAutoHideInterfaceInFullscreenMode)
370 		.Add(fAutoHidePointer)
371 		.Add(fShowHomeButton)
372 		.Add(fDaysInHistoryMenuControl)
373 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
374 
375 		.SetInsets(spacing, spacing, spacing, spacing)
376 
377 		.TopView()
378 	;
379 	view->SetName(B_TRANSLATE("General"));
380 	return view;
381 }
382 
383 
384 BView*
385 SettingsWindow::_CreateFontsPage(float spacing)
386 {
387 	fStandardFontView = new FontSelectionView("standard",
388 		B_TRANSLATE("Standard font:"), true, be_plain_font);
389 	BFont defaultSerifFont = _FindDefaultSerifFont();
390 	fSerifFontView = new FontSelectionView("serif",
391 		B_TRANSLATE("Serif font:"), true, &defaultSerifFont);
392 	fSansSerifFontView = new FontSelectionView("sans serif",
393 		B_TRANSLATE("Sans serif font:"), true, be_plain_font);
394 	fFixedFontView = new FontSelectionView("fixed",
395 		B_TRANSLATE("Fixed font:"), true, be_fixed_font);
396 
397 	fStandardSizesMenu =  new BMenuField("standard font size",
398 		B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"),
399 		B_WILL_DRAW);
400 	_BuildSizesMenu(fStandardSizesMenu->Menu(),
401 		MSG_STANDARD_FONT_SIZE_SELECTED);
402 
403 	fFixedSizesMenu =  new BMenuField("fixed font size",
404 		B_TRANSLATE("Default fixed font size:"), new BPopUpMenu("sizes"),
405 		B_WILL_DRAW);
406 	_BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED);
407 
408 	BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2)
409 		.Add(fStandardFontView->CreateFontsLabelLayoutItem(), 0, 0)
410 		.Add(fStandardFontView->CreateFontsMenuBarLayoutItem(), 1, 0)
411 		.Add(fStandardFontView->PreviewBox(), 0, 1, 2)
412 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 2, 2)
413 
414 		.Add(fSerifFontView->CreateFontsLabelLayoutItem(), 0, 3)
415 		.Add(fSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 3)
416 		.Add(fSerifFontView->PreviewBox(), 0, 4, 2)
417 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2)
418 
419 		.Add(fSansSerifFontView->CreateFontsLabelLayoutItem(), 0, 6)
420 		.Add(fSansSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 6)
421 		.Add(fSansSerifFontView->PreviewBox(), 0, 7, 2)
422 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 8, 2)
423 
424 		.Add(fFixedFontView->CreateFontsLabelLayoutItem(), 0, 9)
425 		.Add(fFixedFontView->CreateFontsMenuBarLayoutItem(), 1, 9)
426 		.Add(fFixedFontView->PreviewBox(), 0, 10, 2)
427 		.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 11, 2)
428 
429 		.Add(fStandardSizesMenu->CreateLabelLayoutItem(), 0, 12)
430 		.Add(fStandardSizesMenu->CreateMenuBarLayoutItem(), 1, 12)
431 		.Add(fFixedSizesMenu->CreateLabelLayoutItem(), 0, 13)
432 		.Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13)
433 
434 		.SetInsets(spacing, spacing, spacing, spacing)
435 
436 		.View()
437 	;
438 
439 	view->SetName(B_TRANSLATE("Fonts"));
440 	return view;
441 }
442 
443 
444 BView*
445 SettingsWindow::_CreateProxyPage(float spacing)
446 {
447 	fUseProxyCheckBox = new BCheckBox("use proxy",
448 		B_TRANSLATE("Use proxy server to connect to the internet"),
449 		new BMessage(MSG_USE_PROXY_CHANGED));
450 	fUseProxyCheckBox->SetValue(B_CONTROL_ON);
451 
452 	fProxyAddressControl = new BTextControl("proxy address",
453 		B_TRANSLATE("Proxy server address:"), "",
454 		new BMessage(MSG_PROXY_ADDRESS_CHANGED));
455 	fProxyAddressControl->SetModificationMessage(
456 		new BMessage(MSG_PROXY_ADDRESS_CHANGED));
457 	fProxyAddressControl->SetText(
458 		fSettings->GetValue(kSettingsKeyProxyAddress, ""));
459 
460 	fProxyPortControl = new BTextControl("proxy port",
461 		B_TRANSLATE("Proxy server port:"), "",
462 		new BMessage(MSG_PROXY_PORT_CHANGED));
463 	fProxyPortControl->SetModificationMessage(
464 		new BMessage(MSG_PROXY_PORT_CHANGED));
465 	fProxyPortControl->SetText(
466 		fSettings->GetValue(kSettingsKeyProxyAddress, ""));
467 
468 	BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2)
469 		.Add(fUseProxyCheckBox)
470 		.Add(BGridLayoutBuilder(spacing / 2, spacing / 2)
471 			.Add(fProxyAddressControl->CreateLabelLayoutItem(), 0, 0)
472 			.Add(fProxyAddressControl->CreateTextViewLayoutItem(), 1, 0)
473 
474 			.Add(fProxyPortControl->CreateLabelLayoutItem(), 0, 1)
475 			.Add(fProxyPortControl->CreateTextViewLayoutItem(), 1, 1)
476 		)
477 		.Add(BSpaceLayoutItem::CreateGlue())
478 
479 		.SetInsets(spacing, spacing, spacing, spacing)
480 
481 		.TopView()
482 	;
483 	view->SetName(B_TRANSLATE("Proxy server"));
484 	return view;
485 }
486 
487 
488 void
489 SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat)
490 {
491 	const float kMinSize = 8.0;
492 	const float kMaxSize = 18.0;
493 
494 	const int32 kSizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 24, 0};
495 
496 	for (int32 i = 0; kSizes[i]; i++) {
497 		int32 size = kSizes[i];
498 		if (size < kMinSize || size > kMaxSize)
499 			continue;
500 
501 		char label[32];
502 		snprintf(label, sizeof(label), "%ld", size);
503 
504 		BMessage* message = new BMessage(messageWhat);
505 		message->AddInt32("size", size);
506 
507 		BMenuItem* item = new BMenuItem(label, message);
508 
509 		menu->AddItem(item);
510 		item->SetTarget(this);
511 	}
512 }
513 
514 
515 void
516 SettingsWindow::_SetupFontSelectionView(FontSelectionView* view,
517 	BMessage* message)
518 {
519 	AddHandler(view);
520 	view->AttachedToLooper();
521 	view->SetMessage(message);
522 	view->SetTarget(this);
523 }
524 
525 
526 // #pragma mark -
527 
528 
529 bool
530 SettingsWindow::_CanApplySettings() const
531 {
532 	bool canApply = false;
533 
534 	// General settings
535 	canApply = canApply || (strcmp(fStartPageControl->Text(),
536 		fSettings->GetValue(kSettingsKeyStartPageURL,
537 			kDefaultStartPageURL)) != 0);
538 
539 	canApply = canApply || (strcmp(fSearchPageControl->Text(),
540 		fSettings->GetValue(kSettingsKeySearchPageURL,
541 			kDefaultSearchPageURL)) != 0);
542 
543 	canApply = canApply || (strcmp(fDownloadFolderControl->Text(),
544 		fSettings->GetValue(kSettingsKeyDownloadPath,
545 			kDefaultDownloadPath)) != 0);
546 
547 	canApply = canApply || ((fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON)
548 		!= fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true));
549 
550 	canApply = canApply || (
551 		(fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON)
552 		!= fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
553 			false));
554 
555 	canApply = canApply || (
556 		(fAutoHidePointer->Value() == B_CONTROL_ON)
557 		!= fSettings->GetValue(kSettingsKeyAutoHidePointer, false));
558 
559 	canApply = canApply || ((fShowHomeButton->Value() == B_CONTROL_ON)
560 		!= fSettings->GetValue(kSettingsKeyShowHomeButton, true));
561 
562 	canApply = canApply || (_MaxHistoryAge()
563 		!= BrowsingHistory::DefaultInstance()->MaxHistoryItemAge());
564 
565 	// New window policy
566 	canApply = canApply || (_NewWindowPolicy()
567 		!= fSettings->GetValue(kSettingsKeyNewWindowPolicy,
568 			(uint32)OpenStartPage));
569 
570 	// New tab policy
571 	canApply = canApply || (_NewTabPolicy()
572 		!= fSettings->GetValue(kSettingsKeyNewTabPolicy,
573 			(uint32)OpenBlankPage));
574 
575 	// Font settings
576 	canApply = canApply || (fStandardFontView->Font()
577 		!= fSettings->GetValue("standard font", *be_plain_font));
578 
579 	canApply = canApply || (fSerifFontView->Font()
580 		!= fSettings->GetValue("serif font", _FindDefaultSerifFont()));
581 
582 	canApply = canApply || (fSansSerifFontView->Font()
583 		!= fSettings->GetValue("sans serif font", *be_plain_font));
584 
585 	canApply = canApply || (fFixedFontView->Font()
586 		!= fSettings->GetValue("fixed font", *be_fixed_font));
587 
588 	canApply = canApply || (_SizesMenuValue(fStandardSizesMenu->Menu())
589 		!= fSettings->GetValue("standard font size", kDefaultFontSize));
590 
591 	canApply = canApply || (_SizesMenuValue(fFixedSizesMenu->Menu())
592 		!= fSettings->GetValue("fixed font size", kDefaultFontSize));
593 
594 	// Proxy settings
595 	canApply = canApply || ((fUseProxyCheckBox->Value() == B_CONTROL_ON)
596 		!= fSettings->GetValue(kSettingsKeyUseProxy, false));
597 
598 	canApply = canApply || (strcmp(fProxyAddressControl->Text(),
599 		fSettings->GetValue(kSettingsKeyProxyAddress, "")) != 0);
600 
601 	canApply = canApply || (_ProxyPort()
602 		!= fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0));
603 
604 	return canApply;
605 }
606 
607 
608 void
609 SettingsWindow::_ApplySettings()
610 {
611 	// Store general settings
612 	int32 maxHistoryAge = _MaxHistoryAge();
613 	BString text;
614 	text << maxHistoryAge;
615 	fDaysInHistoryMenuControl->SetText(text.String());
616 	BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge);
617 
618 	fSettings->SetValue(kSettingsKeyStartPageURL, fStartPageControl->Text());
619 	fSettings->SetValue(kSettingsKeySearchPageURL, fSearchPageControl->Text());
620 	fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text());
621 	fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen,
622 		fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON);
623 	fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
624 		fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON);
625 	fSettings->SetValue(kSettingsKeyAutoHidePointer,
626 		fAutoHidePointer->Value() == B_CONTROL_ON);
627 	fSettings->SetValue(kSettingsKeyShowHomeButton,
628 		fShowHomeButton->Value() == B_CONTROL_ON);
629 
630 	// New page policies
631 	fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy());
632 	fSettings->SetValue(kSettingsKeyNewTabPolicy, _NewTabPolicy());
633 
634 	// Store fond settings
635 	fSettings->SetValue("standard font", fStandardFontView->Font());
636 	fSettings->SetValue("serif font", fSerifFontView->Font());
637 	fSettings->SetValue("sans serif font", fSansSerifFontView->Font());
638 	fSettings->SetValue("fixed font", fFixedFontView->Font());
639 	int32 standardFontSize = _SizesMenuValue(fStandardSizesMenu->Menu());
640 	int32 fixedFontSize = _SizesMenuValue(fFixedSizesMenu->Menu());
641 	fSettings->SetValue("standard font size", standardFontSize);
642 	fSettings->SetValue("fixed font size", fixedFontSize);
643 
644 	// Store proxy settings
645 
646 	fSettings->SetValue(kSettingsKeyUseProxy,
647 		fUseProxyCheckBox->Value() == B_CONTROL_ON);
648 	fSettings->SetValue(kSettingsKeyProxyAddress,
649 		fProxyAddressControl->Text());
650 	uint32 proxyPort = _ProxyPort();
651 	fSettings->SetValue(kSettingsKeyProxyPort, proxyPort);
652 
653 	fSettings->Save();
654 
655 	// Apply settings to default web page settings.
656 	BWebSettings::Default()->SetStandardFont(fStandardFontView->Font());
657 	BWebSettings::Default()->SetSerifFont(fSerifFontView->Font());
658 	BWebSettings::Default()->SetSansSerifFont(fSansSerifFontView->Font());
659 	BWebSettings::Default()->SetFixedFont(fFixedFontView->Font());
660 	BWebSettings::Default()->SetDefaultStandardFontSize(standardFontSize);
661 	BWebSettings::Default()->SetDefaultFixedFontSize(fixedFontSize);
662 
663 	if (fUseProxyCheckBox->Value() == B_CONTROL_ON) {
664 		BWebSettings::Default()->SetProxyInfo(fProxyAddressControl->Text(),
665 			proxyPort, B_PROXY_TYPE_HTTP, "", "");
666 	} else
667 		BWebSettings::Default()->SetProxyInfo();
668 
669 	// This will find all currently instantiated page settings and apply
670 	// the default values, unless the page settings have local overrides.
671 	BWebSettings::Default()->Apply();
672 
673 
674 	_ValidateControlsEnabledStatus();
675 }
676 
677 
678 void
679 SettingsWindow::_RevertSettings()
680 {
681 	fStartPageControl->SetText(
682 		fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL));
683 
684 	fSearchPageControl->SetText(
685 		fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL));
686 
687 	fDownloadFolderControl->SetText(
688 		fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath));
689 	fShowTabsIfOnlyOnePage->SetValue(
690 		fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true));
691 	fAutoHideInterfaceInFullscreenMode->SetValue(
692 		fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
693 			false));
694 	fAutoHidePointer->SetValue(
695 		fSettings->GetValue(kSettingsKeyAutoHidePointer, false));
696 	fShowHomeButton->SetValue(
697 		fSettings->GetValue(kSettingsKeyShowHomeButton, true));
698 
699 	BString text;
700 	text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge();
701 	fDaysInHistoryMenuControl->SetText(text.String());
702 
703 	// New window policy
704 	uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy,
705 		(uint32)OpenStartPage);
706 	switch (newWindowPolicy) {
707 		default:
708 		case OpenStartPage:
709 			fNewWindowBehaviorOpenHomeItem->SetMarked(true);
710 			break;
711 		case OpenSearchPage:
712 			fNewWindowBehaviorOpenSearchItem->SetMarked(true);
713 			break;
714 		case OpenBlankPage:
715 			fNewWindowBehaviorOpenBlankItem->SetMarked(true);
716 			break;
717 	}
718 
719 	// New tab policy
720 	uint32 newTabPolicy = fSettings->GetValue(kSettingsKeyNewTabPolicy,
721 		(uint32)OpenBlankPage);
722 	switch (newTabPolicy) {
723 		default:
724 		case OpenBlankPage:
725 			fNewTabBehaviorOpenBlankItem->SetMarked(true);
726 			break;
727 		case OpenStartPage:
728 			fNewTabBehaviorOpenHomeItem->SetMarked(true);
729 			break;
730 		case OpenSearchPage:
731 			fNewTabBehaviorOpenSearchItem->SetMarked(true);
732 			break;
733 		case CloneCurrentPage:
734 			fNewTabBehaviorCloneCurrentItem->SetMarked(true);
735 			break;
736 	}
737 
738 	// Font settings
739 	int32 defaultFontSize = fSettings->GetValue("standard font size",
740 		kDefaultFontSize);
741 	int32 defaultFixedFontSize = fSettings->GetValue("fixed font size",
742 		kDefaultFontSize);
743 
744 	_SetSizesMenuValue(fStandardSizesMenu->Menu(), defaultFontSize);
745 	_SetSizesMenuValue(fFixedSizesMenu->Menu(), defaultFixedFontSize);
746 
747 	fStandardFontView->SetFont(fSettings->GetValue("standard font",
748 		*be_plain_font), defaultFontSize);
749 	fSerifFontView->SetFont(fSettings->GetValue("serif font",
750 		_FindDefaultSerifFont()), defaultFontSize);
751 	fSansSerifFontView->SetFont(fSettings->GetValue("sans serif font",
752 		*be_plain_font), defaultFontSize);
753 	fFixedFontView->SetFont(fSettings->GetValue("fixed font",
754 		*be_fixed_font), defaultFixedFontSize);
755 
756 	// Proxy settings
757 	fUseProxyCheckBox->SetValue(fSettings->GetValue(kSettingsKeyUseProxy,
758 		false));
759 	fProxyAddressControl->SetText(fSettings->GetValue(kSettingsKeyProxyAddress,
760 		""));
761 	text = "";
762 	text << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0);
763 	fProxyPortControl->SetText(text.String());
764 
765 	_ValidateControlsEnabledStatus();
766 }
767 
768 
769 void
770 SettingsWindow::_ValidateControlsEnabledStatus()
771 {
772 	bool canApply = _CanApplySettings();
773 	fApplyButton->SetEnabled(canApply);
774 	fRevertButton->SetEnabled(canApply);
775 	// Let the Cancel button be enabled always, as another way to close the
776 	// window...
777 	fCancelButton->SetEnabled(true);
778 
779 	bool useProxy = fUseProxyCheckBox->Value() == B_CONTROL_ON;
780 	fProxyAddressControl->SetEnabled(useProxy);
781 	fProxyPortControl->SetEnabled(useProxy);
782 }
783 
784 
785 // #pragma mark -
786 
787 
788 uint32
789 SettingsWindow::_NewWindowPolicy() const
790 {
791 	uint32 newWindowPolicy = OpenStartPage;
792 	BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked();
793 	if (markedItem == fNewWindowBehaviorOpenSearchItem)
794 		newWindowPolicy = OpenSearchPage;
795 	else if (markedItem == fNewWindowBehaviorOpenBlankItem)
796 		newWindowPolicy = OpenBlankPage;
797 	return newWindowPolicy;
798 }
799 
800 
801 uint32
802 SettingsWindow::_NewTabPolicy() const
803 {
804 	uint32 newTabPolicy = OpenBlankPage;
805 	BMenuItem* markedItem = fNewTabBehaviorMenu->Menu()->FindMarked();
806 	if (markedItem == fNewTabBehaviorCloneCurrentItem)
807 		newTabPolicy = CloneCurrentPage;
808 	else if (markedItem == fNewTabBehaviorOpenHomeItem)
809 		newTabPolicy = OpenStartPage;
810 	else if (markedItem == fNewTabBehaviorOpenSearchItem)
811 		newTabPolicy = OpenSearchPage;
812 	return newTabPolicy;
813 }
814 
815 
816 int32
817 SettingsWindow::_MaxHistoryAge() const
818 {
819 	int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text());
820 	if (maxHistoryAge <= 0)
821 		maxHistoryAge = 1;
822 	if (maxHistoryAge >= 35)
823 		maxHistoryAge = 35;
824 	return maxHistoryAge;
825 }
826 
827 
828 void
829 SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value)
830 {
831 	for (int32 i = 0; BMenuItem* item = menu->ItemAt(i); i++) {
832 		bool marked = false;
833 		if (BMessage* message = item->Message()) {
834 			int32 size;
835 			if (message->FindInt32("size", &size) == B_OK && size == value)
836 				marked = true;
837 		}
838 		item->SetMarked(marked);
839 	}
840 }
841 
842 
843 int32
844 SettingsWindow::_SizesMenuValue(BMenu* menu) const
845 {
846 	if (BMenuItem* item = menu->FindMarked()) {
847 		if (BMessage* message = item->Message()) {
848 			int32 size;
849 			if (message->FindInt32("size", &size) == B_OK)
850 				return size;
851 		}
852 	}
853 	return kDefaultFontSize;
854 }
855 
856 
857 BFont
858 SettingsWindow::_FindDefaultSerifFont() const
859 {
860 	// Default to the first "serif" font we find.
861 	BFont serifFont(*be_plain_font);
862 	font_family family;
863 	int32 familyCount = count_font_families();
864 	for (int32 i = 0; i < familyCount; i++) {
865 		if (get_font_family(i, &family) == B_OK) {
866 			BString familyString(family);
867 			if (familyString.IFindFirst("sans") >= 0)
868 				continue;
869 			if (familyString.IFindFirst("serif") >= 0) {
870 				serifFont.SetFamilyAndFace(family, B_REGULAR_FACE);
871 				break;
872 			}
873 		}
874 	}
875 	return serifFont;
876 }
877 
878 
879 uint32
880 SettingsWindow::_ProxyPort() const
881 {
882 	return atoul(fProxyPortControl->Text());
883 }
884 
885 
886