1 /* 2 * Copyright 2004-2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Mike Berg (inseculous) 7 */ 8 9 /*! Notes: OffscreenClock borrows heavily from the clock source. */ 10 11 12 #include "AnalogClock.h" 13 #include "Bitmaps.h" 14 #include "TimeMessages.h" 15 16 #include <Alert.h> 17 #include <Bitmap.h> 18 #include <Debug.h> 19 #include <Dragger.h> 20 #include <Window.h> 21 22 23 class OffscreenClock : public BView { 24 public: 25 OffscreenClock(BRect frame, const char *name); 26 virtual ~OffscreenClock(); 27 28 void DrawClock(); 29 BPoint Position(); 30 31 void SetTo(int32 hour, int32 minute, int32 second); 32 33 private: 34 BBitmap *fBitmap; 35 BBitmap *fCenterBitmap; 36 BBitmap *fCapBitmap; 37 BPoint fCenter; 38 39 BPoint fMinutePoints[60]; 40 BPoint fHourPoints[60]; 41 short fHours; 42 short fMinutes; 43 short fSeconds; 44 }; 45 46 const BRect kClockRect(0, 0, kClockFaceWidth -1, kClockFaceHeight -1); 47 const BRect kCenterRect(0, 0, kCenterWidth -1, kCenterHeight -1); 48 const BRect kCapRect(0, 0, kCapWidth -1, kCapHeight -1); 49 50 /*! 51 Analog Clock face rendering view. 52 */ 53 OffscreenClock::OffscreenClock(BRect frame, const char *name) 54 : BView(frame, name, B_NOT_RESIZABLE, B_WILL_DRAW) 55 { 56 fBitmap = new BBitmap(kClockRect, kClockFaceColorSpace); 57 fBitmap->SetBits(kClockFaceBits, (kClockFaceWidth) *(kClockFaceHeight +3), 0, kClockFaceColorSpace); 58 59 ReplaceTransparentColor(fBitmap, ui_color(B_PANEL_BACKGROUND_COLOR)); 60 61 fCenterBitmap = new BBitmap(kCenterRect, kCenterColorSpace); 62 fCenterBitmap->SetBits(kCenterBits, (kCenterWidth) *(kCenterHeight +1), 0, kCenterColorSpace); 63 64 fCapBitmap = new BBitmap(kCapRect, kCapColorSpace); 65 fCapBitmap->SetBits(kCapBits, (kCapWidth +1) *(kCapHeight +1) +1, 0, kCapColorSpace); 66 67 fCenter = BPoint(42, 42); 68 69 float counter; 70 short index; 71 float x, y, mRadius, hRadius; 72 73 mRadius = fCenter.x - 12; 74 hRadius = mRadius - 10; 75 index = 0; 76 77 // 78 // Generate minutes/hours points array 79 // 80 for (counter = 90; counter >= 0; counter -= 6,index++) { 81 x = mRadius * cos(((360 - counter)/180.0) * 3.1415); 82 x += fCenter.x; 83 y = mRadius * sin(((360 - counter)/180.0) * 3.1415); 84 y += fCenter.x; 85 fMinutePoints[index].Set(x,y); 86 x = hRadius * cos(((360 - counter)/180.0) * 3.1415); 87 x += fCenter.x; 88 y = hRadius * sin(((360 - counter)/180.0) * 3.1415); 89 y += fCenter.x; 90 fHourPoints[index].Set(x,y); 91 } 92 93 for (counter = 354; counter > 90; counter -= 6,index++) { 94 x = mRadius * cos(((360 - counter)/180.0) * 3.1415); 95 x += fCenter.x; 96 y = mRadius * sin(((360 - counter)/180.0) * 3.1415); 97 y += fCenter.x; 98 fMinutePoints[index].Set(x,y); 99 x = hRadius * cos(((360 - counter)/180.0) * 3.1415); 100 x += fCenter.x; 101 y = hRadius * sin(((360 - counter)/180.0) * 3.1415); 102 y += fCenter.x; 103 fHourPoints[index].Set(x,y); 104 } 105 } 106 107 108 OffscreenClock::~OffscreenClock() 109 { 110 delete fBitmap; 111 delete fCenterBitmap; 112 delete fCapBitmap; 113 } 114 115 116 void 117 OffscreenClock::SetTo(int32 hour, int32 minute, int32 second) 118 { 119 if (fSeconds != second || fMinutes != minute || fHours != hour) { 120 fHours = hour; 121 fMinutes = minute; 122 fSeconds = second; 123 } 124 } 125 126 127 void 128 OffscreenClock::DrawClock() 129 { 130 ASSERT(Window()->IsLocked()); 131 132 // draw clockface 133 SetDrawingMode(B_OP_COPY); 134 DrawBitmap(fBitmap, BPoint(0, 0)); 135 136 SetHighColor(0, 0, 0, 255); 137 138 short hours = fHours; 139 if (hours >= 12) 140 hours -= 12; 141 142 hours *= 5; 143 hours += (fMinutes / 12); 144 145 // draw center hub 146 SetDrawingMode(B_OP_OVER); 147 DrawBitmap(fCenterBitmap, fCenter - BPoint(kCenterWidth/2.0, kCenterHeight/2.0)); 148 149 // draw hands 150 StrokeLine(fCenter, fHourPoints[hours]); 151 StrokeLine(fCenter, fMinutePoints[fMinutes]); 152 SetHighColor(tint_color(HighColor(), B_LIGHTEN_1_TINT)); 153 StrokeLine(fCenter, fMinutePoints[fSeconds]); 154 155 // draw center cap 156 DrawBitmap(fCapBitmap, fCenter -BPoint(kCapWidth/2.0, kCapHeight/2.0)); 157 158 Sync(); 159 } 160 161 162 // #pragma mark - 163 164 165 /*! 166 BView to display clock face of current time. 167 */ 168 TAnalogClock::TAnalogClock(BRect frame, const char *name, uint32 resizingmode, uint32 flags) 169 : BView(frame, name, resizingmode, flags | B_DRAW_ON_CHILDREN) 170 { 171 _InitView(frame); 172 } 173 174 175 TAnalogClock::~TAnalogClock() 176 { 177 delete fBitmap; 178 } 179 180 181 void 182 TAnalogClock::_InitView(BRect rect) 183 { 184 fClock = new OffscreenClock(kClockRect, "offscreen"); 185 fBitmap = new BBitmap(kClockRect, B_CMAP8, true); 186 fBitmap->Lock(); 187 fBitmap->AddChild(fClock); 188 fBitmap->Unlock(); 189 } 190 191 192 void 193 TAnalogClock::AttachedToWindow() 194 { 195 SetViewColor(B_TRANSPARENT_COLOR); 196 } 197 198 199 void 200 TAnalogClock::MessageReceived(BMessage *message) 201 { 202 int32 change; 203 switch (message->what) { 204 case B_OBSERVER_NOTICE_CHANGE: 205 message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change); 206 switch (change) { 207 case H_TM_CHANGED: 208 { 209 int32 hour = 0; 210 int32 minute = 0; 211 int32 second = 0; 212 if (message->FindInt32("hour", &hour) == B_OK 213 && message->FindInt32("minute", &minute) == B_OK 214 && message->FindInt32("second", &second) == B_OK) 215 SetTo(hour, minute, second); 216 break; 217 } 218 default: 219 BView::MessageReceived(message); 220 break; 221 } 222 break; 223 default: 224 BView::MessageReceived(message); 225 break; 226 } 227 } 228 229 230 void 231 TAnalogClock::Draw(BRect /*updateRect*/) 232 { 233 SetHighColor(0, 100, 10); 234 235 if (fBitmap->Lock()) { 236 fClock->DrawClock(); 237 DrawBitmap(fBitmap, BPoint(0, 0)); 238 fBitmap->Unlock(); 239 } 240 } 241 242 243 void 244 TAnalogClock::SetTo(int32 hour, int32 minute, int32 second) 245 { 246 fClock->SetTo(hour, minute, second); 247 Invalidate(); 248 } 249