xref: /haiku/src/apps/clock/cl_view.cpp (revision 5d9e40fe9252c8f9c5e5e41594545bfa4419fcc7)
1 /*
2 
3 	cl_view.cpp
4 
5 */
6 
7 /*
8 	Copyright 1999, Be Incorporated.   All Rights Reserved.
9 	This file may be used under the terms of the Be Sample Code License.
10 */
11 
12 #define DEBUG 1
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #include <time.h>
17 #include "clock.h"
18 #include "cl_view.h"
19 #include <float.h>
20 #include <math.h>
21 
22 #include <Debug.h>
23 #include <Application.h>
24 #include <Roster.h>
25 #include <Alert.h>
26 #include <Entry.h>
27 #include <Resources.h>
28 
29 /* ---------------------------------------------------------------- */
30 
31 TOffscreenView::TOffscreenView(BRect frame, char *name, short mRadius,
32 						short hRadius, short offset, long face, bool show)
33 	   		   :BView(frame, name, B_NOT_RESIZABLE, B_WILL_DRAW)
34 {
35 	BRect			theRect;
36 	short			loop;
37 	void			*picH;
38 	size_t			len;
39 	float			counter;
40 	short			index;
41 	float			x,y;
42 	entry_ref		ref;
43 	long			error;
44 
45 	fFace = face;
46 	theRect.Set(0,0,82,82);
47 
48 	for (index = 0; index <= 8; index++)
49 		fClockFace[index] = NULL;
50 
51 //+	error = get_ref_for_path("/boot/apps/Clock", &ref);
52 	error = be_roster->FindApp(app_signature, &ref);
53 
54 	if (error == B_NO_ERROR) {
55 		BFile	file(&ref, O_RDONLY);
56 		if (file.InitCheck() == B_NO_ERROR) {
57 			BResources	rsrcs(&file);
58 			error = 0;
59 
60 			for (loop = 0; loop <= 8; loop++) {
61 				if ((picH = rsrcs.FindResource('PICT', loop+4, &len))) {
62 					fClockFace[loop] = new BBitmap(theRect,B_COLOR_8_BIT);
63 					fClockFace[loop]->SetBits(picH,len,0,B_COLOR_8_BIT);
64 					free(picH);
65 				} else {
66 					error = 1;
67 				}
68 			}
69 
70 			theRect.Set(0,0,15,15);
71 			if ((picH = rsrcs.FindResource('MICN', "center", &len))) {
72 				fCenter = new BBitmap(theRect,B_COLOR_8_BIT);
73 				fCenter->SetBits(picH,len,0,B_COLOR_8_BIT);
74 				free(picH);
75 			} else {
76 				error = 1;
77 			}
78 
79 			theRect.Set(0,0,2,2);
80 			if ((picH = rsrcs.FindResource('PICT', 13, &len))) {
81 				fInner = new BBitmap(theRect,B_COLOR_8_BIT);
82 				fInner->SetBits(picH,len,0,B_COLOR_8_BIT);
83 				free(picH);
84 			} else {
85 				error = 1;
86 			}
87 
88 			if (error) {
89 				// ??? yikes. This is terrible. No good way to signal error
90 				// from here. How do we properly cleanup up here? Need to
91 				// make sure the app_server side also gets cleaned up!
92 
93 				BAlert *alert = new BAlert("Error", "Clock: Could not find necessary resources.", "Quit");
94 				alert->Go();
95 				delete this;
96 				exit(1);
97 			}
98 		}
99 	} else {
100 	 	exit(1);
101 	}
102 
103 	fMinutesRadius = mRadius;
104 	fHoursRadius = hRadius;
105 	fOffset = offset;
106 	fHours = 0;
107 	fMinutes = 0;
108 	fSeconds = 0;
109 	fShowSeconds = show;
110 
111 	index = 0;
112 
113 	//
114 	// Generate minutes points array
115 	//
116 	for (counter = 90; counter >= 0; counter -= 6,index++) {
117 		x = mRadius * cos(((360 - counter)/180.0) * 3.1415);
118 		x += 41;
119 		y = mRadius * sin(((360 - counter)/180.0) * 3.1415);
120 		y += 41;
121 		fMinutePoints[index].Set(x,y);
122 		x = hRadius * cos(((360 - counter)/180.0) * 3.1415);
123 		x += 41;
124 		y = hRadius * sin(((360 - counter)/180.0) * 3.1415);
125 		y += 41;
126 		fHourPoints[index].Set(x,y);
127 	}
128 	for (counter = 354; counter > 90; counter -= 6,index++) {
129 		x = mRadius * cos(((360 - counter)/180.0) * 3.1415);
130 		x += 41;
131 		y = mRadius * sin(((360 - counter)/180.0) * 3.1415);
132 		y += 41;
133 		fMinutePoints[index].Set(x,y);
134 		x = hRadius * cos(((360 - counter)/180.0) * 3.1415);
135 		x += 41;
136 		y = hRadius * sin(((360 - counter)/180.0) * 3.1415);
137 		y += 41;
138 		fHourPoints[index].Set(x,y);
139 	}
140 }
141 
142 /* ---------------------------------------------------------------- */
143 
144 void TOffscreenView::NextFace()
145 {
146 	fFace++;
147 	if (fFace > 8)
148 		fFace = 1;
149 };
150 
151 /* ---------------------------------------------------------------- */
152 
153 void TOffscreenView::AttachedToWindow()
154 {
155 	SetFontSize(18);
156 	SetFont(be_plain_font);
157 }
158 
159 /* ---------------------------------------------------------------- */
160 
161 void TOffscreenView::DrawX()
162 {
163 //BRect		bound;
164 short		hours;
165 
166 	ASSERT(Window());
167 
168 	if (Window()->Lock()) {
169 		DrawBitmap(fClockFace[fFace],BPoint(0,0));
170 
171 		//
172 		// Draw hands
173 		//
174 		SetHighColor(0,0,0);
175 		hours = fHours;
176 		if (hours >= 12)
177 			hours -= 12;
178 		hours *= 5;
179 		hours += (fMinutes / 12);
180 		StrokeLine(BPoint(fOffset,fOffset),fHourPoints[hours]);
181 		SetDrawingMode(B_OP_OVER);
182 
183 		DrawBitmap(fCenter,BPoint(fOffset-3,fOffset-3));
184 		SetDrawingMode(B_OP_COPY);
185 		StrokeLine(BPoint(fOffset,fOffset),fMinutePoints[fMinutes]);
186 		SetHighColor(180,180,180);
187 		if (fShowSeconds)
188 			StrokeLine(BPoint(fOffset,fOffset),fMinutePoints[fSeconds]);
189 		DrawBitmap(fInner,BPoint(fOffset-1,fOffset-1));
190 		Sync();
191 		Window()->Unlock();
192 	}
193 }
194 
195 /* ---------------------------------------------------------------- */
196 
197 TOffscreenView::~TOffscreenView()
198 {
199 	short	counter;
200 
201 	for (counter = 0; counter <= 8; counter++)
202 		delete fClockFace[counter];
203 };
204 
205 /* ---------------------------------------------------------------- */
206 /* ---------------------------------------------------------------- */
207 /* ---------------------------------------------------------------- */
208 
209 #include <Dragger.h>
210 
211 /*
212  * Onscreen view object
213  */
214 TOnscreenView::TOnscreenView(BRect rect, char *title,
215 	short mRadius, short hRadius, short offset)
216   	  :BView(rect, title, B_NOT_RESIZABLE,
217 		  B_WILL_DRAW | B_PULSE_NEEDED | B_DRAW_ON_CHILDREN)
218 {
219 	InitObject(rect, mRadius, hRadius, offset, 1, TRUE);
220 
221 	BRect r = rect;
222 	r.OffsetTo(B_ORIGIN);
223 	r.top = r.bottom - 7;
224 	r.left = r.right - 7;
225 
226 	BDragger *dw = new BDragger(r, this, 0);
227 	AddChild(dw);
228 }
229 
230 void TOnscreenView::InitObject(BRect rect, short mRadius, short hRadius,
231 	short offset, long face, bool show)
232 {
233 	fmRadius = mRadius;
234 	fhRadius = hRadius;
235 	fOffset = offset;
236 	fRect = rect;
237 	OffscreenView = NULL;
238 	Offscreen = NULL;
239 
240 #if 1
241 	OffscreenView = new TOffscreenView(rect, "freqd",mRadius,hRadius,
242 										offset, face, show);
243 	Offscreen = new BBitmap(rect, B_COLOR_8_BIT, TRUE);
244 	Offscreen->Lock();
245 	Offscreen->AddChild(OffscreenView);
246 	Offscreen->Unlock();
247 	OffscreenView->DrawX();
248 #endif
249 }
250 
251 /* ---------------------------------------------------------------- */
252 
253 TOnscreenView::~TOnscreenView()
254 {
255 	delete Offscreen;
256 }
257 
258 /* ---------------------------------------------------------------- */
259 
260 TOnscreenView::TOnscreenView(BMessage *data)
261 	: BView(data)
262 {
263 	InitObject(data->FindRect("bounds"), data->FindInt32("mRadius"),
264 		data->FindInt32("hRadius"), data->FindInt32("offset"),
265 		data->FindInt32("face"), data->FindBool("seconds"));
266 }
267 
268 /* ---------------------------------------------------------------- */
269 
270 status_t TOnscreenView::Archive(BMessage *data, bool deep) const
271 {
272 	inherited::Archive(data, deep);
273 	data->AddString("add_on", app_signature);
274 //+	data->AddString("add_on_path", "/boot/apps/Clock");
275 
276 	data->AddRect("bounds", Bounds());
277 	data->AddInt32("mRadius", OffscreenView->fMinutesRadius);
278 	data->AddInt32("hRadius", OffscreenView->fHoursRadius);
279 	data->AddInt32("offset", OffscreenView->fOffset);
280 	data->AddBool("seconds", OffscreenView->fShowSeconds);
281 	data->AddInt32("face", OffscreenView->fFace);
282 	return 0;
283 }
284 
285 /* ---------------------------------------------------------------- */
286 
287 BArchivable *TOnscreenView::Instantiate(BMessage *data)
288 {
289 	if (!validate_instantiation(data, "TOnscreenView"))
290 		return NULL;
291 	return new TOnscreenView(data);
292 }
293 
294 /* ---------------------------------------------------------------- */
295 
296 void TOnscreenView::AttachedToWindow()
297 {
298 //+	PRINT(("InitData m=%d, h=%d, offset=%d\n", fmRadius, fhRadius, fOffset));
299 //+	PRINT_OBJECT(fRect);
300 }
301 
302 /* ---------------------------------------------------------------- */
303 
304 void TOnscreenView::Pulse()
305 {
306 	short		hours,minutes,seconds;
307 	struct tm	*loctime;
308 	time_t		current;
309 
310 	ASSERT(Offscreen);
311 	ASSERT(OffscreenView);
312 	current = time(0);
313 	loctime = localtime(&current);
314 	hours = loctime->tm_hour;
315 	minutes = loctime->tm_min;
316 	seconds = loctime->tm_sec;
317 
318 	if ((OffscreenView->fShowSeconds && (seconds != OffscreenView->fSeconds)) ||
319 		(minutes != OffscreenView->fMinutes)) {
320 			OffscreenView->fHours = hours;
321 			OffscreenView->fMinutes = minutes;
322 			OffscreenView->fSeconds = seconds;
323 			BRect	b = Bounds();
324 			b.InsetBy(12,12);
325 			Draw(b);
326 	}
327 }
328 
329 /* ---------------------------------------------------------------- */
330 
331 void TOnscreenView::UseFace( short face )
332 {
333 	OffscreenView->fFace = face;
334 	BRect	b = Bounds();
335 	b.InsetBy(12,12);
336 	Draw(b);
337 }
338 
339 /* ---------------------------------------------------------------- */
340 
341 void TOnscreenView::ShowSecs( bool secs )
342 {
343 	OffscreenView->fShowSeconds = secs;
344 	BRect	b = Bounds();
345 	b.InsetBy(12,12);
346 	Invalidate(b);
347 }
348 
349 /* ---------------------------------------------------------------- */
350 
351 short TOnscreenView::ReturnFace( void )
352 {
353 	return(OffscreenView->fFace);
354 }
355 
356 /* ---------------------------------------------------------------- */
357 
358 short TOnscreenView::ReturnSeconds( void )
359 {
360 	return(OffscreenView->fShowSeconds);
361 }
362 
363 /* ---------------------------------------------------------------- */
364 
365 void TOnscreenView::Draw(BRect rect)
366 {
367 	time_t		current;
368 	ASSERT(Offscreen);
369 	ASSERT(OffscreenView);
370 
371 	bool b = Offscreen->Lock();
372 	ASSERT(b);
373 	OffscreenView->DrawX();			// Composite the clock offscreen...
374 	DrawBitmap(Offscreen, rect, rect);
375 	Offscreen->Unlock();
376 
377 	current = time(0);
378 };
379 
380 /* ---------------------------------------------------------------- */
381 
382 void TOnscreenView::MouseDown( BPoint point )
383 {
384 	BPoint	cursor;
385 	ulong	buttons;
386 	BRect	bounds = Bounds();
387 
388 	GetMouse(&cursor,&buttons);
389 	if (buttons & 0x2) {
390 		OffscreenView->fShowSeconds = !OffscreenView->fShowSeconds;
391 		be_app->PostMessage(SHOW_SECONDS);
392 		bounds.InsetBy(12,12);
393 		Draw(bounds);
394 	} else {
395 		OffscreenView->NextFace();
396 		Draw(bounds);
397 		BView *c = ChildAt(0);
398 		if (c)
399 			c->Draw(c->Bounds());
400 	}
401 };
402 
403 /* ---------------------------------------------------------------- */
404 
405 void
406 TOnscreenView::MessageReceived(BMessage *msg)
407 {
408 	switch(msg->what) {
409 		case B_ABOUT_REQUESTED:
410 			(new BAlert("About Clock", "Clock (The Replicant version)\n\n(C)2002 OpenBeOS\n\nOriginally coded  by the folks at Be.\n  Copyright Be Inc., 1991-1998","OK"))->Go();
411 			break;
412 		default:
413 			inherited::MessageReceived(msg);
414 	}
415 }
416