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