1 /* 2 * Copyright 2001-2005, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Mike Wilber 8 * Stefano Ceccherini (burton666@libero.it) 9 * Ivan Tonizza 10 * Stephan Aßmus, <superstippi@gmx.de> 11 */ 12 13 14 #include <Button.h> 15 16 #include <Font.h> 17 #include <LayoutUtils.h> 18 #include <String.h> 19 #include <Window.h> 20 21 22 BButton::BButton(BRect frame, const char *name, const char *label, BMessage *message, 23 uint32 resizingMode, uint32 flags) 24 : BControl(frame, name, label, message, resizingMode, flags | B_WILL_DRAW), 25 fDrawAsDefault(false) 26 { 27 // Resize to minimum height if needed 28 font_height fh; 29 GetFontHeight(&fh); 30 float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent); 31 if (Bounds().Height() < minHeight) 32 ResizeTo(Bounds().Width(), minHeight); 33 } 34 35 36 BButton::BButton(const char* name, const char* label, BMessage *message, 37 uint32 flags) 38 : BControl(BRect(0, 0, -1, -1), name, label, message, B_FOLLOW_NONE, 39 flags | B_WILL_DRAW | B_SUPPORTS_LAYOUT), 40 fDrawAsDefault(false) 41 { 42 // Resize to minimum height if needed 43 font_height fh; 44 GetFontHeight(&fh); 45 float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent); 46 if (Bounds().Height() < minHeight) 47 ResizeTo(Bounds().Width(), minHeight); 48 } 49 50 51 BButton::BButton(const char* label, BMessage *message) 52 : BControl(BRect(0, 0, -1, -1), NULL, label, message, B_FOLLOW_NONE, 53 B_WILL_DRAW | B_NAVIGABLE | B_SUPPORTS_LAYOUT), 54 fDrawAsDefault(false) 55 { 56 // Resize to minimum height if needed 57 font_height fh; 58 GetFontHeight(&fh); 59 float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent); 60 if (Bounds().Height() < minHeight) 61 ResizeTo(Bounds().Width(), minHeight); 62 } 63 64 65 BButton::~BButton() 66 { 67 } 68 69 70 BButton::BButton(BMessage *archive) 71 : BControl (archive) 72 { 73 if (archive->FindBool("_default", &fDrawAsDefault) != B_OK) 74 fDrawAsDefault = false; 75 } 76 77 78 BArchivable * 79 BButton::Instantiate(BMessage *archive) 80 { 81 if (validate_instantiation(archive, "BButton")) 82 return new BButton(archive); 83 84 return NULL; 85 } 86 87 88 status_t 89 BButton::Archive(BMessage* archive, bool deep) const 90 { 91 status_t err = BControl::Archive(archive, deep); 92 93 if (err != B_OK) 94 return err; 95 96 if (IsDefault()) 97 err = archive->AddBool("_default", true); 98 99 return err; 100 } 101 102 103 void 104 BButton::Draw(BRect updateRect) 105 { 106 font_height fh; 107 GetFontHeight(&fh); 108 109 const BRect bounds = Bounds(); 110 BRect rect = bounds; 111 112 const bool enabled = IsEnabled(); 113 const bool pushed = Value() == B_CONTROL_ON; 114 #if 0 115 // Default indicator 116 if (IsDefault()) 117 rect = DrawDefault(rect, enabled); 118 else 119 rect.InsetBy(1.0f, 1.0f); 120 121 BRect fillArea = rect; 122 fillArea.InsetBy(3.0f, 3.0f); 123 124 BString text = Label(); 125 126 #if 1 127 // Label truncation 128 BFont font; 129 GetFont(&font); 130 font.TruncateString(&text, B_TRUNCATE_END, fillArea.Width()); 131 #endif 132 133 // Label position 134 const float stringWidth = StringWidth(text.String()); 135 const float x = (bounds.right - stringWidth) / 2.0f; 136 const float labelY = bounds.top 137 + ((bounds.Height() - fh.ascent - fh.descent) / 2.0f) 138 + fh.ascent + 1.0f; 139 const float focusLineY = labelY + fh.descent; 140 141 /* speed trick: 142 if the focus changes but the button is not pressed then we can 143 redraw only the focus line, 144 if the focus changes and the button is pressed invert the internal rect 145 this block takes care of all the focus changes 146 */ 147 if (IsFocusChanging()) { 148 if (pushed) { 149 rect.InsetBy(2.0, 2.0); 150 InvertRect(rect); 151 } else 152 DrawFocusLine(x, focusLineY, stringWidth, IsFocus() && Window()->IsActive()); 153 154 return; 155 } 156 157 // Colors 158 const rgb_color panelBgColor = ui_color(B_PANEL_BACKGROUND_COLOR); 159 const rgb_color buttonBgColor=tint_color(panelBgColor, B_LIGHTEN_1_TINT); 160 const rgb_color maxLightColor=tint_color(panelBgColor, B_LIGHTEN_MAX_TINT); 161 const rgb_color maxShadowColor=tint_color(panelBgColor, B_DARKEN_MAX_TINT); 162 const rgb_color darkBorderColor = tint_color(panelBgColor, 163 enabled ? B_DARKEN_4_TINT : B_DARKEN_2_TINT); 164 const rgb_color firstBevelColor = enabled ? tint_color(panelBgColor, B_DARKEN_2_TINT) 165 : panelBgColor; 166 const rgb_color cornerColor = IsDefault() ? firstBevelColor : panelBgColor; 167 168 // Fill the button area 169 SetHighColor(buttonBgColor); 170 FillRect(fillArea); 171 172 // external border 173 SetHighColor(darkBorderColor); 174 StrokeRect(rect); 175 176 BeginLineArray(14); 177 178 // Corners 179 AddLine(rect.LeftTop(), rect.LeftTop(), cornerColor); 180 AddLine(rect.LeftBottom(), rect.LeftBottom(), cornerColor); 181 AddLine(rect.RightTop(), rect.RightTop(), cornerColor); 182 AddLine(rect.RightBottom(), rect.RightBottom(), cornerColor); 183 184 rect.InsetBy(1.0f,1.0f); 185 186 // Shadow 187 AddLine(rect.LeftBottom(), rect.RightBottom(), firstBevelColor); 188 AddLine(rect.RightBottom(), rect.RightTop(), firstBevelColor); 189 // Light 190 AddLine(rect.LeftTop(), rect.LeftBottom(),buttonBgColor); 191 AddLine(rect.LeftTop(), rect.RightTop(), buttonBgColor); 192 193 rect.InsetBy(1.0f, 1.0f); 194 195 // Shadow 196 AddLine(rect.LeftBottom(), rect.RightBottom(), panelBgColor); 197 AddLine(rect.RightBottom(), rect.RightTop(), panelBgColor); 198 // Light 199 AddLine(rect.LeftTop(), rect.LeftBottom(),maxLightColor); 200 AddLine(rect.LeftTop(), rect.RightTop(), maxLightColor); 201 202 rect.InsetBy(1.0f,1.0f); 203 204 // Light 205 AddLine(rect.LeftTop(), rect.LeftBottom(),maxLightColor); 206 AddLine(rect.LeftTop(), rect.RightTop(), maxLightColor); 207 208 EndLineArray(); 209 210 // Invert if clicked 211 if (enabled && pushed) { 212 rect.InsetBy(-2.0f, -2.0f); 213 InvertRect(rect); 214 } 215 216 // Label color 217 if (enabled) { 218 if (pushed) { 219 SetHighColor(maxLightColor); 220 SetLowColor(maxShadowColor); 221 } else { 222 SetHighColor(maxShadowColor); 223 SetLowColor(tint_color(panelBgColor, B_LIGHTEN_2_TINT)); 224 } 225 } else { 226 SetHighColor(tint_color(panelBgColor, B_DISABLED_LABEL_TINT)); 227 SetLowColor(tint_color(panelBgColor, B_LIGHTEN_2_TINT)); 228 } 229 230 // Draw the label 231 DrawString(text.String(), BPoint(x, labelY)); 232 233 // Focus line 234 if (enabled && IsFocus() && Window()->IsActive() && !pushed) 235 DrawFocusLine(x,focusLineY,stringWidth,true); 236 #else 237 // Default indicator 238 if (IsDefault()) 239 rect = DrawDefault(rect, enabled); 240 241 BRect fillArea = rect; 242 fillArea.InsetBy(3.0, 3.0); 243 244 BString text = Label(); 245 246 #if 1 247 // Label truncation 248 BFont font; 249 GetFont(&font); 250 font.TruncateString(&text, B_TRUNCATE_END, fillArea.Width() - 4); 251 #endif 252 253 // Label position 254 const float stringWidth = StringWidth(text.String()); 255 const float x = (rect.right - stringWidth) / 2.0; 256 const float labelY = bounds.top 257 + ((bounds.Height() - fh.ascent - fh.descent) / 2.0) 258 + fh.ascent + 1.0; 259 const float focusLineY = labelY + fh.descent; 260 261 /* speed trick: 262 if the focus changes but the button is not pressed then we can 263 redraw only the focus line, 264 if the focus changes and the button is pressed invert the internal rect 265 this block takes care of all the focus changes 266 */ 267 if (IsFocusChanging()) { 268 if (pushed) { 269 rect.InsetBy(2.0, 2.0); 270 InvertRect(rect); 271 } else 272 DrawFocusLine(x, focusLineY, stringWidth, IsFocus() && Window()->IsActive()); 273 274 return; 275 } 276 277 // colors 278 rgb_color panelBgColor = ui_color(B_PANEL_BACKGROUND_COLOR); 279 rgb_color buttonBgColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT); 280 rgb_color lightColor; 281 rgb_color maxLightColor; 282 rgb_color maxShadowColor = tint_color(panelBgColor, B_DARKEN_MAX_TINT); 283 284 rgb_color dark1BorderColor; 285 rgb_color dark2BorderColor; 286 287 rgb_color bevelColor1; 288 rgb_color bevelColor2; 289 rgb_color bevelColorRBCorner; 290 291 rgb_color borderBevelShadow; 292 rgb_color borderBevelLight; 293 294 if (enabled) { 295 lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT); 296 maxLightColor = tint_color(panelBgColor, B_LIGHTEN_MAX_TINT); 297 298 dark1BorderColor = tint_color(panelBgColor, B_DARKEN_3_TINT); 299 dark2BorderColor = tint_color(panelBgColor, B_DARKEN_4_TINT); 300 301 bevelColor1 = tint_color(panelBgColor, B_DARKEN_2_TINT); 302 bevelColor2 = panelBgColor; 303 304 if (IsDefault()) { 305 borderBevelShadow = tint_color(dark1BorderColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2); 306 borderBevelLight = tint_color(dark1BorderColor, B_LIGHTEN_1_TINT); 307 308 borderBevelLight.red = (borderBevelLight.red + panelBgColor.red) / 2; 309 borderBevelLight.green = (borderBevelLight.green + panelBgColor.green) / 2; 310 borderBevelLight.blue = (borderBevelLight.blue + panelBgColor.blue) / 2; 311 312 dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_3_TINT); 313 dark2BorderColor = tint_color(dark1BorderColor, B_DARKEN_4_TINT); 314 315 bevelColorRBCorner = borderBevelShadow; 316 } else { 317 borderBevelShadow = tint_color(panelBgColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2); 318 borderBevelLight = buttonBgColor; 319 320 bevelColorRBCorner = dark1BorderColor; 321 } 322 } else { 323 lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT); 324 maxLightColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT); 325 326 dark1BorderColor = tint_color(panelBgColor, B_DARKEN_1_TINT); 327 dark2BorderColor = tint_color(panelBgColor, B_DARKEN_2_TINT); 328 329 bevelColor1 = panelBgColor; 330 bevelColor2 = buttonBgColor; 331 332 if (IsDefault()) { 333 borderBevelShadow = dark1BorderColor; 334 borderBevelLight = panelBgColor; 335 dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_1_TINT); 336 dark2BorderColor = tint_color(dark1BorderColor, 1.16); 337 338 } else { 339 borderBevelShadow = panelBgColor; 340 borderBevelLight = panelBgColor; 341 } 342 343 bevelColorRBCorner = tint_color(panelBgColor, 1.08);; 344 } 345 346 // fill the button area 347 SetHighColor(buttonBgColor); 348 FillRect(fillArea); 349 350 BeginLineArray(22); 351 // bevel around external border 352 AddLine(BPoint(rect.left, rect.bottom), 353 BPoint(rect.left, rect.top), borderBevelShadow); 354 AddLine(BPoint(rect.left + 1, rect.top), 355 BPoint(rect.right, rect.top), borderBevelShadow); 356 357 AddLine(BPoint(rect.right, rect.top + 1), 358 BPoint(rect.right, rect.bottom), borderBevelLight); 359 AddLine(BPoint(rect.left + 1, rect.bottom), 360 BPoint(rect.right - 1, rect.bottom), borderBevelLight); 361 362 rect.InsetBy(1.0, 1.0); 363 364 // external border 365 AddLine(BPoint(rect.left, rect.bottom), 366 BPoint(rect.left, rect.top), dark1BorderColor); 367 AddLine(BPoint(rect.left + 1, rect.top), 368 BPoint(rect.right, rect.top), dark1BorderColor); 369 AddLine(BPoint(rect.right, rect.top + 1), 370 BPoint(rect.right, rect.bottom), dark2BorderColor); 371 AddLine(BPoint(rect.right - 1, rect.bottom), 372 BPoint(rect.left + 1, rect.bottom), dark2BorderColor); 373 374 rect.InsetBy(1.0, 1.0); 375 376 // Light 377 AddLine(BPoint(rect.left, rect.top), 378 BPoint(rect.left, rect.top), buttonBgColor); 379 AddLine(BPoint(rect.left, rect.top + 1), 380 BPoint(rect.left, rect.bottom - 1), lightColor); 381 AddLine(BPoint(rect.left, rect.bottom), 382 BPoint(rect.left, rect.bottom), bevelColor2); 383 AddLine(BPoint(rect.left + 1, rect.top), 384 BPoint(rect.right - 1, rect.top), lightColor); 385 AddLine(BPoint(rect.right, rect.top), 386 BPoint(rect.right, rect.top), bevelColor2); 387 // Shadow 388 AddLine(BPoint(rect.left + 1, rect.bottom), 389 BPoint(rect.right - 1, rect.bottom), bevelColor1); 390 AddLine(BPoint(rect.right, rect.bottom), 391 BPoint(rect.right, rect.bottom), bevelColorRBCorner); 392 AddLine(BPoint(rect.right, rect.bottom - 1), 393 BPoint(rect.right, rect.top + 1), bevelColor1); 394 395 rect.InsetBy(1.0, 1.0); 396 397 // Light 398 AddLine(BPoint(rect.left, rect.top), 399 BPoint(rect.left, rect.bottom - 1), maxLightColor); 400 AddLine(BPoint(rect.left, rect.bottom), 401 BPoint(rect.left, rect.bottom), buttonBgColor); 402 AddLine(BPoint(rect.left + 1, rect.top), 403 BPoint(rect.right - 1, rect.top), maxLightColor); 404 AddLine(BPoint(rect.right, rect.top), 405 BPoint(rect.right, rect.top), buttonBgColor); 406 // Shadow 407 AddLine(BPoint(rect.left + 1, rect.bottom), 408 BPoint(rect.right, rect.bottom), bevelColor2); 409 AddLine(BPoint(rect.right, rect.bottom - 1), 410 BPoint(rect.right, rect.top + 1), bevelColor2); 411 412 rect.InsetBy(1.0,1.0); 413 414 EndLineArray(); 415 416 // Invert if clicked 417 if (enabled && pushed) { 418 rect.InsetBy(-2.0, -2.0); 419 InvertRect(rect); 420 } 421 422 // Label color 423 if (enabled) { 424 if (pushed) { 425 SetHighColor(maxLightColor); 426 SetLowColor(255 - buttonBgColor.red, 427 255 - buttonBgColor.green, 428 255 - buttonBgColor.blue); 429 } else { 430 SetHighColor(ui_color(B_CONTROL_TEXT_COLOR)); 431 SetLowColor(buttonBgColor); 432 } 433 } else { 434 SetHighColor(tint_color(panelBgColor, B_DISABLED_LABEL_TINT)); 435 SetLowColor(buttonBgColor); 436 } 437 438 // Draw the label 439 DrawString(text.String(), BPoint(x, labelY)); 440 441 // Focus line 442 if (enabled && IsFocus() && Window()->IsActive() && !pushed) 443 DrawFocusLine(x, focusLineY, stringWidth, true); 444 #endif 445 } 446 447 448 void 449 BButton::MouseDown(BPoint point) 450 { 451 if (!IsEnabled()) 452 return; 453 454 SetValue(B_CONTROL_ON); 455 456 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) { 457 SetTracking(true); 458 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 459 } else { 460 BRect bounds = Bounds(); 461 uint32 buttons; 462 463 do { 464 Window()->UpdateIfNeeded(); 465 snooze(40000); 466 467 GetMouse(&point, &buttons, true); 468 469 bool inside = bounds.Contains(point); 470 471 if ((Value() == B_CONTROL_ON) != inside) 472 SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF); 473 } while (buttons != 0); 474 475 if (Value() == B_CONTROL_ON) 476 Invoke(); 477 } 478 } 479 480 481 void 482 BButton::AttachedToWindow() 483 { 484 BControl::AttachedToWindow(); 485 // low color will now be the parents view color 486 487 if (IsDefault()) 488 Window()->SetDefaultButton(this); 489 490 SetViewColor(B_TRANSPARENT_COLOR); 491 } 492 493 494 void 495 BButton::KeyDown(const char *bytes, int32 numBytes) 496 { 497 if (*bytes == B_ENTER || *bytes == B_SPACE) { 498 if (!IsEnabled()) 499 return; 500 501 SetValue(B_CONTROL_ON); 502 503 // make sure the user saw that 504 Window()->UpdateIfNeeded(); 505 snooze(25000); 506 507 Invoke(); 508 509 } else 510 BControl::KeyDown(bytes, numBytes); 511 } 512 513 514 void 515 BButton::MakeDefault(bool flag) 516 { 517 BButton *oldDefault = NULL; 518 BWindow *window = Window(); 519 520 if (window) 521 oldDefault = window->DefaultButton(); 522 523 if (flag) { 524 if (fDrawAsDefault && oldDefault == this) 525 return; 526 527 if (!fDrawAsDefault) { 528 fDrawAsDefault = true; 529 530 ResizeBy(6.0f, 6.0f); 531 MoveBy(-3.0f, -3.0f); 532 } 533 534 if (window && oldDefault != this) 535 window->SetDefaultButton(this); 536 } else { 537 if (!fDrawAsDefault) 538 return; 539 540 fDrawAsDefault = false; 541 542 ResizeBy(-6.0f, -6.0f); 543 MoveBy(3.0f, 3.0f); 544 545 if (window && oldDefault == this) 546 window->SetDefaultButton(NULL); 547 } 548 } 549 550 551 void 552 BButton::SetLabel(const char *string) 553 { 554 BControl::SetLabel(string); 555 } 556 557 558 bool 559 BButton::IsDefault() const 560 { 561 return fDrawAsDefault; 562 } 563 564 565 void 566 BButton::MessageReceived(BMessage *message) 567 { 568 BControl::MessageReceived(message); 569 } 570 571 572 void 573 BButton::WindowActivated(bool active) 574 { 575 BControl::WindowActivated(active); 576 } 577 578 579 void 580 BButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 581 { 582 if (!IsTracking()) 583 return; 584 585 bool inside = Bounds().Contains(point); 586 587 if ((Value() == B_CONTROL_ON) != inside) 588 SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF); 589 } 590 591 592 void 593 BButton::MouseUp(BPoint point) 594 { 595 if (!IsTracking()) 596 return; 597 598 if (Bounds().Contains(point)) 599 Invoke(); 600 601 SetTracking(false); 602 } 603 604 605 void 606 BButton::DetachedFromWindow() 607 { 608 BControl::DetachedFromWindow(); 609 } 610 611 612 void 613 BButton::SetValue(int32 value) 614 { 615 if (value != Value()) 616 BControl::SetValue(value); 617 } 618 619 620 void 621 BButton::GetPreferredSize(float *_width, float *_height) 622 { 623 if (_height) { 624 font_height fontHeight; 625 GetFontHeight(&fontHeight); 626 627 // *_height = 12.0f + ceilf(fontHeight.ascent + fontHeight.descent) 628 *_height = ceilf((fontHeight.ascent + fontHeight.descent) * 1.8) 629 + (fDrawAsDefault ? 6.0f : 0); 630 } 631 632 if (_width) { 633 float width = 20.0f + (float)ceil(StringWidth(Label())); 634 if (width < 75.0f) 635 width = 75.0f; 636 637 if (fDrawAsDefault) 638 width += 6.0f; 639 640 *_width = width; 641 } 642 } 643 644 645 void 646 BButton::ResizeToPreferred() 647 { 648 BControl::ResizeToPreferred(); 649 } 650 651 652 status_t 653 BButton::Invoke(BMessage *message) 654 { 655 Sync(); 656 snooze(50000); 657 658 status_t err = BControl::Invoke(message); 659 660 SetValue(B_CONTROL_OFF); 661 662 return err; 663 } 664 665 666 void 667 BButton::FrameMoved(BPoint newLocation) 668 { 669 BControl::FrameMoved(newLocation); 670 } 671 672 673 void 674 BButton::FrameResized(float width, float height) 675 { 676 BControl::FrameResized(width, height); 677 } 678 679 680 void 681 BButton::MakeFocus(bool focused) 682 { 683 BControl::MakeFocus(focused); 684 } 685 686 687 void 688 BButton::AllAttached() 689 { 690 BControl::AllAttached(); 691 } 692 693 694 void 695 BButton::AllDetached() 696 { 697 BControl::AllDetached(); 698 } 699 700 701 BHandler * 702 BButton::ResolveSpecifier(BMessage *message, int32 index, 703 BMessage *specifier, int32 what, 704 const char *property) 705 { 706 return BControl::ResolveSpecifier(message, index, specifier, what, property); 707 } 708 709 710 status_t 711 BButton::GetSupportedSuites(BMessage *message) 712 { 713 return BControl::GetSupportedSuites(message); 714 } 715 716 717 status_t 718 BButton::Perform(perform_code d, void *arg) 719 { 720 return BControl::Perform(d, arg); 721 } 722 723 724 BSize 725 BButton::MaxSize() 726 { 727 float width, height; 728 GetPreferredSize(&width, &height); 729 730 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), BSize(width, height)); 731 } 732 733 734 void BButton::_ReservedButton1() {} 735 void BButton::_ReservedButton2() {} 736 void BButton::_ReservedButton3() {} 737 738 739 BButton & 740 BButton::operator=(const BButton &) 741 { 742 return *this; 743 } 744 745 746 BRect 747 BButton::DrawDefault(BRect bounds, bool enabled) 748 { 749 #if 0 750 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR), 751 lighten1 = tint_color(no_tint, B_LIGHTEN_1_TINT), 752 darken1 = tint_color(no_tint, B_DARKEN_1_TINT); 753 754 rgb_color borderColor; 755 if (enabled) 756 borderColor = tint_color(no_tint, B_DARKEN_4_TINT); 757 else 758 borderColor = darken1; 759 760 // Dark border 761 BeginLineArray(4); 762 AddLine(BPoint(bounds.left, bounds.bottom - 1.0f), 763 BPoint(bounds.left, bounds.top + 1.0f), borderColor); 764 AddLine(BPoint(bounds.left + 1.0f, bounds.top), 765 BPoint(bounds.right - 1.0f, bounds.top), borderColor); 766 AddLine(BPoint(bounds.right, bounds.top + 1.0f), 767 BPoint(bounds.right, bounds.bottom - 1.0f), borderColor); 768 AddLine(BPoint(bounds.left + 1.0f, bounds.bottom), 769 BPoint(bounds.right - 1.0f, bounds.bottom), borderColor); 770 EndLineArray(); 771 772 if (enabled) { 773 // Bevel 774 bounds.InsetBy(1.0f, 1.0f); 775 SetHighColor(darken1); 776 StrokeRect(bounds); 777 } 778 779 bounds.InsetBy(1.0f, 1.0f); 780 781 // Filling 782 float inset = enabled? 2.0f : 3.0f; 783 SetHighColor(lighten1); 784 785 FillRect(BRect(bounds.left, bounds.top, 786 bounds.right, bounds.top+inset-1.0f)); 787 FillRect(BRect(bounds.left, bounds.bottom-inset+1.0f, 788 bounds.right, bounds.bottom)); 789 FillRect(BRect(bounds.left, bounds.top+inset-1.0f, 790 bounds.left+inset-1.0f, bounds.bottom-inset+1.0f)); 791 FillRect(BRect(bounds.right-inset+1.0f, bounds.top+inset-1.0f, 792 bounds.right, bounds.bottom-inset+1.0f)); 793 794 bounds.InsetBy(inset,inset); 795 796 return bounds; 797 #else 798 rgb_color low = LowColor(); 799 rgb_color focusColor = tint_color(low, enabled ? (B_DARKEN_1_TINT + B_DARKEN_2_TINT) / 2 800 : (B_NO_TINT + B_DARKEN_1_TINT) / 2); 801 802 SetHighColor(focusColor); 803 804 StrokeRect(bounds, B_SOLID_LOW); 805 bounds.InsetBy(1.0, 1.0); 806 StrokeRect(bounds); 807 bounds.InsetBy(1.0, 1.0); 808 StrokeRect(bounds); 809 bounds.InsetBy(1.0, 1.0); 810 811 return bounds; 812 #endif 813 } 814 815 816 status_t 817 BButton::Execute() 818 { 819 if (!IsEnabled()) 820 return B_ERROR; 821 822 SetValue(B_CONTROL_ON); 823 return Invoke(); 824 } 825 826 827 void 828 BButton::DrawFocusLine(float x, float y, float width, bool visible) 829 { 830 if (visible) 831 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 832 else { 833 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 834 B_LIGHTEN_1_TINT)); 835 } 836 837 // Blue Line 838 StrokeLine(BPoint(x, y), BPoint(x + width, y)); 839 840 if (visible) 841 SetHighColor(255, 255, 255); 842 // White Line 843 StrokeLine(BPoint(x, y + 1.0f), BPoint(x + width, y + 1.0f)); 844 } 845