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