1 /* 2 * Copyright 2003-2005, 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 */ 9 10 #include <ListView.h> 11 #include <Application.h> 12 #include <Button.h> 13 #include <Box.h> 14 #include <Font.h> 15 #include <TabView.h> 16 #include <Directory.h> 17 #include <Entry.h> 18 #include <File.h> 19 #include <Path.h> 20 #include <ScrollView.h> 21 #include <FindDirectory.h> 22 #include <Slider.h> 23 #include <StringView.h> 24 #include <ScreenSaver.h> 25 #include <Roster.h> 26 #include <stdio.h> 27 28 #include "ScreenSaverWindow.h" 29 #include "ScreenSaverItem.h" 30 #include "MouseAreaView.h" 31 #include "PreviewView.h" 32 33 #include <Debug.h> 34 #define CALLED() PRINT(("%s\n", __PRETTY_FUNCTION__)) 35 36 static const char *kTimes[]={"30 seconds", "1 minute", "1 minute 30 seconds", 37 "2 minutes", "2 minutes 30 seconds", "3 minutes", 38 "4 minutes", "5 minutes", "6 minutes", 39 "7 minutes", "8 minutes", "9 minutes", 40 "10 minutes", "15 minutes", "20 minutes", 41 "25 minutes", "30 minutes", "40 minutes", 42 "50 minutes", "1 hour", "1 hour 30 minutes", 43 "2 hours", "2 hours 30 minutes", "3 hours", 44 "4 hours", "5 hours"}; 45 46 static const int32 kTimeInUnits[]={ 30, 60, 90, 47 120, 150, 180, 48 240, 300, 360, 49 420, 480, 540, 50 600, 900, 1200, 51 1500, 1800, 2400, 52 3000, 3600, 5400, 53 7200, 9000, 10800, 54 14400, 18000}; 55 56 int32 57 UnitsToSlider(bigtime_t val) 58 { 59 int count = sizeof(kTimeInUnits)/sizeof(int); 60 for (int t=0; t<count; t++) 61 if (kTimeInUnits[t]*1000000LL == val) 62 return t; 63 return -1; 64 } 65 66 67 class CustomTab : public BTab 68 { 69 public: 70 CustomTab(ScreenSaverWin *win, BView *view = NULL); 71 virtual ~CustomTab(); 72 virtual void Select(BView *view); 73 private: 74 ScreenSaverWin *fWin; 75 }; 76 77 78 CustomTab::CustomTab(ScreenSaverWin *win, BView *view) 79 : BTab(view), 80 fWin(win) 81 { 82 83 } 84 85 CustomTab::~CustomTab() 86 { 87 } 88 89 90 void 91 CustomTab::Select(BView *view) 92 { 93 BTab::Select(view); 94 fWin->SelectCurrentModule(); 95 } 96 97 98 ScreenSaverWin::ScreenSaverWin() 99 : BWindow(BRect(50,50,496,375),"OBOS Screen Saver", 100 B_TITLED_WINDOW,B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE) , 101 fFadeState(0),fNoFadeState(0), fListView1(NULL), 102 fSelectedAddonFileName(NULL), 103 fCurrentAddon(NULL), fTestButton(NULL), 104 fEnableCheckbox(NULL), 105 fTurnOffMinutes(NULL), fRunMinutes(NULL), 106 fPasswordMinutes(NULL), fPasswordButton(NULL), 107 fFadeNowString(NULL), 108 fFadeNowString2(NULL), 109 fDontFadeString(NULL), fDontFadeString2(NULL), 110 fFadeNow(NULL),fFadeNever(NULL), 111 fPwMessenger(NULL), fFilePanel(NULL), 112 fSettingsArea(NULL) 113 114 { 115 SetupForm(); 116 } 117 118 119 ScreenSaverWin::~ScreenSaverWin() 120 { 121 delete fFilePanel; 122 } 123 124 125 void 126 ScreenSaverWin::SaverSelected() 127 { 128 CALLED(); 129 UpdateStatus(); 130 fPrefs.SaveSettings(); 131 if (fListView1->CurrentSelection()>=0) { 132 if (fPreviewDisplay->ScreenSaver()) 133 fPreviewDisplay->ScreenSaver()->StopConfig(); 134 ScreenSaverItem* item = reinterpret_cast<ScreenSaverItem*>(fListView1->ItemAt(fListView1->CurrentSelection())); 135 BString settingsMsgName(item->Path()); 136 fPreviewDisplay->SetScreenSaver(settingsMsgName); 137 if (fSettingsArea) { 138 fModuleSettingsBox->RemoveChild(fSettingsArea); 139 delete fSettingsArea; 140 } 141 BRect bnds = fModuleSettingsBox->Bounds(); 142 bnds.left = 3; 143 bnds.right -= 7; 144 bnds.top = 21; 145 bnds.bottom -= 2; 146 fSettingsArea = new BView(bnds,"settingsArea",B_FOLLOW_NONE,B_WILL_DRAW); 147 fSettingsArea->SetViewColor(216,216,216); 148 fModuleSettingsBox->AddChild(fSettingsArea); 149 150 if (fPreviewDisplay->ScreenSaver()) 151 fPreviewDisplay->ScreenSaver()->StartConfig(fSettingsArea); 152 } 153 } 154 155 156 void 157 ScreenSaverWin::MessageReceived(BMessage *msg) 158 { 159 switch(msg->what) { 160 case kRunSliderChanged: 161 fRunSlider->SetLabel(kTimes[fRunSlider->Value()]); 162 if (fRunSlider->Value()>fPasswordSlider->Value()) { 163 fTurnOffSlider->SetValue(fRunSlider->Value()); 164 fTurnOffSlider->SetLabel(kTimes[fTurnOffSlider->Value()]); 165 fPasswordSlider->SetValue(fRunSlider->Value()); 166 fPasswordSlider->SetLabel(kTimes[fPasswordSlider->Value()]); 167 } 168 break; 169 case kTurnOffSliderChanged: 170 fTurnOffSlider->SetLabel(kTimes[fTurnOffSlider->Value()]); 171 break; 172 case kPasswordSliderChanged: 173 fPasswordSlider->SetLabel(kTimes[fPasswordSlider->Value()]); 174 if (fPasswordSlider->Value()<fRunSlider->Value()) { 175 fRunSlider->SetValue(fPasswordSlider->Value()); 176 fRunSlider->SetLabel(kTimes[fRunSlider->Value()]); 177 } 178 break; 179 case kPasswordCheckbox: 180 case kEnableScreenSaverChanged: 181 UpdateStatus(); 182 break; 183 case kPwbutton: 184 fPwMessenger->SendMessage(kShow); 185 break; 186 case kSaver_sel: 187 SaverSelected(); 188 break; 189 case kTest_btn: 190 { 191 BMessage &settings = fPrefs.GetSettings(); 192 be_roster->Launch(SCREEN_BLANKER_SIG, &settings); 193 break; 194 } 195 case kAdd_btn: 196 fFilePanel->Show(); 197 break; 198 case kUpdatelist: 199 PopulateScreenSaverList(); 200 break; 201 } 202 BWindow::MessageReceived(msg); 203 } 204 205 206 bool 207 ScreenSaverWin::QuitRequested() 208 { 209 UpdateStatus(); 210 fPrefs.SaveSettings(); 211 be_app->PostMessage(B_QUIT_REQUESTED); 212 return true; 213 } 214 215 216 void 217 ScreenSaverWin::UpdateStatus(void) 218 { 219 DisableUpdates(); 220 // Policy - enable and disable controls as per checkboxes, etc 221 fPasswordCheckbox->SetEnabled(fEnableCheckbox->Value()); 222 fTurnOffScreenCheckBox->SetEnabled(fEnableCheckbox->Value()); 223 fRunSlider->SetEnabled(fEnableCheckbox->Value()); 224 fTurnOffSlider->SetEnabled(fEnableCheckbox->Value() && fTurnOffScreenCheckBox->Value()); 225 fTurnOffSlider->SetEnabled(false); // This never seems to turn on in the R5 version 226 fTurnOffScreenCheckBox->SetEnabled(false); 227 fPasswordSlider->SetEnabled(fEnableCheckbox->Value() && fPasswordCheckbox->Value()); 228 fPasswordButton->SetEnabled(fEnableCheckbox->Value() && fPasswordCheckbox->Value()); 229 // Set the labels for the sliders 230 fRunSlider->SetLabel(kTimes[fRunSlider->Value()]); 231 fTurnOffSlider->SetLabel(kTimes[fTurnOffSlider->Value()]); 232 fPasswordSlider->SetLabel(kTimes[fPasswordSlider->Value()]); 233 EnableUpdates(); 234 // Update the saved preferences 235 fPrefs.SetWindowFrame(Frame()); 236 fPrefs.SetWindowTab(fTabView->Selection()); 237 fPrefs.SetTimeFlags(fEnableCheckbox->Value()); 238 fPrefs.SetBlankTime(1000000LL* kTimeInUnits[fRunSlider->Value()]); 239 fPrefs.SetOffTime(1000000LL* kTimeInUnits[fTurnOffSlider->Value()]); 240 fPrefs.SetSuspendTime(1000000LL* kTimeInUnits[fTurnOffSlider->Value()]); 241 fPrefs.SetStandbyTime(1000000LL* kTimeInUnits[fTurnOffSlider->Value()]); 242 fPrefs.SetBlankCorner(fFadeNow->getDirection()); 243 fPrefs.SetNeverBlankCorner(fFadeNever->getDirection()); 244 fPrefs.SetLockEnable(fPasswordCheckbox->Value()); 245 fPrefs.SetPasswordTime(1000000LL* kTimeInUnits[fPasswordSlider->Value()]); 246 int selection = fListView1->CurrentSelection(); 247 if (selection >= 0) { 248 fPrefs.SetModuleName(((ScreenSaverItem *)(fListView1->ItemAt(selection)))->Text()); 249 if (strcmp(fPrefs.ModuleName(), "Blackness") == 0) 250 fPrefs.SetModuleName(""); 251 } 252 // TODO - Tell the password window to update its stuff 253 BMessage ssState; 254 if ((fPreviewDisplay->ScreenSaver()) && (fPreviewDisplay->ScreenSaver()->SaveState(&ssState)==B_OK)) 255 fPrefs.SetState(fPrefs.ModuleName(), &ssState); 256 }; 257 258 259 void 260 ScreenSaverWin::SetupForm() 261 { 262 fFilePanel = new BFilePanel(); 263 264 BRect r = Bounds(); 265 BTab *tab1, *tab2; 266 267 // Create a background view 268 BView *background = new BView(r,"background",B_FOLLOW_NONE,0); 269 background->SetViewColor(216,216,216,0); 270 AddChild(background); 271 272 // Add the tab view to the background 273 r.top += 4; 274 fTabView = new BTabView(r, "tab_view"); 275 fTabView->SetViewColor(216,216,216,0); 276 r = fTabView->Bounds(); 277 r.InsetBy(0,4); 278 r.bottom -= fTabView->TabHeight(); 279 280 // Time to load the settings into a message and implement them... 281 fPrefs.LoadSettings(); 282 283 tab2 = new BTab(); 284 fTab2 = new BView(r,"Fade",B_FOLLOW_NONE,0); 285 tab2->SetLabel("Fade"); 286 287 tab1 = new CustomTab(this); 288 fTab1 = new BView(r,"Modules",B_FOLLOW_NONE,0); 289 tab1->SetLabel("Modules"); 290 291 // Create the controls inside the tabs 292 SetupTab2(); 293 SetupTab1(); 294 295 fTabView->AddTab(fTab2, tab2); 296 fTabView->AddTab(fTab1, tab1); 297 background->AddChild(fTabView); 298 299 // Create the password editing window 300 fPwWin = new PasswordWindow(fPrefs); 301 fPwMessenger = new BMessenger(NULL,fPwWin); 302 fPwWin->Run(); 303 304 MoveTo(fPrefs.WindowFrame().left,fPrefs.WindowFrame().top); 305 306 fEnableCheckbox->SetValue(fPrefs.TimeFlags()); 307 fRunSlider->SetValue(UnitsToSlider(fPrefs.BlankTime())); 308 fTurnOffSlider->SetValue(UnitsToSlider(fPrefs.OffTime())); 309 fFadeNow->setDirection(fPrefs.GetBlankCorner()); 310 fFadeNever->setDirection(fPrefs.GetNeverBlankCorner()); 311 fPasswordCheckbox->SetValue(fPrefs.LockEnable()); 312 fPasswordSlider->SetValue(UnitsToSlider(fPrefs.PasswordTime())); 313 314 fTabView->Select(fPrefs.WindowTab()); 315 SelectCurrentModule(); 316 UpdateStatus(); 317 } 318 319 320 void 321 ScreenSaverWin::SelectCurrentModule() 322 { 323 CALLED(); 324 325 int32 count = fListView1->CountItems(); 326 for (int32 i=0; i<count; i++) { 327 ScreenSaverItem *item = dynamic_cast<ScreenSaverItem*>(fListView1->ItemAt(i)); 328 if ((strcmp(fPrefs.ModuleName(), item->Text()) == 0) 329 || (strcmp(fPrefs.ModuleName(),"") == 0 && strcmp(item->Text(), "Blackness") ==0)) { 330 fListView1->Select(i); 331 SaverSelected(); 332 fListView1->ScrollToSelection(); 333 break; 334 } 335 } 336 } 337 338 339 // Set the common Look and Feel stuff for a given control 340 void 341 commonLookAndFeel(BView *widget,bool isSlider,bool isControl) 342 { 343 {rgb_color clr = {216,216,216,255}; widget->SetViewColor(clr);} 344 if (isSlider) { 345 BSlider *slid=dynamic_cast<BSlider *>(widget); 346 {rgb_color clr = {160,160,160,0}; slid->SetBarColor(clr);} 347 slid->SetHashMarks(B_HASH_MARKS_NONE); 348 slid->SetHashMarkCount(0); 349 slid->SetStyle(B_TRIANGLE_THUMB); 350 slid->SetLimitLabels("",""); 351 slid->SetLimitLabels(NULL,NULL); 352 slid->SetLabel("0 minutes"); 353 slid->SetValue(0); 354 slid->SetEnabled(true); 355 } 356 {rgb_color clr = {0,0,0,0}; widget->SetHighColor(clr);} 357 widget->SetFlags(B_WILL_DRAW|B_NAVIGABLE); 358 widget->SetResizingMode(B_FOLLOW_NONE); 359 widget->SetFontSize(10); 360 widget->SetFont(be_plain_font); 361 if (isControl) { 362 BControl *wid=dynamic_cast<BControl *>(widget); 363 wid->SetEnabled(true); 364 } 365 } 366 367 368 // Iterate over a directory, adding the directories files to the list 369 void 370 addScreenSaversToList (directory_which dir, BListView *list) 371 { 372 BPath path; 373 find_directory(dir,&path); 374 path.Append("Screen Savers",true); 375 376 BDirectory ssDir(path.Path()); 377 BEntry thisSS; 378 char thisName[B_FILE_NAME_LENGTH]; 379 380 while (B_OK==ssDir.GetNextEntry(&thisSS,true)) { 381 thisSS.GetName(thisName); 382 BString pathname = path.Path(); 383 pathname += "/"; 384 pathname += thisName; 385 list->AddItem(new ScreenSaverItem(thisName, pathname.String())); 386 } 387 } 388 389 390 // sorting function for ScreenSaverItems 391 int 392 ScreenSaverWin::CompareScreenSaverItems(const void* left, const void* right) 393 { 394 ScreenSaverItem* leftItem = *(ScreenSaverItem **)left; 395 ScreenSaverItem* rightItem = *(ScreenSaverItem **)right; 396 397 return strcmp(leftItem->Text(),rightItem->Text()); 398 } 399 400 401 void 402 ScreenSaverWin::PopulateScreenSaverList(void) 403 { 404 fListView1->DeselectAll(); 405 while (void *i=fListView1->RemoveItem((int32)0)) 406 delete ((ScreenSaverItem *)i); 407 408 fListView1->AddItem(new ScreenSaverItem("Blackness", "")); 409 addScreenSaversToList(B_BEOS_ADDONS_DIRECTORY, fListView1); 410 addScreenSaversToList(B_USER_ADDONS_DIRECTORY, fListView1); 411 412 fListView1->SortItems(CompareScreenSaverItems); 413 } 414 415 416 // Create the controls for the first tab 417 void 418 ScreenSaverWin::SetupTab1() 419 { 420 {rgb_color clr = {216,216,216,255}; fTab1->SetViewColor(clr);} 421 fTab1->AddChild( fModuleSettingsBox = new BBox(BRect(183,11,434,285),"ModuleSettingsBox",B_FOLLOW_NONE,B_WILL_DRAW)); 422 fModuleSettingsBox->SetLabel("Module settings"); 423 fModuleSettingsBox->SetBorder(B_FANCY_BORDER); 424 425 fListView1 = new BListView(BRect(16,136,156,255),"ListView1",B_SINGLE_SELECTION_LIST); 426 fTab1->AddChild(new BScrollView("scroll_list",fListView1,B_FOLLOW_NONE,0,false,true)); 427 commonLookAndFeel(fModuleSettingsBox,false,false); 428 {rgb_color clr = {255,255,255,0}; fListView1->SetViewColor(clr);} 429 fListView1->SetListType(B_SINGLE_SELECTION_LIST); 430 431 // selection message for screensaver list 432 fListView1->SetSelectionMessage( new BMessage( kSaver_sel ) ); 433 434 fTab1->AddChild( fTestButton = new BButton(BRect(13,260,88,277),"TestButton","Test", new BMessage (kTest_btn))); 435 commonLookAndFeel(fTestButton,false,true); 436 fTestButton->SetLabel("Test"); 437 438 fTab1->AddChild( fAddButton = new BButton(BRect(98,260,173,277),"AddButton","Add...", new BMessage (kAdd_btn))); 439 commonLookAndFeel(fAddButton,false,true); 440 fAddButton->SetLabel("Add..."); 441 442 fTab1->AddChild(fPreviewDisplay = new PreviewView(BRect(20,15,150,120),"preview",&fPrefs)); 443 PopulateScreenSaverList(); 444 } 445 446 447 // Create the controls for the second tab 448 void 449 ScreenSaverWin::SetupTab2() 450 { 451 font_height height; 452 be_plain_font->GetHeight(&height); 453 int32 stringHeight = (int32)(height.ascent+height.descent); 454 int32 sliderHeight = 30; 455 int topEdge; 456 {rgb_color clr = {216,216,216,255}; fTab2->SetViewColor(clr);} 457 fTab2->AddChild( fEnableScreenSaverBox = new BBox(BRect(8,6,436,287),"EnableScreenSaverBox")); 458 commonLookAndFeel(fEnableScreenSaverBox,false,false); 459 460 fEnableCheckbox = new BCheckBox(BRect(0,0,90,stringHeight),"EnableCheckBox","Enable Screen Saver", new BMessage(kEnableScreenSaverChanged)); 461 fEnableScreenSaverBox->SetLabel(fEnableCheckbox); 462 fEnableScreenSaverBox->SetBorder(B_FANCY_BORDER); 463 464 // Run Module 465 topEdge=32; 466 fEnableScreenSaverBox->AddChild( fStringView1 = new BStringView(BRect(40,topEdge+2,130,topEdge+2+stringHeight),"StringView1","Run module")); 467 commonLookAndFeel(fStringView1,false,false); 468 fStringView1->SetText("Run module"); 469 fStringView1->SetAlignment(B_ALIGN_LEFT); 470 471 fEnableScreenSaverBox->AddChild( fRunSlider = new BSlider(BRect(135,topEdge,420,topEdge+sliderHeight),"RunSlider","minutes", new BMessage(kRunSliderChanged), 0, 25)); 472 fRunSlider->SetModificationMessage(new BMessage(kRunSliderChanged)); 473 commonLookAndFeel(fRunSlider,true,true); 474 float w,h; 475 fRunSlider->GetPreferredSize(&w,&h); 476 sliderHeight= (int32)h - 6; 477 478 // Turn Off 479 topEdge+=sliderHeight; 480 fEnableScreenSaverBox->AddChild( fTurnOffScreenCheckBox = new BCheckBox(BRect(20,topEdge-2,127,topEdge-2+stringHeight),"TurnOffScreenCheckBox","Turn off screen", new BMessage (kTab2_chg))); 481 commonLookAndFeel(fTurnOffScreenCheckBox,false,true); 482 fTurnOffScreenCheckBox->SetLabel("Turn off screen"); 483 fTurnOffScreenCheckBox->SetResizingMode(B_FOLLOW_NONE); 484 485 fEnableScreenSaverBox->AddChild( fTurnOffSlider = new BSlider(BRect(135,topEdge,420,topEdge+sliderHeight),"TurnOffSlider","", new BMessage(kTurnOffSliderChanged), 0, 25)); 486 fTurnOffSlider->SetModificationMessage(new BMessage(kTurnOffSliderChanged)); 487 commonLookAndFeel(fTurnOffSlider,true,true); 488 489 // Password 490 topEdge+=sliderHeight; 491 fEnableScreenSaverBox->AddChild( fPasswordCheckbox = new BCheckBox(BRect(20,topEdge-2,127,topEdge-2+stringHeight),"PasswordCheckbox","Password lock", new BMessage (kPasswordCheckbox))); 492 commonLookAndFeel(fPasswordCheckbox,false,true); 493 fPasswordCheckbox->SetLabel("Password lock"); 494 495 fEnableScreenSaverBox->AddChild( fPasswordSlider = new BSlider(BRect(135,topEdge,420,topEdge+sliderHeight),"PasswordSlider","", new BMessage(kPasswordSliderChanged), 0, 25)); 496 fPasswordSlider->SetModificationMessage(new BMessage(kPasswordSliderChanged)); 497 commonLookAndFeel(fPasswordSlider,true,true); 498 499 topEdge+=sliderHeight - 6; 500 fEnableScreenSaverBox->AddChild( fPasswordButton = new BButton(BRect(335,topEdge,410,topEdge+24),"PasswordButton","Password...", new BMessage (kPwbutton))); 501 commonLookAndFeel(fPasswordButton,false,true); 502 fPasswordButton->SetLabel("Password..."); 503 504 // Bottom 505 506 fEnableScreenSaverBox->AddChild(fFadeNow=new MouseAreaView(BRect(20,205,80,260),"fadeNow")); 507 fEnableScreenSaverBox->AddChild(fFadeNever=new MouseAreaView(BRect(220,205,280,260),"fadeNever")); 508 509 fEnableScreenSaverBox->AddChild( fFadeNowString = new BStringView(BRect(90,215,193,230),"FadeNowString","Fade now when")); 510 commonLookAndFeel(fFadeNowString,false,false); 511 fFadeNowString->SetText("Fade now when"); 512 fFadeNowString->SetAlignment(B_ALIGN_LEFT); 513 514 fEnableScreenSaverBox->AddChild( fFadeNowString2 = new BStringView(BRect(90,233,193,248),"FadeNowString2","mouse is here")); 515 commonLookAndFeel(fFadeNowString2,false,false); 516 fFadeNowString2->SetText("mouse is here"); 517 fFadeNowString2->SetAlignment(B_ALIGN_LEFT); 518 519 fEnableScreenSaverBox->AddChild( fDontFadeString = new BStringView(BRect(290,215,387,230),"DontFadeString","Don't fade when")); 520 commonLookAndFeel(fDontFadeString,false,false); 521 fDontFadeString->SetText("Don't fade when"); 522 fDontFadeString->SetAlignment(B_ALIGN_LEFT); 523 524 fEnableScreenSaverBox->AddChild( fDontFadeString2 = new BStringView(BRect(290,233,387,248),"DontFadeString2","mouse is here")); 525 commonLookAndFeel(fDontFadeString2,false,false); 526 fDontFadeString2->SetText("mouse is here"); 527 fDontFadeString2->SetAlignment(B_ALIGN_LEFT); 528 } 529