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