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