1/*
2 * Copyright (c) 2008-2009 Gerasim Troeglazov (3dEyes**). All Rights Reserved.
3 * This file may be used under the terms of the MIT License.
4 */
5
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <time.h>
10
11#include <Bitmap.h>
12#include <Catalog.h>
13#include <Polygon.h>
14#include <Screen.h>
15#include <ScreenSaver.h>
16#include <StringView.h>
17#include <View.h>
18
19
20class Clock : public BScreenSaver
21{
22public:
23					Clock(BMessage *message, image_id id);
24	void			StartConfig(BView *view);
25	status_t		StartSaver(BView *view, bool preview);
26	void			Draw(BView *view, int32 frame);
27private:
28	void 			_drawBlock(BView *view, float x, float y, float alpha,
29						float size);
30	void 			_drawArrow(BView *view, float x0, float y0, float angle,
31						float length, float coeff, float width);
32	float 			centerX, centerY;
33};
34
35
36extern "C" _EXPORT BScreenSaver *instantiate_screen_saver(BMessage *message,
37	image_id image)
38{
39	return new Clock(message, image);
40}
41
42
43Clock::Clock(BMessage *message, image_id image)
44	:
45	BScreenSaver(message, image)
46{
47	B_TRANSLATE_MARK_SYSTEM_NAME_VOID("SimpleClock");
48}
49
50
51void
52Clock::StartConfig(BView *view)
53{
54	BStringView	*aboutView = new BStringView(BRect(10, 10, 200, 35),
55		B_EMPTY_STRING, "Simple Clock");
56	aboutView->SetFont(be_bold_font);
57	aboutView->SetFontSize(15);
58	view->AddChild(aboutView);
59	aboutView = new BStringView(BRect(10, 40, 200, 65),
60		B_EMPTY_STRING, " Ver 1.0, ��3dEyes**");
61	view->AddChild(aboutView);
62}
63
64
65status_t
66Clock::StartSaver(BView *view, bool)
67{
68	SetTickSize(1000000);
69	return B_OK;
70}
71
72
73void
74Clock::Draw(BView *view, int32)
75{
76	BScreen screenView;
77	BBitmap bufferBitmap(view->Bounds(), screenView.ColorSpace(), true);
78	BView offscreenView(view->Bounds(), NULL, 0, 0);
79	bufferBitmap.AddChild(&offscreenView);
80	bufferBitmap.Lock();
81
82	float width = view->Bounds().Width();
83	float height = view->Bounds().Height();
84	float zoom = (height / 1024.0) * 0.65;
85
86	time_t timeInfo;
87	time(&timeInfo);
88	struct tm *nowTime = localtime(&timeInfo);
89
90	float secondVal = nowTime->tm_sec;
91	float minuteVal = nowTime->tm_min + (secondVal / 60.0);
92	float hourVal = nowTime->tm_hour + (minuteVal / 60.0);
93
94	offscreenView.SetHighColor(0, 0, 0);
95	offscreenView.SetLowColor(0, 0, 0);
96	offscreenView.FillRect(offscreenView.Bounds());
97
98	offscreenView.SetHighColor(200, 200, 200);
99
100	centerX = width / 2.0;
101	centerY = height / 2.0;
102
103	float markAngle = 0;
104	float markRadius = 510.0 * zoom;
105
106	for(int mark = 0; mark < 60; mark++, markAngle += (2 * M_PI) / 60) {
107		float x = centerX + markRadius * cos(markAngle);
108		float y = centerY + markRadius * sin(markAngle);
109		_drawBlock(&offscreenView, x, y, markAngle, 14.0 * zoom);
110	}
111
112	offscreenView.SetHighColor(255, 255, 255);
113
114	markAngle = 0;
115	markRadius = 500.0 * zoom;
116
117	for (int mark = 0; mark < 12; mark++, markAngle += (2 * M_PI) / 12) {
118		float x = centerX + markRadius * cos(markAngle);
119		float y = centerY + markRadius * sin(markAngle);
120		_drawBlock(&offscreenView, x, y, markAngle, 32 * zoom);
121	}
122
123	offscreenView.SetHighColor(255, 255, 255);
124	_drawArrow(&offscreenView, centerX, centerY,
125		((2 * M_PI / 60) * minuteVal) - (M_PI / 2), 220 * zoom, 1, 8 * zoom);
126
127	_drawArrow(&offscreenView, centerX, centerY,
128		((2 * M_PI / 12) * hourVal) - (M_PI / 2), 140 * zoom, 1, 14 * zoom);
129	offscreenView.FillEllipse(BPoint(centerX, centerY),
130		24 * zoom, 24 * zoom);
131
132	offscreenView.SetHighColor(250, 20, 20);
133	_drawArrow(&offscreenView, centerX, centerY,
134		((2 * M_PI / 60) * secondVal) - (M_PI / 2), 240 * zoom, 1, 4 * zoom);
135	offscreenView.FillEllipse(BPoint(centerX, centerY),
136		20 * zoom, 20 * zoom);
137
138	offscreenView.Sync();
139	bufferBitmap.Unlock();
140	view->DrawBitmap(&bufferBitmap);
141	bufferBitmap.RemoveChild(&offscreenView);
142}
143
144
145void
146Clock::_drawBlock(BView *view, float x, float y, float alpha, float size)
147{
148	float blockAngles[4] = {alpha - (M_PI / 12), alpha + (M_PI / 12),
149		alpha + M_PI - (M_PI / 12), alpha + M_PI + (M_PI / 12)};
150
151	BPoint blockPoints[4];
152	for (int index = 0; index < 4; index++) {
153		blockPoints[index].x = x + size * cos(blockAngles[index]);
154		blockPoints[index].y = y + size * sin(blockAngles[index]);
155	}
156	view->FillPolygon(&blockPoints[0], 4);
157}
158
159
160void
161Clock::_drawArrow(BView *view, float x0, float y0, float angle, float length,
162	float coeff, float width)
163{
164	float alpha = width / length;
165
166	float x = x0 + length * cos(angle);
167	float y = y0 + length * sin(angle);
168
169	float size = length * coeff;
170
171	float blockAngles[4] = {angle - alpha, angle + alpha,
172		angle + M_PI - alpha, angle + M_PI + alpha};
173
174	BPoint blockPoints[4];
175	for(int index = 0; index < 4; index++) {
176		blockPoints[index].x = x + size * cos(blockAngles[index]);
177		blockPoints[index].y = y + size * sin(blockAngles[index]);
178	}
179	view->FillPolygon(&blockPoints[0], 4);
180}
181