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