xref: /haiku/src/apps/deskbar/PreferencesWindow.cpp (revision 633232da4cd49e7bb51951928e5c05071c2a7a47)
1 /*
2  * Copyright 2009-2011 Haiku, Inc.
3  * All Rights Reserved. Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		John Scipione, jscipione@gmail.com
7  *		Jonas Sundström, jonas@kirilla.com
8  */
9 
10 
11 #include "PreferencesWindow.h"
12 
13 #include <ctype.h>
14 #include <stdio.h>
15 
16 #include <Box.h>
17 #include <Button.h>
18 #include <Catalog.h>
19 #include <CheckBox.h>
20 #include <ControlLook.h>
21 #include <FormattingConventions.h>
22 #include <GroupLayout.h>
23 #include <ListView.h>
24 #include <Locale.h>
25 #include <LayoutBuilder.h>
26 #include <OpenWithTracker.h>
27 #include <RadioButton.h>
28 #include <Roster.h>
29 #include <SeparatorView.h>
30 #include <Slider.h>
31 #include <TextControl.h>
32 #include <View.h>
33 
34 #include "BarApp.h"
35 #include "StatusView.h"
36 
37 
38 static const float kIndentSpacing
39 	= be_control_look->DefaultItemSpacing() * 2.3;
40 static const uint32 kSettingsViewChanged = 'Svch';
41 
42 
43 #undef B_TRANSLATION_CONTEXT
44 #define B_TRANSLATION_CONTEXT "PreferencesWindow"
45 
46 
47 PreferencesWindow::PreferencesWindow(BRect frame)
48 	:
49 	BWindow(frame, B_TRANSLATE("Deskbar preferences"), B_TITLED_WINDOW,
50 		B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE)
51 {
52 	// Initial settings (used by revert button)
53 	memcpy(&fSettings, static_cast<TBarApp*>(be_app)->Settings(),
54 		sizeof(desk_settings));
55 
56 	// Menu controls
57 	fMenuRecentDocuments = new BCheckBox(B_TRANSLATE("Recent documents:"),
58 		new BMessage(kUpdateRecentCounts));
59 	fMenuRecentApplications = new BCheckBox(B_TRANSLATE("Recent applications:"),
60 		new BMessage(kUpdateRecentCounts));
61 	fMenuRecentFolders = new BCheckBox(B_TRANSLATE("Recent folders:"),
62 		new BMessage(kUpdateRecentCounts));
63 
64 	fMenuRecentDocumentCount = new BTextControl(NULL, NULL,
65 		new BMessage(kUpdateRecentCounts));
66 	fMenuRecentApplicationCount = new BTextControl(NULL, NULL,
67 		new BMessage(kUpdateRecentCounts));
68 	fMenuRecentFolderCount = new BTextControl(NULL, NULL,
69 		new BMessage(kUpdateRecentCounts));
70 
71 	// Applications controls
72 	fAppsSort = new BCheckBox(B_TRANSLATE("Sort applications by name"),
73 		new BMessage(kSortRunningApps));
74 	fAppsSortTrackerFirst = new BCheckBox(B_TRANSLATE("Tracker always first"),
75 		new BMessage(kTrackerFirst));
76 	fAppsShowExpanders = new BCheckBox(B_TRANSLATE("Show application expander"),
77 		new BMessage(kSuperExpando));
78 	fAppsExpandNew = new BCheckBox(B_TRANSLATE("Expand new applications"),
79 		new BMessage(kExpandNewTeams));
80 	fAppsHideLabels = new BCheckBox(B_TRANSLATE("Hide application names"),
81 		new BMessage(kHideLabels));
82 	fAppsIconSizeSlider = new BSlider("icon_size", B_TRANSLATE("Icon size"),
83 		new BMessage(kResizeTeamIcons), kMinimumIconSize / kIconSizeInterval,
84 		kMaximumIconSize / kIconSizeInterval, B_HORIZONTAL);
85 	fAppsIconSizeSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
86 	fAppsIconSizeSlider->SetHashMarkCount((kMaximumIconSize - kMinimumIconSize)
87 		/ kIconSizeInterval + 1);
88 	fAppsIconSizeSlider->SetLimitLabels(B_TRANSLATE("Small"),
89 		B_TRANSLATE("Large"));
90 	fAppsIconSizeSlider->SetModificationMessage(new BMessage(kResizeTeamIcons));
91 
92 	// Window controls
93 	fWindowAlwaysOnTop = new BCheckBox(B_TRANSLATE("Always on top"),
94 		new BMessage(kAlwaysTop));
95 	fWindowAutoRaise = new BCheckBox(B_TRANSLATE("Auto-raise"),
96 		new BMessage(kAutoRaise));
97 	fWindowAutoHide = new BCheckBox(B_TRANSLATE("Auto-hide"),
98 		new BMessage(kAutoHide));
99 
100 	// Menu settings
101 	BTextView* docTextView = fMenuRecentDocumentCount->TextView();
102 	BTextView* appTextView = fMenuRecentApplicationCount->TextView();
103 	BTextView* folderTextView = fMenuRecentFolderCount->TextView();
104 
105 	for (int32 i = 0; i < 256; i++) {
106 		if (!isdigit(i)) {
107 			docTextView->DisallowChar(i);
108 			appTextView->DisallowChar(i);
109 			folderTextView->DisallowChar(i);
110 		}
111 	}
112 
113 	docTextView->SetMaxBytes(4);
114 	appTextView->SetMaxBytes(4);
115 	folderTextView->SetMaxBytes(4);
116 
117 	int32 docCount = fSettings.recentDocsCount;
118 	int32 appCount = fSettings.recentAppsCount;
119 	int32 folderCount = fSettings.recentFoldersCount;
120 
121 	fMenuRecentDocuments->SetValue(fSettings.recentDocsEnabled);
122 	fMenuRecentDocumentCount->SetEnabled(fSettings.recentDocsEnabled);
123 
124 	fMenuRecentApplications->SetValue(fSettings.recentAppsEnabled);
125 	fMenuRecentApplicationCount->SetEnabled(fSettings.recentAppsEnabled);
126 
127 	fMenuRecentFolders->SetValue(fSettings.recentFoldersEnabled);
128 	fMenuRecentFolderCount->SetEnabled(fSettings.recentFoldersEnabled);
129 
130 	BString docString;
131 	BString appString;
132 	BString folderString;
133 
134 	docString << docCount;
135 	appString << appCount;
136 	folderString << folderCount;
137 
138 	fMenuRecentDocumentCount->SetText(docString.String());
139 	fMenuRecentApplicationCount->SetText(appString.String());
140 	fMenuRecentFolderCount->SetText(folderString.String());
141 
142 	// Applications settings
143 	fAppsSort->SetValue(fSettings.sortRunningApps);
144 	fAppsSortTrackerFirst->SetValue(fSettings.trackerAlwaysFirst);
145 	fAppsShowExpanders->SetValue(fSettings.superExpando);
146 	fAppsExpandNew->SetValue(fSettings.expandNewTeams);
147 	fAppsHideLabels->SetValue(fSettings.hideLabels);
148 	fAppsIconSizeSlider->SetValue(fSettings.iconSize
149 		/ kIconSizeInterval);
150 
151 	// Window settings
152 	fWindowAlwaysOnTop->SetValue(fSettings.alwaysOnTop);
153 	fWindowAutoRaise->SetValue(fSettings.autoRaise);
154 	fWindowAutoHide->SetValue(fSettings.autoHide);
155 
156 	_EnableDisableDependentItems();
157 
158 	// Targets
159 	fAppsSort->SetTarget(be_app);
160 	fAppsSortTrackerFirst->SetTarget(be_app);
161 	fAppsShowExpanders->SetTarget(be_app);
162 	fAppsExpandNew->SetTarget(be_app);
163 	fAppsHideLabels->SetTarget(be_app);
164 	fAppsIconSizeSlider->SetTarget(be_app);
165 
166 	fWindowAlwaysOnTop->SetTarget(be_app);
167 	fWindowAutoRaise->SetTarget(be_app);
168 	fWindowAutoHide->SetTarget(be_app);
169 
170 	// Applications
171 	BBox* appsSettingsBox = new BBox("applications");
172 	appsSettingsBox->SetLabel(B_TRANSLATE("Applications"));
173 	appsSettingsBox->AddChild(BLayoutBuilder::Group<>()
174 		.AddGroup(B_VERTICAL, 0)
175 			.Add(fAppsSort)
176 			.Add(fAppsSortTrackerFirst)
177 			.Add(fAppsShowExpanders)
178 			.AddGroup(B_HORIZONTAL, 0)
179 				.SetInsets(kIndentSpacing, 0, 0, 0)
180 				.Add(fAppsExpandNew)
181 				.End()
182 			.Add(fAppsHideLabels)
183 			.AddGroup(B_HORIZONTAL, 0)
184 				.SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
185 				.Add(fAppsIconSizeSlider)
186 				.End()
187 			.AddGlue()
188 			.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
189 				B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
190 			.End()
191 		.View());
192 
193 	// Recent items
194 	BBox* recentItemsBox = new BBox("recent items");
195 	recentItemsBox->SetLabel(B_TRANSLATE("Recent items"));
196 	recentItemsBox->AddChild(BLayoutBuilder::Group<>()
197 		.AddGroup(B_VERTICAL, 0)
198 			.AddGroup(B_HORIZONTAL, 0)
199 				.AddGroup(B_VERTICAL, 0)
200 					.Add(fMenuRecentDocuments)
201 					.Add(fMenuRecentFolders)
202 					.Add(fMenuRecentApplications)
203 					.End()
204 				.AddGroup(B_VERTICAL, 0)
205 					.Add(fMenuRecentDocumentCount)
206 					.Add(fMenuRecentFolderCount)
207 					.Add(fMenuRecentApplicationCount)
208 					.End()
209 				.End()
210 				//.Add(new BButton(B_TRANSLATE("Open in Tracker" B_UTF8_ELLIPSIS),
211 				//	new BMessage(kOpenInTracker)))
212 			.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
213 				B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
214 			.End()
215 		.View());
216 
217 	// Window
218 	BBox* windowSettingsBox = new BBox("window");
219 	windowSettingsBox->SetLabel(B_TRANSLATE("Window"));
220 	windowSettingsBox->AddChild(BLayoutBuilder::Group<>()
221 		.AddGroup(B_VERTICAL, 0)
222 			.Add(fWindowAlwaysOnTop)
223 			.Add(fWindowAutoRaise)
224 			.Add(fWindowAutoHide)
225 			.AddGlue()
226 			.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
227 				B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
228 			.End()
229 		.View());
230 
231 	// Action Buttons
232 	fDefaultsButton = new BButton(B_TRANSLATE("Defaults"),
233 		new BMessage(kDefaults));
234 	fRevertButton = new BButton(B_TRANSLATE("Revert"),
235 		new BMessage(kRevert));
236 
237 	// Layout
238 	BLayoutBuilder::Group<>(this)
239 		.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
240 			.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
241 				.Add(appsSettingsBox)
242 				.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
243 					.Add(recentItemsBox)
244 					.Add(windowSettingsBox)
245 				.End()
246 			.End()
247 			.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
248 				.Add(fDefaultsButton)
249 				.Add(fRevertButton)
250 				.AddGlue()
251 				.End()
252 			.SetInsets(B_USE_DEFAULT_SPACING)
253 			.End();
254 
255 	CenterOnScreen();
256 }
257 
258 
259 PreferencesWindow::~PreferencesWindow()
260 {
261 	_UpdateRecentCounts();
262 }
263 
264 
265 void
266 PreferencesWindow::MessageReceived(BMessage* message)
267 {
268 	switch (message->what) {
269 		case kOpenInTracker:
270 			OpenWithTracker(B_USER_DESKBAR_DIRECTORY);
271 			break;
272 
273 		case kUpdatePreferences:
274 			_EnableDisableDependentItems();
275 			_UpdateButtons();
276 			break;
277 
278 		case kUpdateRecentCounts:
279 			_UpdateRecentCounts();
280 			_UpdateButtons();
281 			break;
282 
283 		case kStateChanged:
284 			_EnableDisableDependentItems();
285 			break;
286 
287 		case kRevert:
288 			_UpdatePreferences(&fSettings);
289 			break;
290 
291 		case kDefaults:
292 			_UpdatePreferences(
293 				static_cast<TBarApp*>(be_app)->DefaultSettings());
294 			break;
295 
296 		default:
297 			BWindow::MessageReceived(message);
298 			break;
299 	}
300 }
301 
302 
303 bool
304 PreferencesWindow::QuitRequested()
305 {
306 	be_app->PostMessage(kConfigQuit);
307 
308 	return false;
309 }
310 
311 
312 void
313 PreferencesWindow::Show()
314 {
315 	if (IsHidden())
316 		SetWorkspaces(B_CURRENT_WORKSPACE);
317 
318 	_UpdateButtons();
319 
320 	BWindow::Show();
321 }
322 
323 
324 //	#pragma mark - private methods
325 
326 
327 void
328 PreferencesWindow::_EnableDisableDependentItems()
329 {
330 	TBarApp* barApp = static_cast<TBarApp*>(be_app);
331 	if (barApp->BarView()->Vertical()
332 		&& barApp->BarView()->ExpandoState()) {
333 		fAppsShowExpanders->SetEnabled(true);
334 		fAppsExpandNew->SetEnabled(fAppsShowExpanders->Value());
335 	} else {
336 		fAppsShowExpanders->SetEnabled(false);
337 		fAppsExpandNew->SetEnabled(false);
338 	}
339 
340 	fMenuRecentDocumentCount->SetEnabled(
341 		fMenuRecentDocuments->Value() != B_CONTROL_OFF);
342 	fMenuRecentFolderCount->SetEnabled(
343 		fMenuRecentFolders->Value() != B_CONTROL_OFF);
344 	fMenuRecentApplicationCount->SetEnabled(
345 		fMenuRecentApplications->Value() != B_CONTROL_OFF);
346 
347 	fWindowAutoRaise->SetEnabled(
348 		fWindowAlwaysOnTop->Value() == B_CONTROL_OFF);
349 }
350 
351 
352 bool
353 PreferencesWindow::_IsDefaultable()
354 {
355 	desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
356 	desk_settings* defaults = static_cast<TBarApp*>(be_app)->DefaultSettings();
357 
358 	return defaults->sortRunningApps != settings->sortRunningApps
359 		|| defaults->trackerAlwaysFirst != settings->trackerAlwaysFirst
360 		|| defaults->superExpando != settings->superExpando
361 		|| defaults->expandNewTeams != settings->expandNewTeams
362 		|| defaults->hideLabels != settings->hideLabels
363 		|| defaults->iconSize != settings->iconSize
364 		|| defaults->recentAppsEnabled != settings->recentAppsEnabled
365 		|| defaults->recentDocsEnabled != settings->recentDocsEnabled
366 		|| defaults->recentFoldersEnabled
367 			!= settings->recentFoldersEnabled
368 		|| defaults->recentAppsCount != settings->recentAppsCount
369 		|| defaults->recentDocsCount != settings->recentDocsCount
370 		|| defaults->recentFoldersCount != settings->recentFoldersCount
371 		|| defaults->alwaysOnTop != settings->alwaysOnTop
372 		|| defaults->autoRaise != settings->autoRaise
373 		|| defaults->autoHide != settings->autoHide;
374 }
375 
376 
377 bool
378 PreferencesWindow::_IsRevertable()
379 {
380 	desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
381 
382 	return fSettings.sortRunningApps != settings->sortRunningApps
383 		|| fSettings.trackerAlwaysFirst != settings->trackerAlwaysFirst
384 		|| fSettings.superExpando != settings->superExpando
385 		|| fSettings.expandNewTeams != settings->expandNewTeams
386 		|| fSettings.hideLabels != settings->hideLabels
387 		|| fSettings.iconSize != settings->iconSize
388 		|| fSettings.recentAppsEnabled != settings->recentAppsEnabled
389 		|| fSettings.recentDocsEnabled != settings->recentDocsEnabled
390 		|| fSettings.recentFoldersEnabled
391 			!= settings->recentFoldersEnabled
392 		|| fSettings.recentAppsCount != settings->recentAppsCount
393 		|| fSettings.recentDocsCount != settings->recentDocsCount
394 		|| fSettings.recentFoldersCount != settings->recentFoldersCount
395 		|| fSettings.alwaysOnTop != settings->alwaysOnTop
396 		|| fSettings.autoRaise != settings->autoRaise
397 		|| fSettings.autoHide != settings->autoHide;
398 }
399 
400 
401 void
402 PreferencesWindow::_UpdateButtons()
403 {
404 	fDefaultsButton->SetEnabled(_IsDefaultable());
405 	fRevertButton->SetEnabled(_IsRevertable());
406 }
407 
408 
409 void
410 PreferencesWindow::_UpdatePreferences(desk_settings* settings)
411 {
412 	desk_settings* current = static_cast<TBarApp*>(be_app)->Settings();
413 	bool updateRecentCounts = false;
414 
415 	if (current->sortRunningApps != settings->sortRunningApps) {
416 		fAppsSort->SetValue(settings->sortRunningApps);
417 		fAppsSort->Invoke();
418 	}
419 	if (current->trackerAlwaysFirst != settings->trackerAlwaysFirst) {
420 		fAppsSortTrackerFirst->SetValue(settings->trackerAlwaysFirst);
421 		fAppsSortTrackerFirst->Invoke();
422 	}
423 	if (current->superExpando != settings->superExpando) {
424 		fAppsShowExpanders->SetValue(settings->superExpando);
425 		fAppsShowExpanders->Invoke();
426 	}
427 	if (current->expandNewTeams != settings->expandNewTeams) {
428 		fAppsExpandNew->SetValue(settings->expandNewTeams);
429 		fAppsExpandNew->Invoke();
430 	}
431 	if (current->hideLabels != settings->hideLabels) {
432 		fAppsHideLabels->SetValue(settings->hideLabels);
433 		fAppsHideLabels->Invoke();
434 	}
435 	if (current->iconSize != settings->iconSize) {
436 		fAppsIconSizeSlider->SetValue(settings->iconSize / kIconSizeInterval);
437 		fAppsIconSizeSlider->Invoke();
438 	}
439 	if (current->recentDocsEnabled != settings->recentDocsEnabled) {
440 		fMenuRecentDocuments->SetValue(settings->recentDocsEnabled
441 			? B_CONTROL_ON : B_CONTROL_OFF);
442 		updateRecentCounts = true;
443 	}
444 	if (current->recentFoldersEnabled != settings->recentFoldersEnabled) {
445 		fMenuRecentFolders->SetValue(settings->recentFoldersEnabled
446 			? B_CONTROL_ON : B_CONTROL_OFF);
447 		updateRecentCounts = true;
448 	}
449 	if (current->recentAppsEnabled != settings->recentAppsEnabled) {
450 		fMenuRecentApplications->SetValue(settings->recentAppsEnabled
451 			? B_CONTROL_ON : B_CONTROL_OFF);
452 		updateRecentCounts = true;
453 	}
454 	if (current->recentDocsCount != settings->recentDocsCount) {
455 		BString docString;
456 		docString << settings->recentDocsCount;
457 		fMenuRecentDocumentCount->SetText(docString.String());
458 		updateRecentCounts = true;
459 	}
460 	if (current->recentFoldersCount != settings->recentFoldersCount) {
461 		BString folderString;
462 		folderString << settings->recentFoldersCount;
463 		fMenuRecentFolderCount->SetText(folderString.String());
464 		updateRecentCounts = true;
465 	}
466 	if (current->recentAppsCount != settings->recentAppsCount) {
467 		BString appString;
468 		appString << settings->recentAppsCount;
469 		fMenuRecentApplicationCount->SetText(appString.String());
470 		updateRecentCounts = true;
471 	}
472 	if (current->alwaysOnTop != settings->alwaysOnTop) {
473 		fWindowAlwaysOnTop->SetValue(settings->alwaysOnTop);
474 		fWindowAlwaysOnTop->Invoke();
475 	}
476 	if (current->autoRaise != settings->autoRaise) {
477 		fWindowAutoRaise->SetValue(settings->autoRaise);
478 		fWindowAutoRaise->Invoke();
479 	}
480 	if (current->autoHide != settings->autoHide) {
481 		fWindowAutoHide->SetValue(settings->autoHide);
482 		fWindowAutoHide->Invoke();
483 	}
484 
485 	if (updateRecentCounts)
486 		_UpdateRecentCounts();
487 }
488 
489 
490 void
491 PreferencesWindow::_UpdateRecentCounts()
492 {
493 	BMessage message(kUpdateRecentCounts);
494 
495 	int32 docCount = atoi(fMenuRecentDocumentCount->Text());
496 	int32 appCount = atoi(fMenuRecentApplicationCount->Text());
497 	int32 folderCount = atoi(fMenuRecentFolderCount->Text());
498 
499 	message.AddInt32("documents", max_c(0, docCount));
500 	message.AddInt32("applications", max_c(0, appCount));
501 	message.AddInt32("folders", max_c(0, folderCount));
502 
503 	message.AddBool("documentsEnabled", fMenuRecentDocuments->Value());
504 	message.AddBool("applicationsEnabled", fMenuRecentApplications->Value());
505 	message.AddBool("foldersEnabled", fMenuRecentFolders->Value());
506 
507 	be_app->PostMessage(&message);
508 
509 	_EnableDisableDependentItems();
510 }
511