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