xref: /haiku/src/preferences/screensaver/ScreenSaverWindow.cpp (revision f058feb72ffbcfc33564541734bf5061a0a7662d)
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