1 /* 2 * Copyright 1999, Be Incorporated. All Rights Reserved. 3 * This file may be used under the terms of the Be Sample Code License. 4 * 5 */ 6 7 #include "clock.h" 8 #include "cl_view.h" 9 10 11 #include <Alert.h> 12 #include <Bitmap.h> 13 #include <Catalog.h> 14 #include <Debug.h> 15 #include <Dragger.h> 16 #include <Entry.h> 17 #include <Resources.h> 18 #include <Roster.h> 19 20 21 #include <time.h> 22 #include <math.h> 23 24 25 #undef B_TRANSLATION_CONTEXT 26 #define B_TRANSLATION_CONTEXT "Clock" 27 28 29 TOffscreenView::TOffscreenView(BRect frame, const char *name, short mRadius, 30 short hRadius, short offset, long face, bool show) 31 : BView(frame, name, B_FOLLOW_NONE, B_WILL_DRAW), 32 fHours(0), 33 fMinutes(0), 34 fSeconds(0), 35 fOffset(offset), 36 fHoursRadius(hRadius), 37 fMinutesRadius(mRadius), 38 fFace(face), 39 fShowSeconds(show), 40 fInner(NULL), 41 fCenter(NULL) 42 { 43 for (short i = 0; i <= 8; i++) 44 fClockFace[i] = NULL; 45 46 status_t error; 47 BResources rsrcs; 48 error = rsrcs.SetToImage(&&dummy_label); 49 dummy_label: 50 if (error == B_OK) { 51 size_t len; 52 void *picH; 53 BRect theRect(0, 0, 82, 82); 54 for (short loop = 0; loop <= 8; loop++) { 55 if ((picH = rsrcs.FindResource('PICT', loop + 4, &len))) { 56 fClockFace[loop] = new BBitmap(theRect, B_CMAP8); 57 fClockFace[loop]->SetBits(picH, len, 0, B_CMAP8); 58 free(picH); 59 } 60 } 61 62 theRect.Set(0,0,15,15); 63 if ((picH = rsrcs.FindResource(B_MINI_ICON_TYPE, "center", &len))) { 64 fCenter = new BBitmap(theRect, B_CMAP8); 65 fCenter->SetBits(picH, len, 0, B_CMAP8); 66 free(picH); 67 } 68 69 theRect.Set(0,0,2,2); 70 if ((picH = rsrcs.FindResource('PICT', 13, &len))) { 71 fInner = new BBitmap(theRect, B_CMAP8); 72 fInner->SetBits(picH, len, 0, B_CMAP8); 73 free(picH); 74 } 75 } 76 77 float x, y; 78 float counter; 79 short index = 0; 80 81 // Generate minutes points array 82 for (counter = 90; counter >= 0; counter -= 6, index++) { 83 x = mRadius * cos(((360 - counter)/180.0) * M_PI); 84 x += 41; 85 y = mRadius * sin(((360 - counter)/180.0) * M_PI); 86 y += 41; 87 fMinutePoints[index].Set(x,y); 88 x = hRadius * cos(((360 - counter)/180.0) * M_PI); 89 x += 41; 90 y = hRadius * sin(((360 - counter)/180.0) * M_PI); 91 y += 41; 92 fHourPoints[index].Set(x,y); 93 } 94 95 for (counter = 354; counter > 90; counter -= 6,index++) { 96 x = mRadius * cos(((360 - counter)/180.0) * M_PI); 97 x += 41; 98 y = mRadius * sin(((360 - counter)/180.0) * M_PI); 99 y += 41; 100 fMinutePoints[index].Set(x,y); 101 x = hRadius * cos(((360 - counter)/180.0) * M_PI); 102 x += 41; 103 y = hRadius * sin(((360 - counter)/180.0) * M_PI); 104 y += 41; 105 fHourPoints[index].Set(x,y); 106 } 107 } 108 109 110 void 111 TOffscreenView::NextFace() 112 { 113 fFace++; 114 if (fFace > 8) 115 fFace = 1; 116 }; 117 118 119 void 120 TOffscreenView::DrawX() 121 { 122 ASSERT(Window()); 123 124 if (Window()->Lock()) { 125 if (fClockFace[fFace] != NULL) 126 DrawBitmap(fClockFace[fFace], BPoint(0, 0)); 127 128 // 129 // Draw hands 130 // 131 SetHighColor(0, 0, 0); 132 int32 hours = fHours; 133 if (hours >= 12) 134 hours -= 12; 135 hours *= 5; 136 hours += (fMinutes / 12); 137 SetDrawingMode(B_OP_OVER); 138 StrokeLine(BPoint(fOffset, fOffset), fHourPoints[hours]); 139 140 if (fCenter != NULL) 141 DrawBitmap(fCenter, BPoint(fOffset - 3, fOffset - 3)); 142 StrokeLine(BPoint(fOffset, fOffset), fMinutePoints[fMinutes]); 143 SetHighColor(180, 180, 180); 144 if (fShowSeconds) 145 StrokeLine(BPoint(fOffset, fOffset), fMinutePoints[fSeconds]); 146 SetDrawingMode(B_OP_COPY); 147 if (fInner != NULL) 148 DrawBitmap(fInner, BPoint(fOffset - 1, fOffset - 1)); 149 Sync(); 150 Window()->Unlock(); 151 } 152 } 153 154 155 TOffscreenView::~TOffscreenView() 156 { 157 for (int32 counter = 0; counter <= 8; counter++) 158 delete fClockFace[counter]; 159 }; 160 161 162 // #pragma mark - 163 164 165 TOnscreenView::TOnscreenView(BRect rect, const char *title, short mRadius, 166 short hRadius, short offset) 167 : BView(rect, title, B_FOLLOW_NONE, 168 B_WILL_DRAW | B_PULSE_NEEDED | B_DRAW_ON_CHILDREN), 169 fOffscreen(NULL), 170 fOffscreenView(NULL) 171 { 172 InitObject(rect, mRadius, hRadius, offset, 1, TRUE); 173 174 rect.OffsetTo(B_ORIGIN); 175 rect.top = rect.bottom - 7; 176 rect.left = rect.right - 7; 177 BDragger *dw = new BDragger(rect, this); 178 AddChild(dw); 179 } 180 181 182 void 183 TOnscreenView::InitObject(BRect rect, short mRadius, short hRadius, 184 short offset, long face, bool show) 185 { 186 fOffscreenView = new TOffscreenView(rect, "freqd", mRadius, hRadius, offset, face, show); 187 fOffscreen = new BBitmap(rect, B_CMAP8, true); 188 if (fOffscreen != NULL && fOffscreen->Lock()) { 189 fOffscreen->AddChild(fOffscreenView); 190 fOffscreen->Unlock(); 191 } 192 193 Pulse(); 194 } 195 196 197 TOnscreenView::~TOnscreenView() 198 { 199 delete fOffscreen; 200 } 201 202 203 TOnscreenView::TOnscreenView(BMessage *data) 204 : BView(data), 205 fOffscreen(NULL), 206 fOffscreenView(NULL) 207 { 208 InitObject(data->FindRect("bounds"), data->FindInt32("mRadius"), 209 data->FindInt32("hRadius"), data->FindInt32("offset"), 210 data->FindInt32("face"), data->FindBool("seconds")); 211 } 212 213 214 status_t 215 TOnscreenView::Archive(BMessage *data, bool deep) const 216 { 217 status_t status = BView::Archive(data, deep); 218 if (status == B_OK) 219 status = data->AddString("add_on", kAppSignature); 220 221 if (status == B_OK) 222 status = data->AddRect("bounds", Bounds()); 223 224 if (status == B_OK) 225 status = data->AddInt32("mRadius", fOffscreenView->fMinutesRadius); 226 227 if (status == B_OK) 228 status = data->AddInt32("hRadius", fOffscreenView->fHoursRadius); 229 230 if (status == B_OK) 231 status = data->AddInt32("offset", fOffscreenView->fOffset); 232 233 if (status == B_OK) 234 status = data->AddBool("seconds", fOffscreenView->fShowSeconds); 235 236 if (status == B_OK) 237 status = data->AddInt32("face", fOffscreenView->fFace); 238 239 return status; 240 } 241 242 243 BArchivable * 244 TOnscreenView::Instantiate(BMessage *data) 245 { 246 if (!validate_instantiation(data, "TOnscreenView")) 247 return NULL; 248 return new TOnscreenView(data); 249 } 250 251 252 void 253 TOnscreenView::Pulse() 254 { 255 ASSERT(fOffscreen); 256 ASSERT(fOffscreenView); 257 258 time_t current = time(0); 259 struct tm *loctime = localtime(¤t); 260 261 short hours = loctime->tm_hour; 262 short minutes = loctime->tm_min; 263 short seconds = loctime->tm_sec; 264 265 if ((fOffscreenView->fShowSeconds && (seconds != fOffscreenView->fSeconds)) 266 || (minutes != fOffscreenView->fMinutes)) { 267 fOffscreenView->fHours = hours; 268 fOffscreenView->fMinutes = minutes; 269 fOffscreenView->fSeconds = seconds; 270 BRect b = Bounds(); 271 b.InsetBy(12,12); 272 Draw(b); 273 } 274 } 275 276 277 void 278 TOnscreenView::UseFace(short face) 279 { 280 fOffscreenView->fFace = face; 281 BRect b = Bounds(); 282 b.InsetBy(12,12); 283 Draw(b); 284 } 285 286 287 void 288 TOnscreenView::ShowSecs(bool secs) 289 { 290 fOffscreenView->fShowSeconds = secs; 291 BRect b = Bounds(); 292 b.InsetBy(12,12); 293 Invalidate(b); 294 } 295 296 297 short 298 TOnscreenView::ReturnFace() 299 { 300 return fOffscreenView->fFace; 301 } 302 303 304 short 305 TOnscreenView::ReturnSeconds() 306 { 307 return fOffscreenView->fShowSeconds; 308 } 309 310 311 void 312 TOnscreenView::Draw(BRect rect) 313 { 314 ASSERT(fOffscreen); 315 ASSERT(fOffscreenView); 316 317 if (fOffscreen->Lock()) { 318 // Composite the clock offscreen... 319 fOffscreenView->DrawX(); 320 DrawBitmap(fOffscreen, rect, rect); 321 fOffscreen->Unlock(); 322 } 323 }; 324 325 326 void 327 TOnscreenView::MouseDown( BPoint point ) 328 { 329 BPoint cursor; 330 uint32 buttons; 331 BRect bounds = Bounds(); 332 333 GetMouse(&cursor,&buttons); 334 if (buttons & B_SECONDARY_MOUSE_BUTTON) { 335 fOffscreenView->fShowSeconds = !fOffscreenView->fShowSeconds; 336 bounds.InsetBy(12,12); 337 Invalidate(bounds); 338 } else { 339 fOffscreenView->NextFace(); 340 Invalidate(bounds); 341 BView *child = ChildAt(0); 342 if (child) 343 child->Invalidate(); 344 } 345 }; 346 347 348 void 349 TOnscreenView::MessageReceived(BMessage *msg) 350 { 351 switch(msg->what) { 352 case B_ABOUT_REQUESTED: 353 { 354 BAlert *alert = new BAlert(B_TRANSLATE("About Clock"), B_TRANSLATE( 355 "Clock (The Replicant version)\n\nCopyright 2002-2020 " 356 "Haiku, Inc.\n\nOriginally coded by the folks " 357 "at Be.\n Copyright 1991-1998, Be Inc."), B_TRANSLATE("OK")); 358 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 359 alert->Go(); 360 } break; 361 362 default: 363 BView::MessageReceived(msg); 364 } 365 } 366 367