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