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