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