1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 */ 8 9 /*! BStatusBar displays a "percentage-of-completion" gauge. */ 10 11 #include <Debug.h> 12 #include <Message.h> 13 #include <StatusBar.h> 14 15 #include <stdlib.h> 16 #include <string.h> 17 18 19 BStatusBar::BStatusBar(BRect frame, const char *name, const char *label, 20 const char *trailingLabel) 21 : BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW), 22 fLabel(NULL), 23 fTrailingLabel(NULL), 24 fText(NULL), 25 fTrailingText(NULL), 26 fMax(100.0f), 27 fCurrent(0.0f), 28 fBarHeight(-1.0f), 29 fTrailingWidth(-1.0f), 30 fEraseText(-1.0f), 31 fEraseTrailingText(-1.0f), 32 fCustomBarHeight(false) 33 34 { 35 // TODO: Move initializer list and other stuff to InitObject 36 InitObject(label, trailingLabel); 37 38 fBarColor.set_to(50, 150, 255, 255); 39 } 40 41 42 BStatusBar::BStatusBar(BMessage *archive) 43 : BView(archive), 44 fLabel(NULL), 45 fTrailingLabel(NULL), 46 fText(NULL), 47 fTrailingText(NULL), 48 fMax(100.0f), 49 fCurrent(0.0f), 50 fBarHeight(-1.0f), 51 fTrailingWidth(-1.0f), 52 fEraseText(-1.0f), 53 fEraseTrailingText(-1.0f), 54 fCustomBarHeight(false) 55 { 56 const char *label = NULL; 57 const char *trailingLabel = NULL; 58 archive->FindString("_label", &label); 59 archive->FindString("_tlabel", &trailingLabel); 60 61 InitObject(label, trailingLabel); 62 63 if (archive->FindFloat("_high", &fBarHeight) != B_OK) 64 fBarHeight = -1.0f; 65 66 if (archive->FindInt32("_bcolor", (int32 *)&fBarColor) < B_OK) 67 fBarColor.set_to(50, 150, 255, 255); 68 69 if (archive->FindFloat("_val", &fCurrent) < B_OK) 70 fCurrent = 0.0f; 71 72 if (archive->FindFloat("_max", &fMax) < B_OK) 73 fMax = 100.0f; 74 75 const char *string; 76 77 if (archive->FindString("_text", &string) < B_OK) 78 fText = NULL; 79 else 80 fText = strdup(string); 81 82 if (archive->FindString("_ttext", &string) < B_OK) 83 fTrailingText = NULL; 84 else 85 fTrailingText = strdup(string); 86 87 } 88 89 90 BStatusBar::~BStatusBar() 91 { 92 free(fLabel); 93 free(fTrailingLabel); 94 free(fText); 95 free(fTrailingText); 96 } 97 98 99 BArchivable * 100 BStatusBar::Instantiate(BMessage *archive) 101 { 102 if (validate_instantiation(archive, "BStatusBar")) 103 return new BStatusBar(archive); 104 105 return NULL; 106 } 107 108 109 status_t 110 BStatusBar::Archive(BMessage *archive, bool deep) const 111 { 112 status_t err = BView::Archive(archive, deep); 113 114 if (err < B_OK) 115 return err; 116 117 if (fBarHeight != 16.0f) 118 err = archive->AddFloat("_high", fBarHeight); 119 120 if (err < B_OK) 121 return err; 122 123 // DW: I'm pretty sure we don't need to compare the color with (50, 150, 255) ? 124 err = archive->AddInt32("_bcolor", (const uint32 &)fBarColor); 125 126 if (err < B_OK) 127 return err; 128 129 if (fCurrent != 0.0f) 130 err = archive->AddFloat("_val", fCurrent); 131 132 if (err < B_OK) 133 return err; 134 135 if (fMax != 100.0f ) 136 err = archive->AddFloat("_max", fMax); 137 138 if (err < B_OK) 139 return err; 140 141 if (fText ) 142 err = archive->AddString("_text", fText); 143 144 if (err < B_OK) 145 return err; 146 147 if (fTrailingText) 148 err = archive->AddString("_ttext", fTrailingText); 149 150 if (err < B_OK) 151 return err; 152 153 if (fLabel) 154 err = archive->AddString("_label", fLabel); 155 156 if (err < B_OK) 157 return err; 158 159 if (fTrailingLabel) 160 err = archive->AddString ("_tlabel", fTrailingLabel); 161 162 return err; 163 } 164 165 166 void 167 BStatusBar::AttachedToWindow() 168 { 169 float width, height; 170 GetPreferredSize(&width, &height); 171 ResizeTo(Frame().Width(), height); 172 173 if (Parent()) { 174 SetViewColor(Parent()->ViewColor()); 175 SetLowColor(Parent()->ViewColor()); 176 } 177 } 178 179 180 void 181 BStatusBar::MessageReceived(BMessage *message) 182 { 183 switch(message->what) { 184 case B_UPDATE_STATUS_BAR: 185 { 186 float delta; 187 const char *text = NULL, *trailing_text = NULL; 188 189 message->FindFloat("delta", &delta); 190 message->FindString("text", &text); 191 message->FindString("trailing_text", &trailing_text); 192 193 Update(delta, text, trailing_text); 194 195 break; 196 } 197 198 case B_RESET_STATUS_BAR: 199 { 200 const char *label = NULL, *trailing_label = NULL; 201 202 message->FindString("label", &label); 203 message->FindString("trailing_label", &trailing_label); 204 205 Reset(label, trailing_label); 206 207 break; 208 } 209 210 default: 211 BView::MessageReceived(message); 212 break; 213 } 214 } 215 216 217 void 218 BStatusBar::Draw(BRect updateRect) 219 { 220 float width = Frame().Width(); 221 font_height fh; 222 GetFontHeight(&fh); 223 224 SetHighColor(0, 0, 0); 225 MovePenTo(2.0f, (float)ceil(fh.ascent) + 1.0f); 226 227 if (fLabel) 228 DrawString(fLabel); 229 if (fText) 230 DrawString(fText); 231 232 if (fTrailingText) { 233 if (fTrailingLabel) { 234 MovePenTo(width - StringWidth(fTrailingText) - 235 StringWidth(fTrailingLabel) - 2.0f, 236 (float)ceil(fh.ascent) + 1.0f); 237 DrawString(fTrailingText); 238 DrawString(fTrailingLabel); 239 } else { 240 MovePenTo(width - StringWidth(fTrailingText) - 2.0f, 241 (float)ceil(fh.ascent) + 1.0f); 242 DrawString(fTrailingText); 243 } 244 245 } else if (fTrailingLabel) { 246 MovePenTo(width - StringWidth(fTrailingLabel) - 2.0f, 247 (float)ceil(fh.ascent) + 1.0f); 248 DrawString(fTrailingLabel); 249 } 250 251 BRect rect(0.0f, (float)ceil(fh.ascent) + 4.0f, width, 252 (float)ceil(fh.ascent) + 4.0f + fBarHeight); 253 254 // First bevel 255 SetHighColor(tint_color(ui_color ( B_PANEL_BACKGROUND_COLOR ), B_DARKEN_1_TINT)); 256 StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top)); 257 StrokeLine(BPoint(rect.right, rect.top)); 258 259 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT)); 260 StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), BPoint(rect.right, rect.bottom)); 261 StrokeLine(BPoint(rect.right, rect.top + 1.0f)); 262 263 rect.InsetBy(1.0f, 1.0f); 264 265 // Second bevel 266 SetHighColor(tint_color(ui_color ( B_PANEL_BACKGROUND_COLOR ), B_DARKEN_4_TINT)); 267 StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top)); 268 StrokeLine(BPoint(rect.right, rect.top)); 269 270 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 271 StrokeLine(BPoint(rect.left + 1.0f, rect.bottom), BPoint(rect.right, rect.bottom)); 272 StrokeLine(BPoint(rect.right, rect.top + 1.0f)); 273 274 rect.InsetBy(1.0f, 1.0f); 275 276 // Filling 277 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_MAX_TINT)); 278 FillRect(rect); 279 280 if (fCurrent != 0.0f) { 281 rect.right = rect.left + (float)ceil(fCurrent * (width - 4) / fMax), 282 283 // Bevel 284 SetHighColor(tint_color(fBarColor, B_LIGHTEN_2_TINT)); 285 StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.left, rect.top)); 286 StrokeLine(BPoint(rect.right, rect.top)); 287 288 SetHighColor(tint_color(fBarColor, B_DARKEN_2_TINT)); 289 StrokeLine(BPoint(rect.left, rect.bottom), BPoint(rect.right, rect.bottom)); 290 StrokeLine(BPoint(rect.right, rect.top)); 291 292 rect.InsetBy(1.0f, 1.0f); 293 294 // Filling 295 SetHighColor(fBarColor); 296 FillRect(rect); 297 } 298 } 299 300 301 void 302 BStatusBar::SetBarColor(rgb_color color) 303 { 304 fBarColor = color; 305 306 Invalidate(); 307 } 308 309 310 void 311 BStatusBar::SetBarHeight(float height) 312 { 313 BRect frame = Frame(); 314 315 fBarHeight = height; 316 fCustomBarHeight = true; 317 ResizeTo(frame.Width(), fBarHeight + 16); 318 } 319 320 321 void 322 BStatusBar::SetText(const char *string) 323 { 324 SetTextData(&fText, string); 325 326 Invalidate(); 327 } 328 329 330 void 331 BStatusBar::SetTrailingText(const char *string) 332 { 333 SetTextData(&fTrailingText, string); 334 335 Invalidate(); 336 } 337 338 339 void 340 BStatusBar::SetMaxValue(float max) 341 { 342 fMax = max; 343 344 Invalidate(); 345 } 346 347 348 void 349 BStatusBar::Update(float delta, const char *text, const char *trailingText) 350 { 351 fCurrent += delta; 352 353 if (fCurrent > fMax) 354 fCurrent = fMax; 355 356 // Passing NULL for the text or trailingText argument retains the previous 357 // text or trailing text string. 358 if (text) 359 SetTextData(&fText, text); 360 361 if (trailingText) 362 SetTextData(&fTrailingText, trailingText); 363 364 Invalidate(); 365 } 366 367 368 void 369 BStatusBar::Reset(const char *label, const char *trailingLabel) 370 { 371 // Reset replaces the label and trailing label with copies of the 372 // strings passed as arguments. If either argument is NULL, the 373 // label or trailing label will be deleted and erased. 374 SetTextData(&fLabel, label); 375 SetTextData(&fTrailingLabel, trailingLabel); 376 377 // Reset deletes and erases any text or trailing text 378 SetTextData(&fText, NULL); 379 SetTextData(&fTrailingText, NULL); 380 381 fCurrent = 0.0f; 382 fMax = 100.0f; 383 384 Invalidate(); 385 } 386 387 388 float 389 BStatusBar::CurrentValue() const 390 { 391 return fCurrent; 392 } 393 394 395 float 396 BStatusBar::MaxValue() const 397 { 398 return fMax; 399 } 400 401 402 rgb_color 403 BStatusBar::BarColor() const 404 { 405 return fBarColor; 406 } 407 408 409 float 410 BStatusBar::BarHeight() const 411 { 412 if (!fCustomBarHeight && fBarHeight == -1.0f) { 413 font_height fh; 414 GetFontHeight(&fh); 415 const_cast<BStatusBar *>(this)->fBarHeight = fh.ascent + fh.descent + 6.0f; 416 } 417 418 return fBarHeight; 419 } 420 421 422 const char * 423 BStatusBar::Text() const 424 { 425 return fText; 426 } 427 428 429 const char * 430 BStatusBar::TrailingText() const 431 { 432 return fTrailingText; 433 } 434 435 436 const char * 437 BStatusBar::Label() const 438 { 439 return fLabel; 440 } 441 442 443 const char * 444 BStatusBar::TrailingLabel() const 445 { 446 return fTrailingLabel; 447 } 448 449 450 void 451 BStatusBar::MouseDown(BPoint point) 452 { 453 BView::MouseDown(point); 454 } 455 456 457 void 458 BStatusBar::MouseUp(BPoint point) 459 { 460 BView::MouseUp(point); 461 } 462 463 464 void 465 BStatusBar::WindowActivated(bool state) 466 { 467 BView::WindowActivated(state); 468 } 469 470 471 void 472 BStatusBar::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 473 { 474 BView::MouseMoved(point, transit, message); 475 } 476 477 478 void 479 BStatusBar::DetachedFromWindow() 480 { 481 BView::DetachedFromWindow(); 482 } 483 484 485 void 486 BStatusBar::FrameMoved(BPoint newPosition) 487 { 488 BView::FrameMoved(newPosition); 489 } 490 491 492 void 493 BStatusBar::FrameResized(float newWidth, float newHeight) 494 { 495 BView::FrameResized(newWidth, newHeight); 496 } 497 498 499 BHandler * 500 BStatusBar::ResolveSpecifier(BMessage *message, int32 index, 501 BMessage *specifier, 502 int32 what, const char *property) 503 { 504 return BView::ResolveSpecifier(message, index, specifier, what, property); 505 } 506 507 508 void 509 BStatusBar::ResizeToPreferred() 510 { 511 BView::ResizeToPreferred(); 512 } 513 514 515 void 516 BStatusBar::GetPreferredSize(float* _width, float* _height) 517 { 518 if (_width) { 519 *_width = (fLabel ? (float)ceil(StringWidth(fLabel)) : 0.0f) 520 + (fTrailingLabel ? (float)ceil(StringWidth(fTrailingLabel)) : 0.0f) 521 + 7.0f; 522 } 523 524 if (_height) { 525 font_height fontHeight; 526 GetFontHeight(&fontHeight); 527 528 *_height = ceil(fontHeight.ascent + fontHeight.descent) + 5.0f + BarHeight(); 529 } 530 } 531 532 533 void 534 BStatusBar::MakeFocus(bool state) 535 { 536 BView::MakeFocus(state); 537 } 538 539 540 void 541 BStatusBar::AllAttached() 542 { 543 BView::AllAttached(); 544 } 545 546 547 void 548 BStatusBar::AllDetached() 549 { 550 BView::AllDetached(); 551 } 552 553 554 status_t 555 BStatusBar::GetSupportedSuites(BMessage *data) 556 { 557 return BView::GetSupportedSuites(data); 558 } 559 560 561 status_t 562 BStatusBar::Perform(perform_code d, void *arg) 563 { 564 return BView::Perform(d, arg); 565 } 566 567 568 void BStatusBar::_ReservedStatusBar1() {} 569 void BStatusBar::_ReservedStatusBar2() {} 570 void BStatusBar::_ReservedStatusBar3() {} 571 void BStatusBar::_ReservedStatusBar4() {} 572 573 574 BStatusBar & 575 BStatusBar::operator=(const BStatusBar &) 576 { 577 return *this; 578 } 579 580 581 void 582 BStatusBar::InitObject(const char *label, const char *trailingLabel) 583 { 584 SetTextData(&fLabel, label); 585 SetTextData(&fTrailingLabel, trailingLabel); 586 } 587 588 589 void 590 BStatusBar::SetTextData(char **dest, const char *source) 591 { 592 ASSERT(dest != NULL); 593 594 if (*dest != NULL) { 595 free(*dest); 596 *dest = NULL; 597 } 598 599 if (source != NULL && source[0] != '\0') 600 *dest = strdup(source); 601 } 602 603 604 void 605 BStatusBar::FillBar(BRect rect) 606 { 607 // TODO: 608 } 609 610 611 void 612 BStatusBar::Resize() 613 { 614 // TODO: 615 } 616 617 618 void 619 BStatusBar::_Draw(BRect updateRect, bool barOnly) 620 { 621 // TODO: 622 } 623