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