xref: /haiku/src/add-ons/screen_savers/shelf/Shelf.cpp (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
1 /*
2  * Copyright 2007-2012, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ryan Leavengood
7  *		François Revol <revol@free.fr>
8  */
9 
10 
11 #include <Application.h>
12 #include <Alert.h>
13 #include <Button.h>
14 #include <Catalog.h>
15 #include <ControlLook.h>
16 #include <Font.h>
17 #include <LayoutBuilder.h>
18 #include <Screen.h>
19 #include <ScreenSaver.h>
20 #include <Shelf.h>
21 #include <String.h>
22 #include <StringView.h>
23 #include <View.h>
24 #include <Window.h>
25 #include <Debug.h>
26 
27 
28 #undef B_TRANSLATION_CONTEXT
29 #define B_TRANSLATION_CONTEXT "Shelf Screen Saver"
30 
31 
32 const rgb_color kMediumBlue = {0, 0, 100};
33 const rgb_color kWhite = {255, 255, 255};
34 
35 const char *kInConfigName = "InConfig";
36 const char *kShelfArchiveName = "Shelf";
37 
38 
39 // Inspired by the classic BeOS screensaver, of course
40 class Shelf : public BScreenSaver
41 {
42 	public:
43 					Shelf(BMessage *archive, image_id);
44 		void		Draw(BView *view, int32 frame);
45 		void		StartConfig(BView *view);
46 		void		StopConfig();
47 		status_t	StartSaver(BView *view, bool preview);
48 		void		StopSaver();
49 		status_t	SaveState(BMessage *state) const;
50 
51 	private:
52 		BShelf		*fShelf;
53 		BWindow		*fConfigWindow;
54 		bool		fInConfig;
55 		bool		fInEdit;
56 		BMallocIO	fShelfData;
57 };
58 
59 
60 BScreenSaver *instantiate_screen_saver(BMessage *msg, image_id image)
61 {
62 	PRINT(("%s()\n", __FUNCTION__));
63 	return new Shelf(msg, image);
64 }
65 
66 
67 Shelf::Shelf(BMessage *archive, image_id id)
68  :	BScreenSaver(archive, id)
69  ,	fShelf(NULL)
70  ,	fConfigWindow(NULL)
71  ,	fInConfig(false)
72  ,	fInEdit(false)
73  ,	fShelfData()
74 {
75 	archive->PrintToStream();
76 	if (archive->FindBool(kInConfigName, &fInConfig) < B_OK)
77 		fInConfig = false;
78 
79 	status_t status;
80 	const void *data;
81 	ssize_t length;
82 
83 	status = archive->FindData(kShelfArchiveName, 'shlf', &data, &length);
84 	if (status == B_OK) {
85 		fShelfData.WriteAt(0LL, data, length);
86 		fShelfData.Seek(SEEK_SET, 0LL);
87 	}
88 
89 
90 /*
91 	if (fInConfig) {
92 		fInEdit = true;
93 		fInConfig = false;
94 	}
95 */}
96 
97 
98 void
99 Shelf::StartConfig(BView *view)
100 {
101 	PRINT(("%p:%s()\n", this, __FUNCTION__));
102 	fInConfig = true;
103 
104 	BStringView* titleString = new BStringView("Title",
105 		B_TRANSLATE("Shelf"));
106 	titleString->SetFont(be_bold_font);
107 
108 	BStringView* copyrightString = new BStringView("Copyright",
109 		B_TRANSLATE("© 2012 François Revol."));
110 
111 	BTextView* helpText = new BTextView("Help Text");
112 	helpText->MakeEditable(false);
113 	helpText->SetViewColor(view->ViewColor());
114 	rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
115 	helpText->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
116 	BString help;
117 	help << B_TRANSLATE("Drop replicants on the full-screen window "
118 		"behind the preferences panel.");
119 	//help << "\n\n";
120 	//help << B_TRANSLATE("You can also drop colors.");
121 	helpText->SetText(help.String());
122 
123 	BLayoutBuilder::Group<>(view, B_VERTICAL, B_USE_HALF_ITEM_SPACING)
124 		.SetInsets(B_USE_DEFAULT_SPACING)
125 		.Add(titleString)
126 		.Add(copyrightString)
127 		.AddStrut(roundf(be_control_look->DefaultItemSpacing() / 2))
128 		.Add(helpText)
129 		.AddGlue()
130 	.End();
131 
132 	BScreen screen;
133 	fConfigWindow = new BWindow(screen.Frame(), "Shelf Config",
134 		B_UNTYPED_WINDOW, B_NOT_MOVABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE
135 		| B_NOT_MINIMIZABLE | B_NOT_RESIZABLE | B_AVOID_FRONT | B_AVOID_FOCUS);
136 
137 	BView *shelfView = new BView(fConfigWindow->Bounds(), "ShelfView",
138 		B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS);
139 	shelfView->SetViewColor(216, 216, 216, 0);
140 
141 	fConfigWindow->AddChild(shelfView);
142 
143 	fShelfData.Seek(SEEK_SET, 0LL);
144 	fShelf = new BShelf(&fShelfData, shelfView);
145 	fShelf->SetDisplaysZombies(true);
146 	fShelfData.Seek(SEEK_SET, 0LL);
147 
148 	// start the Looper
149 	fConfigWindow->Show();
150 
151 	fConfigWindow->Lock();
152 	fConfigWindow->SendBehind(view->Window());
153 	fConfigWindow->Unlock();
154 
155 	//"\nDrop replicants on me!"
156 }
157 
158 
159 void
160 Shelf::StopConfig()
161 {
162 	fInConfig = false;
163 	PRINT(("%p:%s()\n", this, __FUNCTION__));
164 	fConfigWindow->Lock();
165 	fConfigWindow->Quit();
166 	fShelf = NULL;
167 
168 	BScreenSaver::StopConfig();
169 }
170 
171 
172 status_t
173 Shelf::StartSaver(BView *view, bool preview)
174 {
175 	PRINT(("%p:%s(, %d)\n", this, __FUNCTION__, preview));
176 	if (!preview) {
177 		view->SetViewColor(216, 216, 216, 0);
178 		fShelfData.Seek(SEEK_SET, 0LL);
179 		fShelf = new BShelf(&fShelfData, view);
180 
181 	}
182 	BString s;
183 	s << "preview: " << preview << " ";
184 	s << "BView:Name: " << view->Name() << " ";
185 	s << "BApp:Name: " << be_app->Name();
186 
187 	PRINT(("%p:%s:%s\n", this, __FUNCTION__, s.String()));
188 	//BAlert *a = new BAlert("debug", s.String(), "OK");
189 	//a->Go();
190 	return B_ERROR;
191 #if 0
192 	float width = view->Bounds().Width();
193 	float height = view->Bounds().Height();
194 
195 	BFont font;
196 	view->GetFont(&font);
197 	font.SetSize(height / 2.5);
198 	view->SetFont(&font);
199 
200 	BRect rect;
201 	escapement_delta delta;
202 	delta.nonspace = 0;
203 	delta.space = 0;
204 	// If anyone has suggestions for how to clean this up, speak up
205 	font.GetBoundingBoxesForStrings(&fLine1, 1, B_SCREEN_METRIC, &delta, &rect);
206 	float y = ((height - (rect.Height() * 2 + height / 10)) / 2) + rect.Height();
207 	fLine1Start.Set((width - rect.Width()) / 2, y);
208 	font.GetBoundingBoxesForStrings(&fLine2, 1, B_SCREEN_METRIC, &delta, &rect);
209 	fLine2Start.Set((width - rect.Width()) / 2, y + rect.Height() + height / 10);
210 
211 #endif
212 	return B_OK;
213 }
214 
215 
216 void
217 Shelf::StopSaver()
218 {
219 	PRINT(("%p:%s()\n", this, __FUNCTION__));
220 	//if (fShelf)
221 		//delete fShelf;
222 	//fShelf = NULL;
223 }
224 
225 
226 status_t
227 Shelf::SaveState(BMessage *state) const
228 {
229 	status_t status;
230 
231 	PRINT(("%p:%s()\n", this, __FUNCTION__));
232 	state->PrintToStream();
233 
234 	if (fInConfig)
235 		state->AddBool(kInConfigName, fInConfig);
236 	if (!fInConfig)
237 		state->RemoveData(kInConfigName);
238 	if (fInConfig && fShelf) {
239 		status = state->AddBool("got it", true);
240 
241 		fShelf->LockLooper();
242 		status = fShelf->Save();
243 		fShelf->UnlockLooper();
244 		if (status < B_OK)
245 			return status;
246 		status = state->AddData(kShelfArchiveName, 'shlf', fShelfData.Buffer(),
247 			fShelfData.BufferLength());
248 
249 //		return B_OK;
250 //fShelfData.SetSize(0LL);
251 #if 0
252 		BMallocIO mio;
253 		status = fShelf->SetSaveLocation(&mio);
254 		if (status < B_OK)
255 			return status;
256 		status = fShelf->Save();
257 		fShelf->SetSaveLocation((BDataIO *)NULL);
258 		if (status < B_OK)
259 			return status;
260 		status = state->AddData(kShelfArchiveName, 'shlf', mio.Buffer(),
261 			mio.BufferLength());
262 #endif
263 		if (status < B_OK)
264 			return status;
265 	}
266 	return B_OK;
267 }
268 
269 
270 void
271 Shelf::Draw(BView *view, int32 frame)
272 {
273 	PRINT(("%p:%s(, %" B_PRId32 ")\n", this, __FUNCTION__, frame));
274 	BScreenSaver::Draw(view, frame);
275 #if 0
276 	if (frame == 0) {
277 		// fill with blue on first frame
278 		view->SetLowColor(kMediumBlue);
279 		view->FillRect(view->Bounds(), B_SOLID_LOW);
280 
281 		// Set tick size to 500,000 microseconds = 0.5 second
282 		SetTickSize(500000);
283 	} else {
284 		// Drawing the background color every other frame to make the text blink
285 		if (frame % 2 == 1)
286 			view->SetHighColor(kWhite);
287 		else
288 			view->SetHighColor(kMediumBlue);
289 
290 		view->DrawString(fLine1, fLine1Start);
291 		view->DrawString(fLine2, fLine2Start);
292 	}
293 #endif
294 }
295 
296 
297