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