xref: /haiku/src/add-ons/screen_savers/simpleclock/SimpleClock.cpp (revision 25a7b01d15612846f332751841da3579db313082)
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 
20 class Clock : public BScreenSaver
21 {
22 public:
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);
27 private:
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 
instantiate_screen_saver(BMessage * message,image_id image)36 extern "C" _EXPORT BScreenSaver *instantiate_screen_saver(BMessage *message,
37 	image_id image)
38 {
39 	return new Clock(message, image);
40 }
41 
42 
Clock(BMessage * message,image_id image)43 Clock::Clock(BMessage *message, image_id image)
44 	:
45 	BScreenSaver(message, image)
46 {
47 	B_TRANSLATE_MARK_SYSTEM_NAME_VOID("SimpleClock");
48 }
49 
50 
51 void
StartConfig(BView * view)52 Clock::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 
65 status_t
StartSaver(BView * view,bool)66 Clock::StartSaver(BView *view, bool)
67 {
68 	SetTickSize(1000000);
69 	return B_OK;
70 }
71 
72 
73 void
Draw(BView * view,int32)74 Clock::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 
145 void
_drawBlock(BView * view,float x,float y,float alpha,float size)146 Clock::_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 
160 void
_drawArrow(BView * view,float x0,float y0,float angle,float length,float coeff,float width)161 Clock::_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