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 _CloseSaver(); 355 _OpenSaver(); 356 break; 357 } 358 359 case kMsgTestSaver: 360 SaveState(); 361 fSettings.Save(); 362 363 be_roster->Launch(SCREEN_BLANKER_SIG, &fSettings.Message()); 364 break; 365 366 case kMsgAddSaver: 367 fFilePanel->Show(); 368 break; 369 370 default: 371 BView::MessageReceived(message); 372 } 373 } 374 375 376 void 377 ModulesView::SaveState() 378 { 379 BScreenSaver* saver = _ScreenSaver(); 380 if (saver == NULL) 381 return; 382 383 BMessage state; 384 if (saver->SaveState(&state) == B_OK) 385 fSettings.SetModuleState(fCurrentName.String(), &state); 386 } 387 388 389 void 390 ModulesView::PopulateScreenSaverList() 391 { 392 fListView->DeselectAll(); 393 while (ScreenSaverItem* item = (ScreenSaverItem *)fListView->RemoveItem((int32)0)) { 394 delete item; 395 } 396 397 // Blackness is a built-in screen saver 398 fListView->AddItem(new ScreenSaverItem("Blackness", "")); 399 400 // Iterate over add-on directories, and add their files to the list view 401 402 directory_which which[] = {B_BEOS_ADDONS_DIRECTORY, B_USER_ADDONS_DIRECTORY}; 403 ScreenSaverItem* selectItem = NULL; 404 405 for (uint32 i = 0; i < sizeof(which) / sizeof(which[0]); i++) { 406 BPath basePath; 407 find_directory(which[i], &basePath); 408 basePath.Append("Screen Savers", true); 409 410 BDirectory dir(basePath.Path()); 411 BEntry entry; 412 while (dir.GetNextEntry(&entry, true) == B_OK) { 413 char name[B_FILE_NAME_LENGTH]; 414 if (entry.GetName(name) != B_OK) 415 continue; 416 417 BPath path = basePath; 418 path.Append(name); 419 420 ScreenSaverItem* item = new ScreenSaverItem(name, path.Path()); 421 fListView->AddItem(item); 422 423 if (!strcmp(fSettings.ModuleName(), item->Text()) 424 || (!strcmp(fSettings.ModuleName(), "") 425 && !strcmp(item->Text(), "Blackness"))) 426 selectItem = item; 427 } 428 } 429 430 fListView->SortItems(_CompareScreenSaverItems); 431 432 fListView->Select(fListView->IndexOf(selectItem)); 433 fListView->ScrollToSelection(); 434 } 435 436 437 //! sorting function for ScreenSaverItems 438 int 439 ModulesView::_CompareScreenSaverItems(const void* left, const void* right) 440 { 441 ScreenSaverItem* leftItem = *(ScreenSaverItem **)left; 442 ScreenSaverItem* rightItem = *(ScreenSaverItem **)right; 443 444 return strcasecmp(leftItem->Text(), rightItem->Text()); 445 } 446 447 448 BScreenSaver* 449 ModulesView::_ScreenSaver() 450 { 451 if (fSaverRunner != NULL) 452 return fSaverRunner->ScreenSaver(); 453 454 return NULL; 455 } 456 457 458 void 459 ModulesView::_CloseSaver() 460 { 461 // remove old screen saver preview & config 462 463 BScreenSaver* saver = _ScreenSaver(); 464 BView* view = fPreviewView->RemovePreview(); 465 if (fSettingsView != NULL) 466 fSettingsBox->RemoveChild(fSettingsView); 467 468 if (fSaverRunner != NULL) 469 fSaverRunner->Quit(); 470 if (saver != NULL) 471 saver->StopConfig(); 472 473 SaveState(); 474 475 delete view; 476 delete fSettingsView; 477 delete fSaverRunner; 478 // the saver runner also unloads the add-on, so it must 479 // be deleted last 480 481 fSettingsView = NULL; 482 fSaverRunner = NULL; 483 } 484 485 486 void 487 ModulesView::_OpenSaver() 488 { 489 // create new screen saver preview & config 490 491 BView* view = fPreviewView->AddPreview(); 492 fCurrentName = fSettings.ModuleName(); 493 fSaverRunner = new ScreenSaverRunner(Window(), view, true, fSettings); 494 BScreenSaver* saver = _ScreenSaver(); 495 496 #ifdef __HAIKU__ 497 BRect rect = fSettingsBox->InnerFrame().InsetByCopy(4, 4); 498 #else 499 BRect rect = fSettingsBox->Bounds().InsetByCopy(4, 4); 500 rect.top += 14; 501 #endif 502 fSettingsView = new BView(rect, "SettingsView", B_FOLLOW_ALL, B_WILL_DRAW); 503 fSettingsView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 504 fSettingsBox->AddChild(fSettingsView); 505 506 if (saver != NULL) { 507 fSaverRunner->Run(); 508 saver->StartConfig(fSettingsView); 509 } 510 511 if (fSettingsView->ChildAt(0) == NULL) { 512 // There are no settings at all, we add the module name here to 513 // let it look a bit better at least. 514 rect = BRect(15, 15, 20, 20); 515 BStringView* stringView = new BStringView(rect, "module", fSettings.ModuleName()[0] 516 ? fSettings.ModuleName() : "Blackness"); 517 stringView->SetFont(be_bold_font); 518 stringView->ResizeToPreferred(); 519 fSettingsView->AddChild(stringView); 520 521 rect.OffsetBy(0, stringView->Bounds().Height() + 4); 522 stringView = new BStringView(rect, "info", saver || !fSettings.ModuleName()[0] 523 ? "No options available" : "Could not load screen saver"); 524 stringView->ResizeToPreferred(); 525 fSettingsView->AddChild(stringView); 526 } 527 528 ScreenSaverWindow* window = dynamic_cast<ScreenSaverWindow*>(Window()); 529 if (window == NULL) 530 return; 531 532 // find the minimal size of the settings view 533 534 float right = 0, bottom = 0; 535 int32 i = 0; 536 while ((view = fSettingsView->ChildAt(i++)) != NULL) { 537 // very simple heuristic... 538 float viewRight = view->Frame().right; 539 if ((view->ResizingMode() & _rule_(0, 0xf, 0, 0xf)) == B_FOLLOW_LEFT_RIGHT) { 540 float width, height; 541 view->GetPreferredSize(&width, &height); 542 viewRight = view->Frame().left + width / 2; 543 } else if ((view->ResizingMode() & _rule_(0, 0xf, 0, 0xf)) == B_FOLLOW_RIGHT) 544 viewRight = 8 + view->Frame().Width(); 545 546 float viewBottom = view->Frame().bottom; 547 if ((view->ResizingMode() & _rule_(0xf, 0, 0xf, 0)) == B_FOLLOW_TOP_BOTTOM) { 548 float width, height; 549 view->GetPreferredSize(&width, &height); 550 viewBottom = view->Frame().top + height; 551 } else if ((view->ResizingMode() & _rule_(0xf, 0, 0xf, 0)) == B_FOLLOW_BOTTOM) 552 viewBottom = 8 + view->Frame().Height(); 553 554 if (viewRight > right) 555 right = viewRight; 556 if (viewBottom > bottom) 557 bottom = viewBottom; 558 } 559 560 if (right < kMinSettingsWidth) 561 right = kMinSettingsWidth; 562 if (bottom < kMinSettingsHeight) 563 bottom = kMinSettingsHeight; 564 565 BPoint leftTop = fSettingsView->LeftTop(); 566 fSettingsView->ConvertToScreen(&leftTop); 567 window->ConvertFromScreen(&leftTop); 568 window->SetMinimalSizeLimit(leftTop.x + right + 16, 569 leftTop.y + bottom + 16); 570 } 571 572 573 // #pragma mark - 574 575 576 ScreenSaverWindow::ScreenSaverWindow() 577 : BWindow(BRect(50, 50, 496, 375), "ScreenSaver", 578 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS /*| B_NOT_ZOOMABLE | B_NOT_RESIZABLE*/) 579 { 580 fSettings.Load(); 581 582 BRect rect = Bounds(); 583 fMinWidth = 430; 584 fMinHeight = 325; 585 586 // Create a background view 587 BView *background = new BView(rect, "background", B_FOLLOW_ALL, 0); 588 background->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 589 AddChild(background); 590 591 // Add the tab view to the background 592 rect.top += 4; 593 fTabView = new BTabView(rect, "tab_view"); 594 595 // Create the controls inside the tabs 596 rect = fTabView->ContainerView()->Bounds(); 597 _SetupFadeTab(rect); 598 fModulesView = new ModulesView(rect, "Modules", fSettings); 599 600 fTabView->AddTab(fFadeView); 601 fTabView->AddTab(fModulesView); 602 background->AddChild(fTabView); 603 604 // Create the password editing window 605 fPasswordWindow = new PasswordWindow(fSettings); 606 fPasswordWindow->Run(); 607 608 SetMinimalSizeLimit(fMinWidth, fMinHeight); 609 MoveTo(fSettings.WindowFrame().left, fSettings.WindowFrame().top); 610 ResizeTo(fSettings.WindowFrame().Width(), fSettings.WindowFrame().Height()); 611 612 fEnableCheckBox->SetValue(fSettings.TimeFlags() & ENABLE_SAVER ? B_CONTROL_ON : B_CONTROL_OFF); 613 fRunSlider->SetTime(fSettings.BlankTime()); 614 fTurnOffSlider->SetTime(fSettings.OffTime() + fSettings.BlankTime()); 615 fFadeNow->SetCorner(fSettings.BlankCorner()); 616 fFadeNever->SetCorner(fSettings.NeverBlankCorner()); 617 fPasswordCheckBox->SetValue(fSettings.LockEnable()); 618 fPasswordSlider->SetTime(fSettings.PasswordTime()); 619 620 fTabView->Select(fSettings.WindowTab()); 621 622 _UpdateTurnOffScreen(); 623 _UpdateStatus(); 624 } 625 626 627 ScreenSaverWindow::~ScreenSaverWindow() 628 { 629 } 630 631 632 //! Create the controls for the fade tab 633 void 634 ScreenSaverWindow::_SetupFadeTab(BRect rect) 635 { 636 fFadeView = new FadeView(rect, "Fade", fSettings); 637 638 float labelWidth = be_plain_font->StringWidth("Turn off screen") + 20.0f; 639 640 font_height fontHeight; 641 be_plain_font->GetHeight(&fontHeight); 642 float textHeight = ceilf(fontHeight.ascent + fontHeight.descent); 643 644 // taken from BRadioButton: 645 float radioButtonOffset = 2 * floorf(textHeight / 2 - 2) + floorf(textHeight / 2); 646 647 fEnableCheckBox = new BCheckBox(BRect(0, 0, 1, 1), "EnableCheckBox", 648 "Enable Screen Saver", new BMessage(kMsgEnableScreenSaverBox)); 649 fEnableCheckBox->ResizeToPreferred(); 650 651 rect.InsetBy(8, 8); 652 BBox* box = new BBox(rect, "EnableScreenSaverBox", B_FOLLOW_ALL); 653 box->SetLabel(fEnableCheckBox); 654 fFadeView->AddChild(box); 655 656 // Run Module 657 rect.left += radioButtonOffset; 658 rect.top = fEnableCheckBox->Bounds().bottom + 8.0f; 659 rect.right = box->Bounds().right - 8; 660 BStringView* stringView = new BStringView(rect, NULL, "Run module"); 661 stringView->ResizeToPreferred(); 662 box->AddChild(stringView); 663 664 rect.left += labelWidth; 665 fRunSlider = new TimeSlider(rect, "RunSlider", kMsgRunSliderChanged, 666 kMsgRunSliderUpdate); 667 float width, height; 668 fRunSlider->GetPreferredSize(&width, &height); 669 fRunSlider->ResizeTo(fRunSlider->Bounds().Width(), height); 670 box->AddChild(fRunSlider); 671 672 // Turn Off 673 rect.left = 8; 674 rect.OffsetBy(0, fRunSlider->Bounds().Height() + 4.0f); 675 fTurnOffCheckBox = new BCheckBox(rect, "TurnOffScreenCheckBox", 676 "Turn off screen", new BMessage(kMsgTurnOffCheckBox)); 677 fTurnOffCheckBox->ResizeToPreferred(); 678 box->AddChild(fTurnOffCheckBox); 679 680 rect.left += radioButtonOffset + labelWidth; 681 fTurnOffSlider = new TimeSlider(rect, "TurnOffSlider", 682 kMsgTurnOffSliderChanged, kMsgTurnOffSliderUpdate); 683 fTurnOffSlider->ResizeTo(fTurnOffSlider->Bounds().Width(), height); 684 box->AddChild(fTurnOffSlider); 685 686 // Password 687 rect.left = 8; 688 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 689 fPasswordCheckBox = new BCheckBox(rect, "PasswordCheckbox", 690 "Password lock", new BMessage(kMsgPasswordCheckBox)); 691 fPasswordCheckBox->ResizeToPreferred(); 692 box->AddChild(fPasswordCheckBox); 693 694 rect.left += radioButtonOffset + labelWidth; 695 fPasswordSlider = new TimeSlider(rect, "PasswordSlider", 696 kMsgPasswordSliderChanged, kMsgPasswordSliderUpdate); 697 fPasswordSlider->ResizeTo(fPasswordSlider->Bounds().Width(), height); 698 box->AddChild(fPasswordSlider); 699 700 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 701 rect.left = rect.right; 702 fPasswordButton = new BButton(rect, "PasswordButton", "Password" B_UTF8_ELLIPSIS, 703 new BMessage(kMsgChangePassword), B_FOLLOW_TOP | B_FOLLOW_RIGHT); 704 fPasswordButton->ResizeToPreferred(); 705 fPasswordButton->MoveBy(-fPasswordButton->Bounds().Width(), 0); 706 box->AddChild(fPasswordButton); 707 708 // Bottom 709 710 float monitorHeight = 10 + textHeight * 3; 711 float monitorWidth = monitorHeight * 4 / 3; 712 rect.left = 15; 713 rect.top = box->Bounds().Height() - 15 - monitorHeight; 714 rect.right = rect.left + monitorWidth; 715 rect.bottom = rect.top + monitorHeight; 716 box->AddChild(fFadeNow = new ScreenCornerSelector(rect, "FadeNow", 717 new BMessage(kMsgFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 718 719 rect.OffsetBy(monitorWidth + 10, 0); 720 stringView = new BStringView(rect, NULL, "Fade now when", 721 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 722 stringView->ResizeToPreferred(); 723 float maxWidth = stringView->Bounds().Width(); 724 box->AddChild(stringView); 725 726 rect.OffsetBy(0, stringView->Bounds().Height()); 727 stringView = new BStringView(rect, NULL, "mouse is here", 728 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 729 stringView->ResizeToPreferred(); 730 if (maxWidth < stringView->Bounds().Width()) 731 maxWidth = stringView->Bounds().Width(); 732 box->AddChild(stringView); 733 734 rect.left += maxWidth + 20; 735 rect.top = box->Bounds().Height() - 15 - monitorHeight; 736 rect.right = rect.left + monitorWidth; 737 rect.bottom = rect.top + monitorHeight; 738 box->AddChild(fFadeNever = new ScreenCornerSelector(rect, "FadeNever", 739 new BMessage(kMsgNeverFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 740 741 rect.OffsetBy(monitorWidth + 10, 0); 742 stringView = new BStringView(rect, NULL,"Don't fade when", 743 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 744 stringView->ResizeToPreferred(); 745 if (maxWidth < stringView->Bounds().Width()) 746 maxWidth = stringView->Bounds().Width(); 747 box->AddChild(stringView); 748 749 rect.OffsetBy(0, stringView->Bounds().Height()); 750 stringView = new BStringView(rect, NULL, "mouse is here", 751 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 752 stringView->ResizeToPreferred(); 753 if (maxWidth < stringView->Bounds().Width()) 754 maxWidth = stringView->Bounds().Width(); 755 box->AddChild(stringView); 756 757 float size = rect.left + maxWidth + 40; 758 if (fMinWidth < size) 759 fMinWidth = size; 760 size = fPasswordButton->Frame().bottom + box->Frame().top 761 + monitorHeight + 40 + textHeight * 2; 762 if (fMinHeight < size) 763 fMinHeight = size; 764 } 765 766 767 void 768 ScreenSaverWindow::_UpdateTurnOffScreen() 769 { 770 bool enabled = (fSettings.TimeFlags() & ENABLE_DPMS_MASK) != 0; 771 772 BScreen screen(this); 773 uint32 dpmsCapabilities = screen.DPMSCapabilites(); 774 775 fTurnOffScreenFlags = 0; 776 if (dpmsCapabilities & B_DPMS_OFF) 777 fTurnOffScreenFlags |= ENABLE_DPMS_OFF; 778 if (dpmsCapabilities & B_DPMS_STAND_BY) 779 fTurnOffScreenFlags |= ENABLE_DPMS_STAND_BY; 780 if (dpmsCapabilities & B_DPMS_SUSPEND) 781 fTurnOffScreenFlags |= ENABLE_DPMS_SUSPEND; 782 783 fTurnOffCheckBox->SetValue(enabled && fTurnOffScreenFlags != 0 784 ? B_CONTROL_ON : B_CONTROL_OFF); 785 } 786 787 788 void 789 ScreenSaverWindow::_UpdateStatus() 790 { 791 DisableUpdates(); 792 793 bool enabled = fEnableCheckBox->Value() == B_CONTROL_ON; 794 fPasswordCheckBox->SetEnabled(enabled); 795 fTurnOffCheckBox->SetEnabled(enabled && fTurnOffScreenFlags != 0); 796 fRunSlider->SetEnabled(enabled); 797 fTurnOffSlider->SetEnabled(enabled && fTurnOffCheckBox->Value()); 798 fPasswordSlider->SetEnabled(enabled && fPasswordCheckBox->Value()); 799 fPasswordButton->SetEnabled(enabled && fPasswordCheckBox->Value()); 800 801 EnableUpdates(); 802 803 // Update the saved preferences 804 fSettings.SetWindowFrame(Frame()); 805 fSettings.SetWindowTab(fTabView->Selection()); 806 fSettings.SetTimeFlags((enabled ? ENABLE_SAVER : 0) 807 | (fTurnOffCheckBox->Value() ? fTurnOffScreenFlags : 0)); 808 fSettings.SetBlankTime(fRunSlider->Time()); 809 bigtime_t offTime = fTurnOffSlider->Time() - fSettings.BlankTime(); 810 fSettings.SetOffTime(offTime); 811 fSettings.SetSuspendTime(offTime); 812 fSettings.SetStandByTime(offTime); 813 fSettings.SetBlankCorner(fFadeNow->Corner()); 814 fSettings.SetNeverBlankCorner(fFadeNever->Corner()); 815 fSettings.SetLockEnable(fPasswordCheckBox->Value()); 816 fSettings.SetPasswordTime(fPasswordSlider->Time()); 817 818 // TODO - Tell the password window to update its stuff 819 } 820 821 822 void 823 ScreenSaverWindow::SetMinimalSizeLimit(float width, float height) 824 { 825 if (width < fMinWidth) 826 width = fMinWidth; 827 if (height < fMinHeight) 828 height = fMinHeight; 829 830 SetSizeLimits(width, 32767, height, 32767); 831 } 832 833 834 void 835 ScreenSaverWindow::MessageReceived(BMessage *msg) 836 { 837 // "Fade" tab, slider updates 838 839 switch (msg->what) { 840 case kMsgRunSliderChanged: 841 case kMsgRunSliderUpdate: 842 if (fRunSlider->Value() > fTurnOffSlider->Value()) 843 fTurnOffSlider->SetValue(fRunSlider->Value()); 844 845 if (fRunSlider->Value() > fPasswordSlider->Value()) 846 fPasswordSlider->SetValue(fRunSlider->Value()); 847 break; 848 849 case kMsgTurnOffSliderChanged: 850 case kMsgTurnOffSliderUpdate: 851 if (fRunSlider->Value() > fTurnOffSlider->Value()) 852 fRunSlider->SetValue(fTurnOffSlider->Value()); 853 break; 854 855 case kMsgPasswordSliderChanged: 856 case kMsgPasswordSliderUpdate: 857 if (fPasswordSlider->Value() < fRunSlider->Value()) 858 fRunSlider->SetValue(fPasswordSlider->Value()); 859 break; 860 } 861 862 switch (msg->what) { 863 // "Fade" tab 864 865 case kMsgTurnOffCheckBox: 866 fTurnOffSlider->SetEnabled(fTurnOffCheckBox->Value() == B_CONTROL_ON); 867 break; 868 869 case kMsgRunSliderChanged: 870 case kMsgTurnOffSliderChanged: 871 case kMsgPasswordSliderChanged: 872 case kMsgPasswordCheckBox: 873 case kMsgEnableScreenSaverBox: 874 case kMsgFadeCornerChanged: 875 case kMsgNeverFadeCornerChanged: 876 _UpdateStatus(); 877 fSettings.Save(); 878 break; 879 880 case kMsgChangePassword: 881 fPasswordWindow->Show(); 882 break; 883 884 // "Modules" tab 885 886 case kMsgUpdateList: 887 fModulesView->PopulateScreenSaverList(); 888 break; 889 890 default: 891 BWindow::MessageReceived(msg); 892 break; 893 } 894 } 895 896 897 void 898 ScreenSaverWindow::ScreenChanged(BRect frame, color_space colorSpace) 899 { 900 _UpdateTurnOffScreen(); 901 } 902 903 904 bool 905 ScreenSaverWindow::QuitRequested() 906 { 907 _UpdateStatus(); 908 fModulesView->SaveState(); 909 fSettings.Save(); 910 911 be_app->PostMessage(B_QUIT_REQUESTED); 912 return true; 913 } 914 915