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