1 /* 2 * Copyright 2003-2007, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Phipps 7 * Jérôme Duval, jerome.duval@free.fr 8 * Axel Dörfler, axeld@pinc-software.de 9 */ 10 11 12 #include "PreviewView.h" 13 #include "ScreenCornerSelector.h" 14 #include "ScreenSaverItem.h" 15 #include "ScreenSaverWindow.h" 16 17 #include <Application.h> 18 #include <Box.h> 19 #include <Button.h> 20 #include <Directory.h> 21 #include <Entry.h> 22 #include <File.h> 23 #include <FindDirectory.h> 24 #include <Font.h> 25 #include <ListView.h> 26 #include <Path.h> 27 #include <Roster.h> 28 #include <Screen.h> 29 #include <ScreenSaver.h> 30 #include <ScrollView.h> 31 #include <Slider.h> 32 #include <StringView.h> 33 #include <TabView.h> 34 35 #include <stdio.h> 36 37 38 const uint32 kPreviewMonitorGap = 16; 39 const uint32 kMinSettingsWidth = 230; 40 const uint32 kMinSettingsHeight = 120; 41 42 const int32 kMsgSaverSelected = 'SSEL'; 43 const int32 kMsgTestSaver = 'TEST'; 44 const int32 kMsgAddSaver = 'ADD '; 45 const int32 kMsgPasswordCheckBox = 'PWCB'; 46 const int32 kMsgRunSliderChanged = 'RSch'; 47 const int32 kMsgRunSliderUpdate = 'RSup'; 48 const int32 kMsgPasswordSliderChanged = 'PWch'; 49 const int32 kMsgPasswordSliderUpdate = 'PWup'; 50 const int32 kMsgChangePassword = 'PWBT'; 51 const int32 kMsgEnableScreenSaverBox = 'ESCH'; 52 53 const int32 kMsgTurnOffCheckBox = 'TUOF'; 54 const int32 kMsgTurnOffSliderChanged = 'TUch'; 55 const int32 kMsgTurnOffSliderUpdate = 'TUup'; 56 57 const int32 kMsgFadeCornerChanged = 'fdcc'; 58 const int32 kMsgNeverFadeCornerChanged = 'nfcc'; 59 60 61 class TimeSlider : public BSlider { 62 public: 63 TimeSlider(BRect frame, const char* name, uint32 changedMessage, 64 uint32 updateMessage); 65 virtual ~TimeSlider(); 66 67 virtual void AttachedToWindow(); 68 virtual void SetValue(int32 value); 69 70 void SetTime(bigtime_t useconds); 71 bigtime_t Time(); 72 73 private: 74 void _TimeToString(bigtime_t useconds, BString& string); 75 }; 76 77 class FadeView : public BView { 78 public: 79 FadeView(BRect frame, const char* name, ScreenSaverSettings& settings); 80 81 virtual void AttachedToWindow(); 82 }; 83 84 class ModulesView : public BView { 85 public: 86 ModulesView(BRect frame, const char* name, ScreenSaverSettings& settings); 87 virtual ~ModulesView(); 88 89 virtual void DetachedFromWindow(); 90 virtual void AttachedToWindow(); 91 virtual void AllAttached(); 92 virtual void MessageReceived(BMessage* message); 93 94 void PopulateScreenSaverList(); 95 void SaveState(); 96 97 private: 98 static int _CompareScreenSaverItems(const void* left, const void* right); 99 BScreenSaver* _ScreenSaver(); 100 void _CloseSaver(); 101 void _OpenSaver(); 102 103 BFilePanel* fFilePanel; 104 BListView* fListView; 105 BButton* fTestButton; 106 BButton* fAddButton; 107 108 ScreenSaverSettings& fSettings; 109 ScreenSaverRunner* fSaverRunner; 110 BString fCurrentName; 111 112 BBox* fSettingsBox; 113 BView* fSettingsView; 114 115 PreviewView* fPreviewView; 116 }; 117 118 static const int32 kTimeInUnits[] = { 119 30, 60, 90, 120 120, 150, 180, 121 240, 300, 360, 122 420, 480, 540, 123 600, 900, 1200, 124 1500, 1800, 2400, 125 3000, 3600, 5400, 126 7200, 9000, 10800, 127 14400, 18000 128 }; 129 static const int32 kTimeUnitCount = sizeof(kTimeInUnits) / sizeof(kTimeInUnits[0]); 130 131 132 TimeSlider::TimeSlider(BRect frame, const char* name, uint32 changedMessage, 133 uint32 updateMessage) 134 : BSlider(frame, name, "30 seconds", new BMessage(changedMessage), 135 0, kTimeUnitCount - 1, B_TRIANGLE_THUMB, B_FOLLOW_LEFT_RIGHT) 136 { 137 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 138 SetModificationMessage(new BMessage(updateMessage)); 139 SetBarThickness(10); 140 } 141 142 143 TimeSlider::~TimeSlider() 144 { 145 } 146 147 148 void 149 TimeSlider::AttachedToWindow() 150 { 151 BSlider::AttachedToWindow(); 152 SetTarget(Window()); 153 } 154 155 156 void 157 TimeSlider::SetValue(int32 value) 158 { 159 int32 oldValue = Value(); 160 BSlider::SetValue(value); 161 162 if (oldValue != Value()) { 163 BString label; 164 _TimeToString(kTimeInUnits[Value()] * 1000000LL, label); 165 SetLabel(label.String()); 166 } 167 } 168 169 170 void 171 TimeSlider::SetTime(bigtime_t useconds) 172 { 173 for (int t = 0; t < kTimeUnitCount; t++) { 174 if (kTimeInUnits[t] * 1000000LL == useconds) { 175 SetValue(t); 176 break; 177 } 178 } 179 } 180 181 182 bigtime_t 183 TimeSlider::Time() 184 { 185 return 1000000LL * kTimeInUnits[Value()]; 186 } 187 188 189 void 190 TimeSlider::_TimeToString(bigtime_t useconds, BString& string) 191 { 192 useconds /= 1000000LL; 193 // convert to seconds 194 195 string = ""; 196 197 // hours 198 uint32 hours = useconds / 3600; 199 if (hours != 0) 200 string << hours << " hours"; 201 202 useconds %= 3600; 203 204 // minutes 205 uint32 minutes = useconds / 60; 206 if (hours != 0) 207 string << " "; 208 if (minutes != 0) 209 string << minutes << " minutes"; 210 211 useconds %= 60; 212 213 // seconds 214 uint32 seconds = useconds; 215 if (hours != 0 || minutes != 0) 216 string << " "; 217 if (seconds != 0) 218 string << seconds << " seconds"; 219 } 220 221 222 // #pragma mark - 223 224 225 FadeView::FadeView(BRect rect, const char* name, ScreenSaverSettings& settings) 226 : BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW) 227 { 228 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 229 } 230 231 232 void 233 FadeView::AttachedToWindow() 234 { 235 if (Parent() != NULL) { 236 // We adopt the size of our parent view (in case the window 237 // was resized during our absence (BTabView...) 238 ResizeTo(Parent()->Bounds().Width(), Parent()->Bounds().Height()); 239 } 240 } 241 242 243 // #pragma mark - 244 245 246 ModulesView::ModulesView(BRect rect, const char* name, ScreenSaverSettings& settings) 247 : BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW), 248 fSettings(settings), 249 fSaverRunner(NULL), 250 fSettingsView(NULL) 251 { 252 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 253 254 fTestButton = new BButton(rect, "TestButton", "Test", new BMessage(kMsgTestSaver), 255 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 256 float width, height; 257 fTestButton->GetPreferredSize(&width, &height); 258 fTestButton->ResizeTo(width + 16, height); 259 fTestButton->MoveTo(8, rect.bottom - 8 - height); 260 AddChild(fTestButton); 261 262 rect = fTestButton->Frame(); 263 rect.OffsetBy(fTestButton->Bounds().Width() + 8, 0); 264 fAddButton = new BButton(rect, "AddButton", "Add" B_UTF8_ELLIPSIS, 265 new BMessage(kMsgAddSaver), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 266 AddChild(fAddButton); 267 268 rect = Bounds().InsetByCopy(8 + kPreviewMonitorGap, 12); 269 rect.right = fAddButton->Frame().right - kPreviewMonitorGap; 270 rect.bottom = rect.top + 3 * rect.Width() / 4; 271 // 4:3 monitor 272 273 fPreviewView = new PreviewView(rect, "preview"); 274 AddChild(fPreviewView); 275 276 rect.left = 8; 277 rect.right -= B_V_SCROLL_BAR_WIDTH + 2 - kPreviewMonitorGap; 278 // scroll view border 279 rect.top = rect.bottom + 14; 280 rect.bottom = fTestButton->Frame().top - 10; 281 fListView = new BListView(rect, "SaversListView", B_SINGLE_SELECTION_LIST, 282 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM); 283 fListView->SetSelectionMessage(new BMessage(kMsgSaverSelected)); 284 AddChild(new BScrollView("scroll_list", fListView, 285 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 0, false, true)); 286 287 rect = Bounds().InsetByCopy(8, 8); 288 rect.left = fAddButton->Frame().right + 8; 289 AddChild(fSettingsBox = new BBox(rect, "SettingsBox", B_FOLLOW_ALL, B_WILL_DRAW)); 290 fSettingsBox->SetLabel("Module settings"); 291 292 PopulateScreenSaverList(); 293 fFilePanel = new BFilePanel(); 294 } 295 296 297 ModulesView::~ModulesView() 298 { 299 delete fFilePanel; 300 } 301 302 303 void 304 ModulesView::DetachedFromWindow() 305 { 306 _CloseSaver(); 307 } 308 309 310 void 311 ModulesView::AttachedToWindow() 312 { 313 if (Parent() != NULL) { 314 // We adopt the size of our parent view (in case the window 315 // was resized during our absence (BTabView...) 316 ResizeTo(Parent()->Bounds().Width(), Parent()->Bounds().Height()); 317 } 318 319 _OpenSaver(); 320 321 fListView->SetTarget(this); 322 fTestButton->SetTarget(this); 323 fAddButton->SetTarget(this); 324 } 325 326 327 void 328 ModulesView::AllAttached() 329 { 330 // This only works after the view has been attached 331 fListView->ScrollToSelection(); 332 } 333 334 335 void 336 ModulesView::MessageReceived(BMessage* message) 337 { 338 switch (message->what) { 339 case kMsgSaverSelected: 340 { 341 int selection = fListView->CurrentSelection(); 342 if (selection < 0) 343 break; 344 345 ScreenSaverItem* item = (ScreenSaverItem *)fListView->ItemAt(selection); 346 if (item == NULL) 347 break; 348 349 if (!strcmp(item->Text(), "Blackness")) 350 fSettings.SetModuleName(""); 351 else 352 fSettings.SetModuleName(item->Text()); 353 354 SaveState(); 355 _CloseSaver(); 356 _OpenSaver(); 357 break; 358 } 359 360 case kMsgTestSaver: 361 SaveState(); 362 fSettings.Save(); 363 364 be_roster->Launch(SCREEN_BLANKER_SIG, &fSettings.Message()); 365 break; 366 367 case kMsgAddSaver: 368 fFilePanel->Show(); 369 break; 370 371 default: 372 BView::MessageReceived(message); 373 } 374 } 375 376 377 void 378 ModulesView::SaveState() 379 { 380 BScreenSaver* saver = _ScreenSaver(); 381 if (saver == NULL) 382 return; 383 384 BMessage state; 385 if (saver->SaveState(&state) == B_OK) 386 fSettings.SetModuleState(fCurrentName.String(), &state); 387 } 388 389 390 void 391 ModulesView::PopulateScreenSaverList() 392 { 393 fListView->DeselectAll(); 394 while (ScreenSaverItem* item = (ScreenSaverItem *)fListView->RemoveItem((int32)0)) { 395 delete item; 396 } 397 398 // Blackness is a built-in screen saver 399 fListView->AddItem(new ScreenSaverItem("Blackness", "")); 400 401 // Iterate over add-on directories, and add their files to the list view 402 403 directory_which which[] = {B_BEOS_ADDONS_DIRECTORY, B_USER_ADDONS_DIRECTORY}; 404 ScreenSaverItem* selectItem = NULL; 405 406 for (uint32 i = 0; i < sizeof(which) / sizeof(which[0]); i++) { 407 BPath basePath; 408 find_directory(which[i], &basePath); 409 basePath.Append("Screen Savers", true); 410 411 BDirectory dir(basePath.Path()); 412 BEntry entry; 413 while (dir.GetNextEntry(&entry, true) == B_OK) { 414 char name[B_FILE_NAME_LENGTH]; 415 if (entry.GetName(name) != B_OK) 416 continue; 417 418 BPath path = basePath; 419 path.Append(name); 420 421 ScreenSaverItem* item = new ScreenSaverItem(name, path.Path()); 422 fListView->AddItem(item); 423 424 if (!strcmp(fSettings.ModuleName(), item->Text()) 425 || (!strcmp(fSettings.ModuleName(), "") 426 && !strcmp(item->Text(), "Blackness"))) 427 selectItem = item; 428 } 429 } 430 431 fListView->SortItems(_CompareScreenSaverItems); 432 433 fListView->Select(fListView->IndexOf(selectItem)); 434 fListView->ScrollToSelection(); 435 } 436 437 438 //! sorting function for ScreenSaverItems 439 int 440 ModulesView::_CompareScreenSaverItems(const void* left, const void* right) 441 { 442 ScreenSaverItem* leftItem = *(ScreenSaverItem **)left; 443 ScreenSaverItem* rightItem = *(ScreenSaverItem **)right; 444 445 return strcasecmp(leftItem->Text(), rightItem->Text()); 446 } 447 448 449 BScreenSaver* 450 ModulesView::_ScreenSaver() 451 { 452 if (fSaverRunner != NULL) 453 return fSaverRunner->ScreenSaver(); 454 455 return NULL; 456 } 457 458 459 void 460 ModulesView::_CloseSaver() 461 { 462 // remove old screen saver preview & config 463 464 BScreenSaver* saver = _ScreenSaver(); 465 BView* view = fPreviewView->RemovePreview(); 466 if (fSettingsView != NULL) 467 fSettingsBox->RemoveChild(fSettingsView); 468 469 if (fSaverRunner != NULL) 470 fSaverRunner->Quit(); 471 if (saver != NULL) 472 saver->StopConfig(); 473 474 delete view; 475 delete fSettingsView; 476 delete fSaverRunner; 477 // the saver runner also unloads the add-on, so it must 478 // be deleted last 479 480 fSettingsView = NULL; 481 fSaverRunner = NULL; 482 } 483 484 485 void 486 ModulesView::_OpenSaver() 487 { 488 // create new screen saver preview & config 489 490 BView* view = fPreviewView->AddPreview(); 491 fCurrentName = fSettings.ModuleName(); 492 fSaverRunner = new ScreenSaverRunner(Window(), view, true, fSettings); 493 BScreenSaver* saver = _ScreenSaver(); 494 495 #ifdef __HAIKU__ 496 BRect rect = fSettingsBox->InnerFrame().InsetByCopy(4, 4); 497 #else 498 BRect rect = fSettingsBox->Bounds().InsetByCopy(4, 4); 499 rect.top += 14; 500 #endif 501 fSettingsView = new BView(rect, "SettingsView", B_FOLLOW_ALL, B_WILL_DRAW); 502 fSettingsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 503 fSettingsBox->AddChild(fSettingsView); 504 505 if (saver != NULL) { 506 fSaverRunner->Run(); 507 saver->StartConfig(fSettingsView); 508 } 509 510 if (fSettingsView->ChildAt(0) == NULL) { 511 // There are no settings at all, we add the module name here to 512 // let it look a bit better at least. 513 rect = BRect(15, 15, 20, 20); 514 BStringView* stringView = new BStringView(rect, "module", fSettings.ModuleName()[0] 515 ? fSettings.ModuleName() : "Blackness"); 516 stringView->SetFont(be_bold_font); 517 stringView->ResizeToPreferred(); 518 fSettingsView->AddChild(stringView); 519 520 rect.OffsetBy(0, stringView->Bounds().Height() + 4); 521 stringView = new BStringView(rect, "info", saver || !fSettings.ModuleName()[0] 522 ? "No options available" : "Could not load screen saver"); 523 stringView->ResizeToPreferred(); 524 fSettingsView->AddChild(stringView); 525 } 526 527 ScreenSaverWindow* window = dynamic_cast<ScreenSaverWindow*>(Window()); 528 if (window == NULL) 529 return; 530 531 // find the minimal size of the settings view 532 533 float right = 0, bottom = 0; 534 int32 i = 0; 535 while ((view = fSettingsView->ChildAt(i++)) != NULL) { 536 // very simple heuristic... 537 float viewRight = view->Frame().right; 538 if ((view->ResizingMode() & _rule_(0, 0xf, 0, 0xf)) == B_FOLLOW_LEFT_RIGHT) { 539 float width, height; 540 view->GetPreferredSize(&width, &height); 541 viewRight = view->Frame().left + width / 2; 542 } else if ((view->ResizingMode() & _rule_(0, 0xf, 0, 0xf)) == B_FOLLOW_RIGHT) 543 viewRight = 8 + view->Frame().Width(); 544 545 float viewBottom = view->Frame().bottom; 546 if ((view->ResizingMode() & _rule_(0xf, 0, 0xf, 0)) == B_FOLLOW_TOP_BOTTOM) { 547 float width, height; 548 view->GetPreferredSize(&width, &height); 549 viewBottom = view->Frame().top + height; 550 } else if ((view->ResizingMode() & _rule_(0xf, 0, 0xf, 0)) == B_FOLLOW_BOTTOM) 551 viewBottom = 8 + view->Frame().Height(); 552 553 if (viewRight > right) 554 right = viewRight; 555 if (viewBottom > bottom) 556 bottom = viewBottom; 557 } 558 559 if (right < kMinSettingsWidth) 560 right = kMinSettingsWidth; 561 if (bottom < kMinSettingsHeight) 562 bottom = kMinSettingsHeight; 563 564 BPoint leftTop = fSettingsView->LeftTop(); 565 fSettingsView->ConvertToScreen(&leftTop); 566 window->ConvertFromScreen(&leftTop); 567 window->SetMinimalSizeLimit(leftTop.x + right + 16, 568 leftTop.y + bottom + 16); 569 } 570 571 572 // #pragma mark - 573 574 575 ScreenSaverWindow::ScreenSaverWindow() 576 : BWindow(BRect(50, 50, 496, 375), "ScreenSaver", 577 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS /*| B_NOT_ZOOMABLE | B_NOT_RESIZABLE*/) 578 { 579 fSettings.Load(); 580 581 BRect rect = Bounds(); 582 fMinWidth = 430; 583 fMinHeight = 325; 584 585 // Create a background view 586 BView *background = new BView(rect, "background", B_FOLLOW_ALL, 0); 587 background->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 588 AddChild(background); 589 590 // Add the tab view to the background 591 rect.top += 4; 592 fTabView = new BTabView(rect, "tab_view"); 593 594 // Create the controls inside the tabs 595 rect = fTabView->ContainerView()->Bounds(); 596 _SetupFadeTab(rect); 597 fModulesView = new ModulesView(rect, "Modules", fSettings); 598 599 fTabView->AddTab(fFadeView); 600 fTabView->AddTab(fModulesView); 601 background->AddChild(fTabView); 602 603 // Create the password editing window 604 fPasswordWindow = new PasswordWindow(fSettings); 605 fPasswordWindow->Run(); 606 607 SetMinimalSizeLimit(fMinWidth, fMinHeight); 608 MoveTo(fSettings.WindowFrame().left, fSettings.WindowFrame().top); 609 ResizeTo(fSettings.WindowFrame().Width(), fSettings.WindowFrame().Height()); 610 611 fEnableCheckBox->SetValue(fSettings.TimeFlags() & ENABLE_SAVER ? B_CONTROL_ON : B_CONTROL_OFF); 612 fRunSlider->SetTime(fSettings.BlankTime()); 613 fTurnOffSlider->SetTime(fSettings.OffTime() + fSettings.BlankTime()); 614 fFadeNow->SetCorner(fSettings.BlankCorner()); 615 fFadeNever->SetCorner(fSettings.NeverBlankCorner()); 616 fPasswordCheckBox->SetValue(fSettings.LockEnable()); 617 fPasswordSlider->SetTime(fSettings.PasswordTime()); 618 619 fTabView->Select(fSettings.WindowTab()); 620 621 _UpdateTurnOffScreen(); 622 _UpdateStatus(); 623 } 624 625 626 ScreenSaverWindow::~ScreenSaverWindow() 627 { 628 } 629 630 631 //! Create the controls for the fade tab 632 void 633 ScreenSaverWindow::_SetupFadeTab(BRect rect) 634 { 635 fFadeView = new FadeView(rect, "Fade", fSettings); 636 637 float labelWidth = be_plain_font->StringWidth("Turn off screen") + 20.0f; 638 639 font_height fontHeight; 640 be_plain_font->GetHeight(&fontHeight); 641 float textHeight = ceilf(fontHeight.ascent + fontHeight.descent); 642 643 // taken from BRadioButton: 644 float radioButtonOffset = 2 * floorf(textHeight / 2 - 2) + floorf(textHeight / 2); 645 646 fEnableCheckBox = new BCheckBox(BRect(0, 0, 1, 1), "EnableCheckBox", 647 "Enable Screen Saver", new BMessage(kMsgEnableScreenSaverBox)); 648 fEnableCheckBox->ResizeToPreferred(); 649 650 rect.InsetBy(8, 8); 651 BBox* box = new BBox(rect, "EnableScreenSaverBox", B_FOLLOW_ALL); 652 box->SetLabel(fEnableCheckBox); 653 fFadeView->AddChild(box); 654 655 // Run Module 656 rect.left += radioButtonOffset; 657 rect.top = fEnableCheckBox->Bounds().bottom + 8.0f; 658 rect.right = box->Bounds().right - 8; 659 BStringView* stringView = new BStringView(rect, NULL, "Run module"); 660 stringView->ResizeToPreferred(); 661 box->AddChild(stringView); 662 663 rect.left += labelWidth; 664 fRunSlider = new TimeSlider(rect, "RunSlider", kMsgRunSliderChanged, 665 kMsgRunSliderUpdate); 666 float width, height; 667 fRunSlider->GetPreferredSize(&width, &height); 668 fRunSlider->ResizeTo(fRunSlider->Bounds().Width(), height); 669 box->AddChild(fRunSlider); 670 671 // Turn Off 672 rect.left = 8; 673 rect.OffsetBy(0, fRunSlider->Bounds().Height() + 4.0f); 674 fTurnOffCheckBox = new BCheckBox(rect, "TurnOffScreenCheckBox", 675 "Turn off screen", new BMessage(kMsgTurnOffCheckBox)); 676 fTurnOffCheckBox->ResizeToPreferred(); 677 box->AddChild(fTurnOffCheckBox); 678 679 rect.left += radioButtonOffset + labelWidth; 680 fTurnOffSlider = new TimeSlider(rect, "TurnOffSlider", 681 kMsgTurnOffSliderChanged, kMsgTurnOffSliderUpdate); 682 fTurnOffSlider->ResizeTo(fTurnOffSlider->Bounds().Width(), height); 683 box->AddChild(fTurnOffSlider); 684 685 // Password 686 rect.left = 8; 687 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 688 fPasswordCheckBox = new BCheckBox(rect, "PasswordCheckbox", 689 "Password lock", new BMessage(kMsgPasswordCheckBox)); 690 fPasswordCheckBox->ResizeToPreferred(); 691 box->AddChild(fPasswordCheckBox); 692 693 rect.left += radioButtonOffset + labelWidth; 694 fPasswordSlider = new TimeSlider(rect, "PasswordSlider", 695 kMsgPasswordSliderChanged, kMsgPasswordSliderUpdate); 696 fPasswordSlider->ResizeTo(fPasswordSlider->Bounds().Width(), height); 697 box->AddChild(fPasswordSlider); 698 699 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 700 rect.left = rect.right; 701 fPasswordButton = new BButton(rect, "PasswordButton", "Password" B_UTF8_ELLIPSIS, 702 new BMessage(kMsgChangePassword), B_FOLLOW_TOP | B_FOLLOW_RIGHT); 703 fPasswordButton->ResizeToPreferred(); 704 fPasswordButton->MoveBy(-fPasswordButton->Bounds().Width(), 0); 705 box->AddChild(fPasswordButton); 706 707 // Bottom 708 709 float monitorHeight = 10 + textHeight * 3; 710 float monitorWidth = monitorHeight * 4 / 3; 711 rect.left = 15; 712 rect.top = box->Bounds().Height() - 15 - monitorHeight; 713 rect.right = rect.left + monitorWidth; 714 rect.bottom = rect.top + monitorHeight; 715 box->AddChild(fFadeNow = new ScreenCornerSelector(rect, "FadeNow", 716 new BMessage(kMsgFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 717 718 rect.OffsetBy(monitorWidth + 10, 0); 719 stringView = new BStringView(rect, NULL, "Fade now when", 720 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 721 stringView->ResizeToPreferred(); 722 float maxWidth = stringView->Bounds().Width(); 723 box->AddChild(stringView); 724 725 rect.OffsetBy(0, stringView->Bounds().Height()); 726 stringView = new BStringView(rect, NULL, "mouse is here", 727 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 728 stringView->ResizeToPreferred(); 729 if (maxWidth < stringView->Bounds().Width()) 730 maxWidth = stringView->Bounds().Width(); 731 box->AddChild(stringView); 732 733 rect.left += maxWidth + 20; 734 rect.top = box->Bounds().Height() - 15 - monitorHeight; 735 rect.right = rect.left + monitorWidth; 736 rect.bottom = rect.top + monitorHeight; 737 box->AddChild(fFadeNever = new ScreenCornerSelector(rect, "FadeNever", 738 new BMessage(kMsgNeverFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 739 740 rect.OffsetBy(monitorWidth + 10, 0); 741 stringView = new BStringView(rect, NULL,"Don't fade when", 742 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 743 stringView->ResizeToPreferred(); 744 if (maxWidth < stringView->Bounds().Width()) 745 maxWidth = stringView->Bounds().Width(); 746 box->AddChild(stringView); 747 748 rect.OffsetBy(0, stringView->Bounds().Height()); 749 stringView = new BStringView(rect, NULL, "mouse is here", 750 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 751 stringView->ResizeToPreferred(); 752 if (maxWidth < stringView->Bounds().Width()) 753 maxWidth = stringView->Bounds().Width(); 754 box->AddChild(stringView); 755 756 float size = rect.left + maxWidth + 40; 757 if (fMinWidth < size) 758 fMinWidth = size; 759 size = fPasswordButton->Frame().bottom + box->Frame().top 760 + monitorHeight + 40 + textHeight * 2; 761 if (fMinHeight < size) 762 fMinHeight = size; 763 } 764 765 766 void 767 ScreenSaverWindow::_UpdateTurnOffScreen() 768 { 769 bool enabled = (fSettings.TimeFlags() & ENABLE_DPMS_MASK) != 0; 770 771 BScreen screen(this); 772 uint32 dpmsCapabilities = screen.DPMSCapabilites(); 773 774 fTurnOffScreenFlags = 0; 775 if (dpmsCapabilities & B_DPMS_OFF) 776 fTurnOffScreenFlags |= ENABLE_DPMS_OFF; 777 if (dpmsCapabilities & B_DPMS_STAND_BY) 778 fTurnOffScreenFlags |= ENABLE_DPMS_STAND_BY; 779 if (dpmsCapabilities & B_DPMS_SUSPEND) 780 fTurnOffScreenFlags |= ENABLE_DPMS_SUSPEND; 781 782 fTurnOffCheckBox->SetValue(enabled && fTurnOffScreenFlags != 0 783 ? B_CONTROL_ON : B_CONTROL_OFF); 784 } 785 786 787 void 788 ScreenSaverWindow::_UpdateStatus() 789 { 790 DisableUpdates(); 791 792 bool enabled = fEnableCheckBox->Value() == B_CONTROL_ON; 793 fPasswordCheckBox->SetEnabled(enabled); 794 fTurnOffCheckBox->SetEnabled(enabled && fTurnOffScreenFlags != 0); 795 fRunSlider->SetEnabled(enabled); 796 fTurnOffSlider->SetEnabled(enabled && fTurnOffCheckBox->Value()); 797 fPasswordSlider->SetEnabled(enabled && fPasswordCheckBox->Value()); 798 fPasswordButton->SetEnabled(enabled && fPasswordCheckBox->Value()); 799 800 EnableUpdates(); 801 802 // Update the saved preferences 803 fSettings.SetWindowFrame(Frame()); 804 fSettings.SetWindowTab(fTabView->Selection()); 805 fSettings.SetTimeFlags((enabled ? ENABLE_SAVER : 0) 806 | (fTurnOffCheckBox->Value() ? fTurnOffScreenFlags : 0)); 807 fSettings.SetBlankTime(fRunSlider->Time()); 808 bigtime_t offTime = fTurnOffSlider->Time() - fSettings.BlankTime(); 809 fSettings.SetOffTime(offTime); 810 fSettings.SetSuspendTime(offTime); 811 fSettings.SetStandByTime(offTime); 812 fSettings.SetBlankCorner(fFadeNow->Corner()); 813 fSettings.SetNeverBlankCorner(fFadeNever->Corner()); 814 fSettings.SetLockEnable(fPasswordCheckBox->Value()); 815 fSettings.SetPasswordTime(fPasswordSlider->Time()); 816 817 // TODO - Tell the password window to update its stuff 818 } 819 820 821 void 822 ScreenSaverWindow::SetMinimalSizeLimit(float width, float height) 823 { 824 if (width < fMinWidth) 825 width = fMinWidth; 826 if (height < fMinHeight) 827 height = fMinHeight; 828 829 SetSizeLimits(width, 32767, height, 32767); 830 } 831 832 833 void 834 ScreenSaverWindow::MessageReceived(BMessage *msg) 835 { 836 // "Fade" tab, slider updates 837 838 switch (msg->what) { 839 case kMsgRunSliderChanged: 840 case kMsgRunSliderUpdate: 841 if (fRunSlider->Value() > fTurnOffSlider->Value()) 842 fTurnOffSlider->SetValue(fRunSlider->Value()); 843 844 if (fRunSlider->Value() > fPasswordSlider->Value()) 845 fPasswordSlider->SetValue(fRunSlider->Value()); 846 break; 847 848 case kMsgTurnOffSliderChanged: 849 case kMsgTurnOffSliderUpdate: 850 if (fRunSlider->Value() > fTurnOffSlider->Value()) 851 fRunSlider->SetValue(fTurnOffSlider->Value()); 852 break; 853 854 case kMsgPasswordSliderChanged: 855 case kMsgPasswordSliderUpdate: 856 if (fPasswordSlider->Value() < fRunSlider->Value()) 857 fRunSlider->SetValue(fPasswordSlider->Value()); 858 break; 859 } 860 861 switch (msg->what) { 862 // "Fade" tab 863 864 case kMsgTurnOffCheckBox: 865 fTurnOffSlider->SetEnabled(fTurnOffCheckBox->Value() == B_CONTROL_ON); 866 break; 867 868 case kMsgRunSliderChanged: 869 case kMsgTurnOffSliderChanged: 870 case kMsgPasswordSliderChanged: 871 case kMsgPasswordCheckBox: 872 case kMsgEnableScreenSaverBox: 873 case kMsgFadeCornerChanged: 874 case kMsgNeverFadeCornerChanged: 875 _UpdateStatus(); 876 fSettings.Save(); 877 break; 878 879 case kMsgChangePassword: 880 fPasswordWindow->Show(); 881 break; 882 883 // "Modules" tab 884 885 case kMsgUpdateList: 886 fModulesView->PopulateScreenSaverList(); 887 break; 888 889 default: 890 BWindow::MessageReceived(msg); 891 break; 892 } 893 } 894 895 896 void 897 ScreenSaverWindow::ScreenChanged(BRect frame, color_space colorSpace) 898 { 899 _UpdateTurnOffScreen(); 900 } 901 902 903 bool 904 ScreenSaverWindow::QuitRequested() 905 { 906 _UpdateStatus(); 907 fModulesView->SaveState(); 908 fSettings.Save(); 909 910 be_app->PostMessage(B_QUIT_REQUESTED); 911 return true; 912 } 913 914