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