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