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