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
23TOffscreenView::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);
39dummy_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
116void
117TOffscreenView::NextFace()
118{
119	fFace++;
120	if (fFace > 8)
121		fFace = 1;
122};
123
124
125void
126TOffscreenView::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
161TOffscreenView::~TOffscreenView()
162{
163	for (int32 counter = 0; counter <= 8; counter++)
164		delete fClockFace[counter];
165};
166
167
168//	#pragma mark -
169
170
171TOnscreenView::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
188void
189TOnscreenView::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
203TOnscreenView::~TOnscreenView()
204{
205	delete fOffscreen;
206}
207
208
209TOnscreenView::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
220status_t
221TOnscreenView::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
249BArchivable *
250TOnscreenView::Instantiate(BMessage *data)
251{
252	if (!validate_instantiation(data, "TOnscreenView"))
253		return NULL;
254	return new TOnscreenView(data);
255}
256
257
258void
259TOnscreenView::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
283void
284TOnscreenView::UseFace(short face)
285{
286	fOffscreenView->fFace = face;
287	BRect b = Bounds();
288	b.InsetBy(12,12);
289	Draw(b);
290}
291
292
293void
294TOnscreenView::ShowSecs(bool secs)
295{
296	fOffscreenView->fShowSeconds = secs;
297	BRect b = Bounds();
298	b.InsetBy(12,12);
299	Invalidate(b);
300}
301
302
303short
304TOnscreenView::ReturnFace()
305{
306	return fOffscreenView->fFace;
307}
308
309
310short
311TOnscreenView::ReturnSeconds()
312{
313	return fOffscreenView->fShowSeconds;
314}
315
316
317void
318TOnscreenView::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
332void
333TOnscreenView::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
354void
355TOnscreenView::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