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