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