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 strcmp(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 595 // Create a background view 596 BView *background = new BView(rect, "background", B_FOLLOW_ALL, 0); 597 background->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 598 AddChild(background); 599 600 // Add the tab view to the background 601 rect.top += 4; 602 fTabView = new BTabView(rect, "tab_view"); 603 604 // Create the controls inside the tabs 605 rect = fTabView->ContainerView()->Bounds(); 606 _SetupFadeTab(rect); 607 fModulesView = new ModulesView(rect, "Modules", fSettings); 608 609 fTabView->AddTab(fFadeView); 610 fTabView->AddTab(fModulesView); 611 background->AddChild(fTabView); 612 613 // Create the password editing window 614 fPasswordWindow = new PasswordWindow(fSettings); 615 fPasswordWindow->Run(); 616 617 // TODO: better limits! 618 fMinWidth = 430; 619 fMinHeight = 325; 620 SetMinimalSizeLimit(fMinWidth, fMinHeight); 621 MoveTo(fSettings.WindowFrame().left, fSettings.WindowFrame().top); 622 ResizeTo(fSettings.WindowFrame().Width(), fSettings.WindowFrame().Height()); 623 624 fEnableCheckBox->SetValue(fSettings.TimeFlags() & ENABLE_SAVER ? B_CONTROL_ON : B_CONTROL_OFF); 625 fRunSlider->SetTime(fSettings.BlankTime()); 626 fTurnOffSlider->SetTime(fSettings.OffTime() + fSettings.BlankTime()); 627 fFadeNow->SetCorner(fSettings.BlankCorner()); 628 fFadeNever->SetCorner(fSettings.NeverBlankCorner()); 629 fPasswordCheckBox->SetValue(fSettings.LockEnable()); 630 fPasswordSlider->SetTime(fSettings.PasswordTime()); 631 632 fTabView->Select(fSettings.WindowTab()); 633 634 _UpdateTurnOffScreen(); 635 _UpdateStatus(); 636 } 637 638 639 ScreenSaverWindow::~ScreenSaverWindow() 640 { 641 } 642 643 644 //! Create the controls for the fade tab 645 void 646 ScreenSaverWindow::_SetupFadeTab(BRect rect) 647 { 648 fFadeView = new FadeView(rect, "Fade", fSettings); 649 650 float labelWidth = be_plain_font->StringWidth("Turn off screen") + 20.0f; 651 652 font_height fontHeight; 653 be_plain_font->GetHeight(&fontHeight); 654 float textHeight = ceilf(fontHeight.ascent + fontHeight.descent); 655 656 // taken from BRadioButton: 657 float radioButtonOffset = 2 * floorf(textHeight / 2 - 2) + floorf(textHeight / 2); 658 659 fEnableCheckBox = new BCheckBox(BRect(0, 0, 1, 1), "EnableCheckBox", 660 "Enable Screen Saver", new BMessage(kMsgEnableScreenSaverBox)); 661 fEnableCheckBox->ResizeToPreferred(); 662 663 rect.InsetBy(8, 8); 664 BBox* box = new BBox(rect, "EnableScreenSaverBox", B_FOLLOW_ALL); 665 box->SetLabel(fEnableCheckBox); 666 fFadeView->AddChild(box); 667 668 // Run Module 669 rect.left += radioButtonOffset; 670 rect.top = fEnableCheckBox->Bounds().bottom + 8.0f; 671 rect.right = box->Bounds().right - 8; 672 BStringView* stringView = new BStringView(rect, NULL, "Run module"); 673 stringView->ResizeToPreferred(); 674 box->AddChild(stringView); 675 676 rect.left += labelWidth; 677 fRunSlider = new TimeSlider(rect, "RunSlider", kMsgRunSliderChanged); 678 float width, height; 679 fRunSlider->GetPreferredSize(&width, &height); 680 fRunSlider->ResizeTo(fRunSlider->Bounds().Width(), height); 681 box->AddChild(fRunSlider); 682 683 // Turn Off 684 rect.left = 8; 685 rect.OffsetBy(0, fRunSlider->Bounds().Height() + 4.0f); 686 fTurnOffCheckBox = new BCheckBox(rect, "TurnOffScreenCheckBox", 687 "Turn off screen", new BMessage(kMsgTurnOffCheckBox)); 688 fTurnOffCheckBox->ResizeToPreferred(); 689 box->AddChild(fTurnOffCheckBox); 690 691 rect.left += radioButtonOffset + labelWidth; 692 fTurnOffSlider = new TimeSlider(rect, "TurnOffSlider", kMsgTurnOffSliderChanged); 693 fTurnOffSlider->ResizeTo(fTurnOffSlider->Bounds().Width(), height); 694 box->AddChild(fTurnOffSlider); 695 696 // Password 697 rect.left = 8; 698 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 699 fPasswordCheckBox = new BCheckBox(rect, "PasswordCheckbox", 700 "Password lock", new BMessage(kMsgPasswordCheckBox)); 701 fPasswordCheckBox->ResizeToPreferred(); 702 box->AddChild(fPasswordCheckBox); 703 704 rect.left += radioButtonOffset + labelWidth; 705 fPasswordSlider = new TimeSlider(rect, "PasswordSlider", kMsgPasswordSliderChanged); 706 fPasswordSlider->ResizeTo(fPasswordSlider->Bounds().Width(), height); 707 box->AddChild(fPasswordSlider); 708 709 rect.OffsetBy(0, fTurnOffSlider->Bounds().Height() + 4.0f); 710 rect.left = rect.right; 711 fPasswordButton = new BButton(rect, "PasswordButton", "Password" B_UTF8_ELLIPSIS, 712 new BMessage(kMsgChangePassword), B_FOLLOW_TOP | B_FOLLOW_RIGHT); 713 fPasswordButton->ResizeToPreferred(); 714 fPasswordButton->MoveBy(-fPasswordButton->Bounds().Width(), 0); 715 box->AddChild(fPasswordButton); 716 717 // Bottom 718 719 box->AddChild(fFadeNow = new ScreenCornerSelector(BRect(20,205,80,260), "FadeNow", 720 new BMessage(kMsgFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 721 box->AddChild(fFadeNever = new ScreenCornerSelector(BRect(220,205,280,260), "FadeNever", 722 new BMessage(kMsgNeverFadeCornerChanged), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM)); 723 724 rect = BRect(90,215,193,230); 725 stringView = new BStringView(rect, NULL, "Fade now when", 726 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 727 stringView->ResizeToPreferred(); 728 box->AddChild(stringView); 729 730 rect.OffsetBy(0, stringView->Bounds().Height()); 731 stringView = new BStringView(rect, NULL, "mouse is here", 732 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 733 stringView->ResizeToPreferred(); 734 box->AddChild(stringView); 735 736 rect = BRect(290,215,387,230); 737 stringView = new BStringView(rect, NULL,"Don't fade when", 738 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 739 stringView->ResizeToPreferred(); 740 box->AddChild(stringView); 741 742 rect.OffsetBy(0, stringView->Bounds().Height()); 743 stringView = new BStringView(rect, NULL, "mouse is here", 744 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 745 stringView->ResizeToPreferred(); 746 box->AddChild(stringView); 747 } 748 749 750 void 751 ScreenSaverWindow::_UpdateTurnOffScreen() 752 { 753 bool enabled = (fSettings.TimeFlags() & ENABLE_DPMS_MASK) != 0; 754 755 BScreen screen(this); 756 uint32 dpmsCapabilities = screen.DPMSCapabilites(); 757 758 fTurnOffScreenFlags = 0; 759 if (dpmsCapabilities & B_DPMS_OFF) 760 fTurnOffScreenFlags |= ENABLE_DPMS_OFF; 761 if (dpmsCapabilities & B_DPMS_STAND_BY) 762 fTurnOffScreenFlags |= ENABLE_DPMS_STAND_BY; 763 if (dpmsCapabilities & B_DPMS_SUSPEND) 764 fTurnOffScreenFlags |= ENABLE_DPMS_SUSPEND; 765 766 fTurnOffCheckBox->SetValue(enabled && fTurnOffScreenFlags != 0 767 ? B_CONTROL_ON : B_CONTROL_OFF); 768 } 769 770 771 void 772 ScreenSaverWindow::_UpdateStatus() 773 { 774 DisableUpdates(); 775 776 bool enabled = fEnableCheckBox->Value() == B_CONTROL_ON; 777 fPasswordCheckBox->SetEnabled(enabled); 778 fTurnOffCheckBox->SetEnabled(enabled && fTurnOffScreenFlags != 0); 779 fRunSlider->SetEnabled(enabled); 780 fTurnOffSlider->SetEnabled(enabled && fTurnOffCheckBox->Value()); 781 fPasswordSlider->SetEnabled(enabled && fPasswordCheckBox->Value()); 782 fPasswordButton->SetEnabled(enabled && fPasswordCheckBox->Value()); 783 784 EnableUpdates(); 785 786 // Update the saved preferences 787 fSettings.SetWindowFrame(Frame()); 788 fSettings.SetWindowTab(fTabView->Selection()); 789 fSettings.SetTimeFlags((enabled ? ENABLE_SAVER : 0) 790 | (fTurnOffCheckBox->Value() ? fTurnOffScreenFlags : 0)); 791 fSettings.SetBlankTime(fRunSlider->Time()); 792 bigtime_t offTime = fTurnOffSlider->Time() - fSettings.BlankTime(); 793 fSettings.SetOffTime(offTime); 794 fSettings.SetSuspendTime(offTime); 795 fSettings.SetStandByTime(offTime); 796 fSettings.SetBlankCorner(fFadeNow->Corner()); 797 fSettings.SetNeverBlankCorner(fFadeNever->Corner()); 798 fSettings.SetLockEnable(fPasswordCheckBox->Value()); 799 fSettings.SetPasswordTime(fPasswordSlider->Time()); 800 801 // TODO - Tell the password window to update its stuff 802 } 803 804 805 void 806 ScreenSaverWindow::SetMinimalSizeLimit(float width, float height) 807 { 808 if (width < fMinWidth) 809 width = fMinWidth; 810 if (height < fMinHeight) 811 height = fMinHeight; 812 813 SetSizeLimits(width, 32767, height, 32767); 814 } 815 816 817 void 818 ScreenSaverWindow::MessageReceived(BMessage *msg) 819 { 820 switch (msg->what) { 821 // "Fade" tab 822 823 case kMsgRunSliderChanged: 824 if (fRunSlider->Value() > fTurnOffSlider->Value()) 825 fTurnOffSlider->SetValue(fRunSlider->Value()); 826 827 if (fRunSlider->Value() > fPasswordSlider->Value()) 828 fPasswordSlider->SetValue(fRunSlider->Value()); 829 break; 830 831 case kMsgTurnOffCheckBox: 832 fTurnOffSlider->SetEnabled(fTurnOffCheckBox->Value() == B_CONTROL_ON); 833 break; 834 835 case kMsgTurnOffSliderChanged: 836 if (fRunSlider->Value() > fTurnOffSlider->Value()) 837 fRunSlider->SetValue(fTurnOffSlider->Value()); 838 break; 839 840 case kMsgPasswordSliderChanged: 841 if (fPasswordSlider->Value() < fRunSlider->Value()) 842 fRunSlider->SetValue(fPasswordSlider->Value()); 843 break; 844 845 case kMsgPasswordCheckBox: 846 case kMsgEnableScreenSaverBox: 847 case kMsgFadeCornerChanged: 848 case kMsgNeverFadeCornerChanged: 849 _UpdateStatus(); 850 fSettings.Save(); 851 break; 852 853 case kMsgChangePassword: 854 fPasswordWindow->Show(); 855 break; 856 857 // "Modules" tab 858 859 case kMsgUpdateList: 860 fModulesView->PopulateScreenSaverList(); 861 break; 862 } 863 BWindow::MessageReceived(msg); 864 } 865 866 867 void 868 ScreenSaverWindow::ScreenChanged(BRect frame, color_space colorSpace) 869 { 870 _UpdateTurnOffScreen(); 871 } 872 873 874 bool 875 ScreenSaverWindow::QuitRequested() 876 { 877 _UpdateStatus(); 878 fModulesView->SaveState(); 879 fSettings.Save(); 880 881 be_app->PostMessage(B_QUIT_REQUESTED); 882 return true; 883 } 884 885