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