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
32const rgb_color kMediumBlue = {0, 0, 100};
33const rgb_color kWhite = {255, 255, 255};
34
35const char *kInConfigName = "InConfig";
36const char *kShelfArchiveName = "Shelf";
37
38
39// Inspired by the classic BeOS screensaver, of course
40class 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
60BScreenSaver *instantiate_screen_saver(BMessage *msg, image_id image)
61{
62	PRINT(("%s()\n", __FUNCTION__));
63	return new Shelf(msg, image);
64}
65
66
67Shelf::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
98void
99Shelf::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
159void
160Shelf::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
172status_t
173Shelf::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
216void
217Shelf::StopSaver()
218{
219	PRINT(("%p:%s()\n", this, __FUNCTION__));
220	//if (fShelf)
221		//delete fShelf;
222	//fShelf = NULL;
223}
224
225
226status_t
227Shelf::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
270void
271Shelf::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