xref: /haiku/src/apps/clock/cl_view.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
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 <float.h>
14 #include <math.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18 
19 #include <Alert.h>
20 #include <Application.h>
21 #include <Debug.h>
22 #include <Dragger.h>
23 #include <Entry.h>
24 #include <Resources.h>
25 #include <Roster.h>
26 
27 #include "clock.h"
28 #include "cl_view.h"
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 #ifdef __HAIKU__
52 	BResources rsrcs;
53 	error = rsrcs.SetToImage(&&dummy_label);
54 dummy_label:
55 	if (error == B_OK) {
56 		{
57 #else	// !__HAIKU__
58 	// Note: Since we can be run as replicant, we get our resources this way,
59 	// not via be_app->AppResources().
60 	error = be_roster->FindApp(app_signature, &ref);
61 	printf("be_roster->FindApp() returned %s\n", strerror(error));
62 	if (error == B_NO_ERROR) {
63 		BFile file(&ref, O_RDONLY);
64 		error = file.InitCheck();
65 		if (error == B_NO_ERROR) {
66 			BResources rsrcs(&file);
67 #endif	// !__HAIKU__
68 
69 			for (loop = 0; loop <= 8; loop++) {
70 				if ((picH = rsrcs.FindResource('PICT', loop+4, &len))) {
71 					fClockFace[loop] = new BBitmap(theRect, B_CMAP8);
72 					fClockFace[loop]->SetBits(picH,len,0, B_CMAP8);
73 					free(picH);
74 				}
75 			}
76 
77 			theRect.Set(0,0,15,15);
78 			if ((picH = rsrcs.FindResource('MICN', "center", &len))) {
79 				fCenter = new BBitmap(theRect, B_CMAP8);
80 				fCenter->SetBits(picH,len,0, B_CMAP8);
81 				free(picH);
82 			}
83 
84 			theRect.Set(0,0,2,2);
85 			if ((picH = rsrcs.FindResource('PICT', 13, &len))) {
86 				fInner = new BBitmap(theRect, B_CMAP8);
87 				fInner->SetBits(picH,len,0, B_CMAP8);
88 				free(picH);
89 			}
90 		}
91 	}
92 
93 	fMinutesRadius = mRadius;
94 	fHoursRadius = hRadius;
95 	fOffset = offset;
96 	fHours = 0;
97 	fMinutes = 0;
98 	fSeconds = 0;
99 	fShowSeconds = show;
100 
101 	index = 0;
102 
103 	//
104 	// Generate minutes points array
105 	//
106 	for (counter = 90; counter >= 0; counter -= 6,index++) {
107 		x = mRadius * cos(((360 - counter)/180.0) * 3.1415);
108 		x += 41;
109 		y = mRadius * sin(((360 - counter)/180.0) * 3.1415);
110 		y += 41;
111 		fMinutePoints[index].Set(x,y);
112 		x = hRadius * cos(((360 - counter)/180.0) * 3.1415);
113 		x += 41;
114 		y = hRadius * sin(((360 - counter)/180.0) * 3.1415);
115 		y += 41;
116 		fHourPoints[index].Set(x,y);
117 	}
118 	for (counter = 354; counter > 90; counter -= 6,index++) {
119 		x = mRadius * cos(((360 - counter)/180.0) * 3.1415);
120 		x += 41;
121 		y = mRadius * sin(((360 - counter)/180.0) * 3.1415);
122 		y += 41;
123 		fMinutePoints[index].Set(x,y);
124 		x = hRadius * cos(((360 - counter)/180.0) * 3.1415);
125 		x += 41;
126 		y = hRadius * sin(((360 - counter)/180.0) * 3.1415);
127 		y += 41;
128 		fHourPoints[index].Set(x,y);
129 	}
130 }
131 
132 
133 void
134 TOffscreenView::NextFace()
135 {
136 	fFace++;
137 	if (fFace > 8)
138 		fFace = 1;
139 };
140 
141 
142 void
143 TOffscreenView::AttachedToWindow()
144 {
145 	SetFontSize(18);
146 	SetFont(be_plain_font);
147 }
148 
149 
150 void
151 TOffscreenView::DrawX()
152 {
153 	ASSERT(Window());
154 
155 	if (Window()->Lock()) {
156 		if (fClockFace != NULL)
157 			DrawBitmap(fClockFace[fFace], BPoint(0, 0));
158 
159 		//
160 		// Draw hands
161 		//
162 		SetHighColor(0, 0, 0);
163 		int32 hours = fHours;
164 		if (hours >= 12)
165 			hours -= 12;
166 		hours *= 5;
167 		hours += (fMinutes / 12);
168 		SetDrawingMode(B_OP_OVER);
169 		StrokeLine(BPoint(fOffset, fOffset), fHourPoints[hours]);
170 
171 		if (fCenter != NULL)
172 			DrawBitmap(fCenter, BPoint(fOffset - 3, fOffset - 3));
173 		StrokeLine(BPoint(fOffset, fOffset), fMinutePoints[fMinutes]);
174 		SetHighColor(180, 180, 180);
175 		if (fShowSeconds)
176 			StrokeLine(BPoint(fOffset, fOffset), fMinutePoints[fSeconds]);
177 		SetDrawingMode(B_OP_COPY);
178 		if (fInner != NULL)
179 			DrawBitmap(fInner, BPoint(fOffset - 1, fOffset - 1));
180 		Sync();
181 		Window()->Unlock();
182 	}
183 }
184 
185 
186 TOffscreenView::~TOffscreenView()
187 {
188 	for (int32 counter = 0; counter <= 8; counter++)
189 		delete fClockFace[counter];
190 };
191 
192 
193 /*
194  * Onscreen view object
195  */
196 TOnscreenView::TOnscreenView(BRect rect, char *title,
197 	short mRadius, short hRadius, short offset)
198   	  :BView(rect, title, B_NOT_RESIZABLE,
199 		  B_WILL_DRAW | B_PULSE_NEEDED | B_DRAW_ON_CHILDREN)
200 {
201 	InitObject(rect, mRadius, hRadius, offset, 1, TRUE);
202 
203 	BRect r = rect;
204 	r.OffsetTo(B_ORIGIN);
205 	r.top = r.bottom - 7;
206 	r.left = r.right - 7;
207 
208 	BDragger *dw = new BDragger(r, this, 0);
209 	AddChild(dw);
210 }
211 
212 
213 void
214 TOnscreenView::InitObject(BRect rect, short mRadius, short hRadius,
215 	short offset, long face, bool show)
216 {
217 	fmRadius = mRadius;
218 	fhRadius = hRadius;
219 	fOffset = offset;
220 	fRect = rect;
221 	fOffscreenView = NULL;
222 	fOffscreen = NULL;
223 
224 	fOffscreenView = new TOffscreenView(rect, "freqd",mRadius,hRadius, offset, face, show);
225 	fOffscreen = new BBitmap(rect, B_CMAP8, true);
226 	if (fOffscreen != NULL && fOffscreen->Lock()) {
227 		fOffscreen->AddChild(fOffscreenView);
228 		fOffscreen->Unlock();
229 
230 		fOffscreenView->DrawX();
231 	}
232 }
233 
234 
235 TOnscreenView::~TOnscreenView()
236 {
237 	delete fOffscreen;
238 }
239 
240 
241 TOnscreenView::TOnscreenView(BMessage *data)
242 	: BView(data)
243 {
244 	InitObject(data->FindRect("bounds"), data->FindInt32("mRadius"),
245 		data->FindInt32("hRadius"), data->FindInt32("offset"),
246 		data->FindInt32("face"), data->FindBool("seconds"));
247 }
248 
249 
250 status_t
251 TOnscreenView::Archive(BMessage *data, bool deep) const
252 {
253 	inherited::Archive(data, deep);
254 	data->AddString("add_on", app_signature);
255 //+	data->AddString("add_on_path", "/boot/apps/Clock");
256 
257 	data->AddRect("bounds", Bounds());
258 	data->AddInt32("mRadius", fOffscreenView->fMinutesRadius);
259 	data->AddInt32("hRadius", fOffscreenView->fHoursRadius);
260 	data->AddInt32("offset", fOffscreenView->fOffset);
261 	data->AddBool("seconds", fOffscreenView->fShowSeconds);
262 	data->AddInt32("face", fOffscreenView->fFace);
263 	return 0;
264 }
265 
266 
267 BArchivable *
268 TOnscreenView::Instantiate(BMessage *data)
269 {
270 	if (!validate_instantiation(data, "TOnscreenView"))
271 		return NULL;
272 	return new TOnscreenView(data);
273 }
274 
275 
276 void
277 TOnscreenView::AttachedToWindow()
278 {
279 //+	PRINT(("InitData m=%d, h=%d, offset=%d\n", fmRadius, fhRadius, fOffset));
280 //+	PRINT_OBJECT(fRect);
281 }
282 
283 
284 void
285 TOnscreenView::Pulse()
286 {
287 	short		hours,minutes,seconds;
288 	struct tm	*loctime;
289 	time_t		current;
290 
291 	ASSERT(fOffscreen);
292 	ASSERT(fOffscreenView);
293 	current = time(0);
294 	loctime = localtime(&current);
295 	hours = loctime->tm_hour;
296 	minutes = loctime->tm_min;
297 	seconds = loctime->tm_sec;
298 
299 	if ((fOffscreenView->fShowSeconds && (seconds != fOffscreenView->fSeconds)) ||
300 		(minutes != fOffscreenView->fMinutes)) {
301 			fOffscreenView->fHours = hours;
302 			fOffscreenView->fMinutes = minutes;
303 			fOffscreenView->fSeconds = seconds;
304 			BRect	b = Bounds();
305 			b.InsetBy(12,12);
306 			Draw(b);
307 	}
308 }
309 
310 
311 void
312 TOnscreenView::UseFace( short face )
313 {
314 	fOffscreenView->fFace = face;
315 	BRect	b = Bounds();
316 	b.InsetBy(12,12);
317 	Draw(b);
318 }
319 
320 
321 void
322 TOnscreenView::ShowSecs( bool secs )
323 {
324 	fOffscreenView->fShowSeconds = secs;
325 	BRect	b = Bounds();
326 	b.InsetBy(12,12);
327 	Invalidate(b);
328 }
329 
330 
331 short
332 TOnscreenView::ReturnFace( void )
333 {
334 	return(fOffscreenView->fFace);
335 }
336 
337 
338 short
339 TOnscreenView::ReturnSeconds( void )
340 {
341 	return(fOffscreenView->fShowSeconds);
342 }
343 
344 
345 void
346 TOnscreenView::Draw(BRect rect)
347 {
348 	ASSERT(fOffscreen);
349 	ASSERT(fOffscreenView);
350 
351 	if (fOffscreen->Lock()) {
352 		fOffscreenView->DrawX();			// Composite the clock offscreen...
353 		DrawBitmap(fOffscreen, rect, rect);
354 		fOffscreen->Unlock();
355 	}
356 };
357 
358 
359 void
360 TOnscreenView::MouseDown( BPoint point )
361 {
362 	BPoint	cursor;
363 	ulong	buttons;
364 	BRect	bounds = Bounds();
365 
366 	GetMouse(&cursor,&buttons);
367 	if (buttons & B_SECONDARY_MOUSE_BUTTON) {
368 		fOffscreenView->fShowSeconds = !fOffscreenView->fShowSeconds;
369 		be_app->PostMessage(SHOW_SECONDS);
370 		bounds.InsetBy(12,12);
371 		Invalidate(bounds);
372 	} else {
373 		fOffscreenView->NextFace();
374 		Invalidate(bounds);
375 		BView *child = ChildAt(0);
376 		if (child)
377 			child->Invalidate();
378 	}
379 };
380 
381 
382 void
383 TOnscreenView::MessageReceived(BMessage *msg)
384 {
385 	switch(msg->what) {
386 		case B_ABOUT_REQUESTED:
387 			(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();
388 			break;
389 		default:
390 			inherited::MessageReceived(msg);
391 	}
392 }
393