1 /* 2 * Copyright 2009, Stephan Aßmus <superstippi@gmx.de> 3 * Copyright 2012-2015 Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Stephan Aßmus, superstippi@gmx.de 8 * John Scipione, jscipione@gmail.com 9 */ 10 11 12 #include <ControlLook.h> 13 14 #include <algorithm> 15 16 #include <Control.h> 17 #include <GradientLinear.h> 18 #include <LayoutUtils.h> 19 #include <Region.h> 20 #include <Shape.h> 21 #include <String.h> 22 #include <View.h> 23 #include <Window.h> 24 25 #include "ContainerWindow.h" 26 27 28 namespace BPrivate { 29 30 31 static const float kEdgeBevelLightTint = 0.59; 32 static const float kEdgeBevelShadowTint = 1.0735; 33 static const float kHoverTintFactor = 0.85; 34 35 static const float kButtonPopUpIndicatorWidth = 11; 36 37 38 BControlLook::BControlLook(): 39 fCachedOutline(false), 40 fCachedWorkspace(-1) 41 { 42 } 43 44 45 BControlLook::~BControlLook() 46 { 47 } 48 49 50 BAlignment 51 BControlLook::DefaultLabelAlignment() const 52 { 53 return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER); 54 } 55 56 57 float 58 BControlLook::DefaultLabelSpacing() const 59 { 60 return ceilf(be_plain_font->Size() / 2.0); 61 } 62 63 64 float 65 BControlLook::DefaultItemSpacing() const 66 { 67 return ceilf(be_plain_font->Size() * 0.85); 68 } 69 70 71 float 72 BControlLook::ComposeSpacing(float spacing) 73 { 74 switch ((int)spacing) { 75 case B_USE_DEFAULT_SPACING: 76 case B_USE_ITEM_SPACING: 77 return be_control_look->DefaultItemSpacing(); 78 case B_USE_HALF_ITEM_SPACING: 79 return ceilf(be_control_look->DefaultItemSpacing() * 0.5f); 80 case B_USE_WINDOW_SPACING: 81 return be_control_look->DefaultItemSpacing(); 82 case B_USE_SMALL_SPACING: 83 return ceilf(be_control_look->DefaultItemSpacing() * 0.7f); 84 case B_USE_BIG_SPACING: 85 return ceilf(be_control_look->DefaultItemSpacing() * 1.3f); 86 } 87 88 return spacing; 89 } 90 91 92 uint32 93 BControlLook::Flags(BControl* control) const 94 { 95 uint32 flags = B_IS_CONTROL; 96 97 if (!control->IsEnabled()) 98 flags |= B_DISABLED; 99 100 if (control->IsFocus() && control->Window() != NULL 101 && control->Window()->IsActive()) { 102 flags |= B_FOCUSED; 103 } 104 105 switch (control->Value()) { 106 case B_CONTROL_ON: 107 flags |= B_ACTIVATED; 108 break; 109 case B_CONTROL_PARTIALLY_ON: 110 flags |= B_PARTIALLY_ACTIVATED; 111 break; 112 } 113 114 if (control->Parent() != NULL 115 && (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) { 116 // In this constellation, assume we want to render the control 117 // against the already existing view contents of the parent view. 118 flags |= B_BLEND_FRAME; 119 } 120 121 return flags; 122 } 123 124 125 // #pragma mark - 126 127 128 void 129 BControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, 130 const rgb_color& base, const rgb_color& background, uint32 flags, 131 uint32 borders) 132 { 133 _DrawButtonFrame(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, base, 134 background, 1.0, 1.0, flags, borders); 135 } 136 137 138 void 139 BControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, 140 float radius, const rgb_color& base, const rgb_color& background, uint32 flags, 141 uint32 borders) 142 { 143 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius, 144 base, background, 1.0, 1.0, flags, borders); 145 } 146 147 148 void 149 BControlLook::DrawButtonFrame(BView* view, BRect& rect, 150 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 151 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 152 const rgb_color& background, uint32 flags, 153 uint32 borders) 154 { 155 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius, 156 leftBottomRadius, rightBottomRadius, base, background, 157 1.0, 1.0, flags, borders); 158 } 159 160 161 void 162 BControlLook::DrawButtonBackground(BView* view, BRect& rect, 163 const BRect& updateRect, const rgb_color& base, uint32 flags, 164 uint32 borders, orientation orientation) 165 { 166 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, 167 base, false, flags, borders, orientation); 168 } 169 170 171 void 172 BControlLook::DrawButtonBackground(BView* view, BRect& rect, 173 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 174 uint32 borders, orientation orientation) 175 { 176 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius, 177 radius, base, false, flags, borders, orientation); 178 } 179 180 181 void 182 BControlLook::DrawButtonBackground(BView* view, BRect& rect, 183 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 184 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 185 uint32 flags, uint32 borders, orientation orientation) 186 { 187 _DrawButtonBackground(view, rect, updateRect, leftTopRadius, 188 rightTopRadius, leftBottomRadius, rightBottomRadius, base, false, flags, 189 borders, orientation); 190 } 191 192 193 void 194 BControlLook::DrawMenuBarBackground(BView* view, BRect& rect, 195 const BRect& updateRect, const rgb_color& base, uint32 flags, 196 uint32 borders) 197 { 198 if (!rect.IsValid() || !rect.Intersects(updateRect)) 199 return; 200 201 // the surface edges 202 203 // colors 204 float topTint; 205 float bottomTint; 206 207 if ((flags & B_ACTIVATED) != 0) { 208 rgb_color bevelColor1 = tint_color(base, 1.40); 209 rgb_color bevelColor2 = tint_color(base, 1.25); 210 211 topTint = 1.25; 212 bottomTint = 1.20; 213 214 _DrawFrame(view, rect, 215 bevelColor1, bevelColor1, 216 bevelColor2, bevelColor2, 217 borders & B_TOP_BORDER); 218 } else { 219 rgb_color cornerColor = tint_color(base, 0.9); 220 rgb_color bevelColorTop = tint_color(base, 0.5); 221 rgb_color bevelColorLeft = tint_color(base, 0.7); 222 rgb_color bevelColorRightBottom = tint_color(base, 1.08); 223 224 topTint = 0.69; 225 bottomTint = 1.03; 226 227 _DrawFrame(view, rect, 228 bevelColorLeft, bevelColorTop, 229 bevelColorRightBottom, bevelColorRightBottom, 230 cornerColor, cornerColor, 231 borders); 232 } 233 234 // draw surface top 235 _FillGradient(view, rect, base, topTint, bottomTint); 236 } 237 238 239 void 240 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 241 const BRect& updateRect, const rgb_color& base, 242 const rgb_color& background, uint32 flags, uint32 borders) 243 { 244 _DrawButtonFrame(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, base, 245 background, 0.6, 1.0, flags, borders); 246 } 247 248 249 void 250 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 251 const BRect& updateRect, float radius, const rgb_color& base, 252 const rgb_color& background, uint32 flags, uint32 borders) 253 { 254 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius, 255 base, background, 0.6, 1.0, flags, borders); 256 } 257 258 259 void 260 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 261 const BRect& updateRect, float leftTopRadius, 262 float rightTopRadius, float leftBottomRadius, 263 float rightBottomRadius, const rgb_color& base, 264 const rgb_color& background, uint32 flags, uint32 borders) 265 { 266 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius, 267 leftBottomRadius, rightBottomRadius, base, background, 0.6, 1.0, 268 flags, borders); 269 } 270 271 272 void 273 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 274 const BRect& updateRect, const rgb_color& base, bool popupIndicator, 275 uint32 flags) 276 { 277 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, 278 0.0f, 0.0f, 0.0f, 0.0f, base, popupIndicator, flags); 279 } 280 281 282 void 283 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 284 const BRect& updateRect, const rgb_color& base, uint32 flags, 285 uint32 borders) 286 { 287 _DrawMenuFieldBackgroundInside(view, rect, updateRect, 288 0.0f, 0.0f, 0.0f, 0.0f, base, flags, borders); 289 } 290 291 292 void 293 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 294 const BRect& updateRect, float radius, const rgb_color& base, 295 bool popupIndicator, uint32 flags) 296 { 297 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius, 298 radius, radius, base, popupIndicator, flags); 299 } 300 301 302 void 303 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 304 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 305 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 306 bool popupIndicator, uint32 flags) 307 { 308 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius, 309 rightTopRadius, leftBottomRadius, rightBottomRadius, base, 310 popupIndicator, flags); 311 } 312 313 314 void 315 BControlLook::DrawMenuBackground(BView* view, BRect& rect, 316 const BRect& updateRect, const rgb_color& base, uint32 flags, 317 uint32 borders) 318 { 319 if (!rect.IsValid() || !rect.Intersects(updateRect)) 320 return; 321 322 // surface top color 323 rgb_color background = tint_color(base, 0.75); 324 325 // inner bevel colors 326 rgb_color bevelLightColor; 327 rgb_color bevelShadowColor; 328 329 if ((flags & B_DISABLED) != 0) { 330 bevelLightColor = tint_color(background, 0.80); 331 bevelShadowColor = tint_color(background, 1.07); 332 } else { 333 bevelLightColor = tint_color(background, 0.6); 334 bevelShadowColor = tint_color(background, 1.12); 335 } 336 337 // draw inner bevel 338 _DrawFrame(view, rect, 339 bevelLightColor, bevelLightColor, 340 bevelShadowColor, bevelShadowColor, 341 borders); 342 343 // draw surface top 344 view->SetHighColor(background); 345 view->FillRect(rect); 346 } 347 348 349 void 350 BControlLook::DrawMenuItemBackground(BView* view, BRect& rect, 351 const BRect& updateRect, const rgb_color& base, uint32 flags, 352 uint32 borders) 353 { 354 if (!rect.IsValid() || !rect.Intersects(updateRect)) 355 return; 356 357 // surface edges 358 float topTint; 359 float bottomTint; 360 rgb_color selectedColor = base; 361 362 if ((flags & B_ACTIVATED) != 0) { 363 topTint = 0.9; 364 bottomTint = 1.05; 365 } else if ((flags & B_DISABLED) != 0) { 366 topTint = 0.80; 367 bottomTint = 1.07; 368 } else { 369 topTint = 0.6; 370 bottomTint = 1.12; 371 } 372 373 rgb_color bevelLightColor = tint_color(selectedColor, topTint); 374 rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint); 375 376 // draw surface edges 377 _DrawFrame(view, rect, 378 bevelLightColor, bevelLightColor, 379 bevelShadowColor, bevelShadowColor, 380 borders); 381 382 // draw surface top 383 view->SetLowColor(selectedColor); 384 // _FillGradient(view, rect, selectedColor, topTint, bottomTint); 385 _FillGradient(view, rect, selectedColor, bottomTint, topTint); 386 } 387 388 389 void 390 BControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect, 391 const rgb_color& base, const rgb_color& barColor, float progressPosition) 392 { 393 if (!rect.Intersects(updateRect)) 394 return; 395 396 _DrawOuterResessedFrame(view, rect, base, 0.6); 397 398 // colors 399 rgb_color dark1BorderColor = tint_color(base, 1.3); 400 rgb_color dark2BorderColor = tint_color(base, 1.2); 401 rgb_color dark1FilledBorderColor = tint_color(barColor, 1.20); 402 rgb_color dark2FilledBorderColor = tint_color(barColor, 1.45); 403 404 BRect filledRect(rect); 405 filledRect.right = progressPosition - 1; 406 407 BRect nonfilledRect(rect); 408 nonfilledRect.left = progressPosition; 409 410 bool filledSurface = filledRect.Width() > 0; 411 bool nonfilledSurface = nonfilledRect.Width() > 0; 412 413 if (filledSurface) { 414 _DrawFrame(view, filledRect, 415 dark1FilledBorderColor, dark1FilledBorderColor, 416 dark2FilledBorderColor, dark2FilledBorderColor); 417 418 _FillGlossyGradient(view, filledRect, barColor, 0.55, 0.68, 0.76, 0.90); 419 } 420 421 if (nonfilledSurface) { 422 _DrawFrame(view, nonfilledRect, dark1BorderColor, dark1BorderColor, 423 dark2BorderColor, dark2BorderColor, 424 B_TOP_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER); 425 426 if (nonfilledRect.left < nonfilledRect.right) { 427 // shadow from fill bar, or left border 428 rgb_color leftBorder = dark1BorderColor; 429 if (filledSurface) 430 leftBorder = tint_color(base, 0.50); 431 view->SetHighColor(leftBorder); 432 view->StrokeLine(nonfilledRect.LeftTop(), 433 nonfilledRect.LeftBottom()); 434 nonfilledRect.left++; 435 } 436 437 _FillGradient(view, nonfilledRect, base, 0.25, 0.06); 438 } 439 } 440 441 442 void 443 BControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect, 444 const rgb_color& base, uint32 flags) 445 { 446 if (!rect.Intersects(updateRect)) 447 return; 448 449 rgb_color dark1BorderColor; 450 rgb_color dark2BorderColor; 451 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 452 453 if ((flags & B_DISABLED) != 0) { 454 _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags); 455 456 dark1BorderColor = tint_color(base, 1.15); 457 dark2BorderColor = tint_color(base, 1.15); 458 } else if ((flags & B_CLICKED) != 0) { 459 dark1BorderColor = tint_color(base, 1.50); 460 dark2BorderColor = tint_color(base, 1.48); 461 462 _DrawFrame(view, rect, 463 dark1BorderColor, dark1BorderColor, 464 dark2BorderColor, dark2BorderColor); 465 466 dark2BorderColor = dark1BorderColor; 467 } else { 468 _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags); 469 470 dark1BorderColor = tint_color(base, 1.40); 471 dark2BorderColor = tint_color(base, 1.38); 472 } 473 474 if ((flags & B_FOCUSED) != 0) { 475 dark1BorderColor = navigationColor; 476 dark2BorderColor = navigationColor; 477 } 478 479 _DrawFrame(view, rect, 480 dark1BorderColor, dark1BorderColor, 481 dark2BorderColor, dark2BorderColor); 482 483 if ((flags & B_DISABLED) != 0) 484 _FillGradient(view, rect, base, 0.4, 0.2); 485 else 486 _FillGradient(view, rect, base, 0.15, 0.0); 487 488 rgb_color markColor; 489 if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) { 490 view->SetHighColor(markColor); 491 492 BFont font; 493 view->GetFont(&font); 494 float inset = std::max(2.0f, roundf(font.Size() / 6)); 495 rect.InsetBy(inset, inset); 496 497 float penSize = std::max(1.0f, ceilf(rect.Width() / 3.5f)); 498 if (penSize > 1.0f && fmodf(penSize, 2.0f) == 0.0f) { 499 // Tweak ends to "include" the pixel at the index, 500 // we need to do this in order to produce results like R5, 501 // where coordinates were inclusive 502 rect.right++; 503 rect.bottom++; 504 } 505 506 view->SetPenSize(penSize); 507 view->SetDrawingMode(B_OP_OVER); 508 view->StrokeLine(rect.LeftTop(), rect.RightBottom()); 509 view->StrokeLine(rect.LeftBottom(), rect.RightTop()); 510 } 511 } 512 513 514 void 515 BControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateRect, 516 const rgb_color& base, uint32 flags) 517 { 518 if (!rect.Intersects(updateRect)) 519 return; 520 521 rgb_color borderColor; 522 rgb_color bevelLight; 523 rgb_color bevelShadow; 524 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 525 526 if ((flags & B_DISABLED) != 0) { 527 borderColor = tint_color(base, 1.15); 528 bevelLight = base; 529 bevelShadow = base; 530 } else if ((flags & B_CLICKED) != 0) { 531 borderColor = tint_color(base, 1.50); 532 bevelLight = borderColor; 533 bevelShadow = borderColor; 534 } else { 535 borderColor = tint_color(base, 1.45); 536 bevelLight = tint_color(base, 0.55); 537 bevelShadow = tint_color(base, 1.11); 538 } 539 540 if ((flags & B_FOCUSED) != 0) { 541 borderColor = navigationColor; 542 } 543 544 BGradientLinear bevelGradient; 545 bevelGradient.AddColor(bevelShadow, 0); 546 bevelGradient.AddColor(bevelLight, 255); 547 bevelGradient.SetStart(rect.LeftTop()); 548 bevelGradient.SetEnd(rect.RightBottom()); 549 550 view->FillEllipse(rect, bevelGradient); 551 rect.InsetBy(1, 1); 552 553 bevelGradient.MakeEmpty(); 554 bevelGradient.AddColor(borderColor, 0); 555 bevelGradient.AddColor(tint_color(borderColor, 0.8), 255); 556 view->FillEllipse(rect, bevelGradient); 557 rect.InsetBy(1, 1); 558 559 float topTint; 560 float bottomTint; 561 if ((flags & B_DISABLED) != 0) { 562 topTint = 0.4; 563 bottomTint = 0.2; 564 } else { 565 topTint = 0.15; 566 bottomTint = 0.0; 567 } 568 569 BGradientLinear gradient; 570 _MakeGradient(gradient, rect, base, topTint, bottomTint); 571 view->FillEllipse(rect, gradient); 572 573 rgb_color markColor; 574 if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) { 575 view->SetHighColor(markColor); 576 BFont font; 577 view->GetFont(&font); 578 float inset = roundf(font.Size() / 4); 579 rect.InsetBy(inset, inset); 580 view->FillEllipse(rect); 581 } 582 } 583 584 585 void 586 BControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2, 587 const BRect& updateRect, const rgb_color& base, uint32 flags, 588 orientation orientation) 589 { 590 DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); 591 DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); 592 } 593 594 595 void 596 BControlLook::DrawScrollBarBackground(BView* view, BRect& rect, 597 const BRect& updateRect, const rgb_color& base, uint32 flags, 598 orientation orientation) 599 { 600 if (!rect.IsValid() || !rect.Intersects(updateRect)) 601 return; 602 603 float gradient1Tint; 604 float gradient2Tint; 605 float darkEdge1Tint; 606 float darkEdge2Tint; 607 float shadowTint; 608 609 if ((flags & B_DISABLED) != 0) { 610 gradient1Tint = 0.9; 611 gradient2Tint = 0.8; 612 darkEdge1Tint = B_DARKEN_2_TINT; 613 darkEdge2Tint = B_DARKEN_2_TINT; 614 shadowTint = gradient1Tint; 615 } else { 616 gradient1Tint = 1.10; 617 gradient2Tint = 1.05; 618 darkEdge1Tint = B_DARKEN_3_TINT; 619 darkEdge2Tint = B_DARKEN_2_TINT; 620 shadowTint = gradient1Tint; 621 } 622 623 rgb_color darkEdge1 = tint_color(base, darkEdge1Tint); 624 rgb_color darkEdge2 = tint_color(base, darkEdge2Tint); 625 rgb_color shadow = tint_color(base, shadowTint); 626 627 if (orientation == B_HORIZONTAL) { 628 // dark vertical line on left edge 629 if (rect.Width() > 0) { 630 view->SetHighColor(darkEdge1); 631 view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); 632 rect.left++; 633 } 634 // dark vertical line on right edge 635 if (rect.Width() >= 0) { 636 view->SetHighColor(darkEdge2); 637 view->StrokeLine(rect.RightTop(), rect.RightBottom()); 638 rect.right--; 639 } 640 // vertical shadow line after left edge 641 if (rect.Width() >= 0) { 642 view->SetHighColor(shadow); 643 view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); 644 rect.left++; 645 } 646 // fill 647 if (rect.Width() >= 0) { 648 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, 649 orientation); 650 } 651 } else { 652 // dark vertical line on top edge 653 if (rect.Height() > 0) { 654 view->SetHighColor(darkEdge1); 655 view->StrokeLine(rect.LeftTop(), rect.RightTop()); 656 rect.top++; 657 } 658 // dark vertical line on bottom edge 659 if (rect.Height() >= 0) { 660 view->SetHighColor(darkEdge2); 661 view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); 662 rect.bottom--; 663 } 664 // horizontal shadow line after top edge 665 if (rect.Height() >= 0) { 666 view->SetHighColor(shadow); 667 view->StrokeLine(rect.LeftTop(), rect.RightTop()); 668 rect.top++; 669 } 670 // fill 671 if (rect.Height() >= 0) { 672 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, 673 orientation); 674 } 675 } 676 } 677 678 679 void 680 BControlLook::DrawScrollViewFrame(BView* view, BRect& rect, 681 const BRect& updateRect, BRect verticalScrollBarFrame, 682 BRect horizontalScrollBarFrame, const rgb_color& base, 683 border_style border, uint32 flags, uint32 _borders) 684 { 685 // calculate scroll corner rect before messing with the "rect" 686 BRect scrollCornerFillRect(rect.right, rect.bottom, 687 rect.right, rect.bottom); 688 689 if (horizontalScrollBarFrame.IsValid()) 690 scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1; 691 692 if (verticalScrollBarFrame.IsValid()) 693 scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1; 694 695 if (border == B_NO_BORDER) { 696 if (scrollCornerFillRect.IsValid()) { 697 view->SetHighColor(base); 698 view->FillRect(scrollCornerFillRect); 699 } 700 return; 701 } 702 703 bool excludeScrollCorner = border == B_FANCY_BORDER 704 && horizontalScrollBarFrame.IsValid() 705 && verticalScrollBarFrame.IsValid(); 706 707 uint32 borders = _borders; 708 if (excludeScrollCorner) { 709 rect.bottom = horizontalScrollBarFrame.top; 710 rect.right = verticalScrollBarFrame.left; 711 borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER); 712 } 713 714 rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT); 715 716 if (border == B_FANCY_BORDER) 717 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); 718 719 if ((flags & B_FOCUSED) != 0) { 720 rgb_color focusColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 721 _DrawFrame(view, rect, focusColor, focusColor, focusColor, focusColor, 722 borders); 723 } else { 724 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 725 scrollbarFrameColor, scrollbarFrameColor, borders); 726 } 727 728 if (excludeScrollCorner) { 729 horizontalScrollBarFrame.InsetBy(-1, -1); 730 // do not overdraw the top edge 731 horizontalScrollBarFrame.top += 2; 732 borders = _borders; 733 borders &= ~B_TOP_BORDER; 734 _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base, 735 1.0, 1.0, flags, borders); 736 _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor, 737 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, 738 borders); 739 740 verticalScrollBarFrame.InsetBy(-1, -1); 741 // do not overdraw the left edge 742 verticalScrollBarFrame.left += 2; 743 borders = _borders; 744 borders &= ~B_LEFT_BORDER; 745 _DrawOuterResessedFrame(view, verticalScrollBarFrame, base, 746 1.0, 1.0, flags, borders); 747 _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor, 748 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, 749 borders); 750 751 // exclude recessed frame 752 scrollCornerFillRect.top++; 753 scrollCornerFillRect.left++; 754 } 755 756 if (scrollCornerFillRect.IsValid()) { 757 view->SetHighColor(base); 758 view->FillRect(scrollCornerFillRect); 759 } 760 } 761 762 763 void 764 BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, 765 const rgb_color& base, uint32 direction, uint32 flags, float tint) 766 { 767 BPoint tri1, tri2, tri3; 768 float hInset = rect.Width() / 3; 769 float vInset = rect.Height() / 3; 770 rect.InsetBy(hInset, vInset); 771 772 switch (direction) { 773 case B_LEFT_ARROW: 774 tri1.Set(rect.right, rect.top); 775 tri2.Set(rect.right - rect.Width() / 1.33, 776 (rect.top + rect.bottom + 1) / 2); 777 tri3.Set(rect.right, rect.bottom + 1); 778 break; 779 case B_RIGHT_ARROW: 780 tri1.Set(rect.left + 1, rect.bottom + 1); 781 tri2.Set(rect.left + 1 + rect.Width() / 1.33, 782 (rect.top + rect.bottom + 1) / 2); 783 tri3.Set(rect.left + 1, rect.top); 784 break; 785 case B_UP_ARROW: 786 tri1.Set(rect.left, rect.bottom); 787 tri2.Set((rect.left + rect.right + 1) / 2, 788 rect.bottom - rect.Height() / 1.33); 789 tri3.Set(rect.right + 1, rect.bottom); 790 break; 791 case B_DOWN_ARROW: 792 default: 793 tri1.Set(rect.left, rect.top + 1); 794 tri2.Set((rect.left + rect.right + 1) / 2, 795 rect.top + 1 + rect.Height() / 1.33); 796 tri3.Set(rect.right + 1, rect.top + 1); 797 break; 798 case B_LEFT_UP_ARROW: 799 tri1.Set(rect.left, rect.bottom); 800 tri2.Set(rect.left, rect.top); 801 tri3.Set(rect.right - 1, rect.top); 802 break; 803 case B_RIGHT_UP_ARROW: 804 tri1.Set(rect.left + 1, rect.top); 805 tri2.Set(rect.right, rect.top); 806 tri3.Set(rect.right, rect.bottom); 807 break; 808 case B_RIGHT_DOWN_ARROW: 809 tri1.Set(rect.right, rect.top); 810 tri2.Set(rect.right, rect.bottom); 811 tri3.Set(rect.left + 1, rect.bottom); 812 break; 813 case B_LEFT_DOWN_ARROW: 814 tri1.Set(rect.right - 1, rect.bottom); 815 tri2.Set(rect.left, rect.bottom); 816 tri3.Set(rect.left, rect.top); 817 break; 818 } 819 820 BShape arrowShape; 821 arrowShape.MoveTo(tri1); 822 arrowShape.LineTo(tri2); 823 arrowShape.LineTo(tri3); 824 825 if ((flags & B_DISABLED) != 0) 826 tint = (tint + B_NO_TINT + B_NO_TINT) / 3; 827 828 view->SetHighColor(tint_color(base, tint)); 829 830 float penSize = view->PenSize(); 831 drawing_mode mode = view->DrawingMode(); 832 833 view->MovePenTo(BPoint(0, 0)); 834 835 view->SetPenSize(ceilf(hInset / 2.0)); 836 view->SetDrawingMode(B_OP_OVER); 837 view->StrokeShape(&arrowShape); 838 839 view->SetPenSize(penSize); 840 view->SetDrawingMode(mode); 841 } 842 843 844 rgb_color 845 BControlLook::SliderBarColor(const rgb_color& base) 846 { 847 return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT); 848 } 849 850 851 void 852 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 853 const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor, 854 float sliderScale, uint32 flags, orientation orientation) 855 { 856 if (!rect.IsValid() || !rect.Intersects(updateRect)) 857 return; 858 859 // save the clipping constraints of the view 860 view->PushState(); 861 862 // separate the bar in two sides 863 float sliderPosition; 864 BRect leftBarSide = rect; 865 BRect rightBarSide = rect; 866 867 if (orientation == B_HORIZONTAL) { 868 sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2) 869 * sliderScale); 870 leftBarSide.right = sliderPosition - 1; 871 rightBarSide.left = sliderPosition; 872 } else { 873 // NOTE: position is reverse of coords 874 sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2) 875 * (1.0 - sliderScale)); 876 leftBarSide.top = sliderPosition; 877 rightBarSide.bottom = sliderPosition - 1; 878 } 879 880 // fill the background for the corners, exclude the middle bar for now 881 BRegion region(rect); 882 region.Exclude(rightBarSide); 883 view->ConstrainClippingRegion(®ion); 884 885 view->PushState(); 886 887 DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags, 888 orientation); 889 890 view->PopState(); 891 892 region.Set(rect); 893 region.Exclude(leftBarSide); 894 view->ConstrainClippingRegion(®ion); 895 896 view->PushState(); 897 898 DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags, 899 orientation); 900 901 view->PopState(); 902 903 // restore the clipping constraints of the view 904 view->PopState(); 905 } 906 907 908 void 909 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 910 const rgb_color& base, rgb_color fillColor, uint32 flags, 911 orientation orientation) 912 { 913 if (!rect.IsValid() || !rect.Intersects(updateRect)) 914 return; 915 916 // separate the rect into corners 917 BRect leftCorner(rect); 918 BRect rightCorner(rect); 919 BRect barRect(rect); 920 921 if (orientation == B_HORIZONTAL) { 922 leftCorner.right = leftCorner.left + leftCorner.Height(); 923 rightCorner.left = rightCorner.right - rightCorner.Height(); 924 barRect.left += ceilf(barRect.Height() / 2); 925 barRect.right -= ceilf(barRect.Height() / 2); 926 } else { 927 leftCorner.bottom = leftCorner.top + leftCorner.Width(); 928 rightCorner.top = rightCorner.bottom - rightCorner.Width(); 929 barRect.top += ceilf(barRect.Width() / 2); 930 barRect.bottom -= ceilf(barRect.Width() / 2); 931 } 932 933 // fill the background for the corners, exclude the middle bar for now 934 BRegion region(rect); 935 region.Exclude(barRect); 936 view->ConstrainClippingRegion(®ion); 937 938 if ((flags & B_BLEND_FRAME) == 0) { 939 view->SetHighColor(base); 940 view->FillRect(rect); 941 } 942 943 // figure out the tints to be used 944 float edgeLightTint; 945 float edgeShadowTint; 946 float frameLightTint; 947 float frameShadowTint; 948 float fillLightTint; 949 float fillShadowTint; 950 uint8 edgeLightAlpha; 951 uint8 edgeShadowAlpha; 952 uint8 frameLightAlpha; 953 uint8 frameShadowAlpha; 954 955 if ((flags & B_DISABLED) != 0) { 956 edgeLightTint = 1.0; 957 edgeShadowTint = 1.0; 958 frameLightTint = 1.20; 959 frameShadowTint = 1.25; 960 fillLightTint = 0.9; 961 fillShadowTint = 1.05; 962 edgeLightAlpha = 12; 963 edgeShadowAlpha = 12; 964 frameLightAlpha = 40; 965 frameShadowAlpha = 45; 966 967 fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6); 968 fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6); 969 fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6); 970 } else { 971 edgeLightTint = 0.65; 972 edgeShadowTint = 1.07; 973 frameLightTint = 1.40; 974 frameShadowTint = 1.50; 975 fillLightTint = 0.8; 976 fillShadowTint = 1.1; 977 edgeLightAlpha = 15; 978 edgeShadowAlpha = 15; 979 frameLightAlpha = 92; 980 frameShadowAlpha = 107; 981 } 982 983 rgb_color edgeLightColor; 984 rgb_color edgeShadowColor; 985 rgb_color frameLightColor; 986 rgb_color frameShadowColor; 987 rgb_color fillLightColor = tint_color(fillColor, fillLightTint); 988 rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint); 989 990 drawing_mode oldMode = view->DrawingMode(); 991 992 if ((flags & B_BLEND_FRAME) != 0) { 993 edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha }; 994 edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha }; 995 frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha }; 996 frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha }; 997 998 view->SetDrawingMode(B_OP_ALPHA); 999 } else { 1000 edgeLightColor = tint_color(base, edgeLightTint); 1001 edgeShadowColor = tint_color(base, edgeShadowTint); 1002 frameLightColor = tint_color(fillColor, frameLightTint); 1003 frameShadowColor = tint_color(fillColor, frameShadowTint); 1004 } 1005 1006 if (orientation == B_HORIZONTAL) { 1007 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, 1008 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 1009 fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation); 1010 1011 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, 1012 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 1013 fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation); 1014 } else { 1015 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, 1016 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 1017 fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation); 1018 1019 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, 1020 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 1021 fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation); 1022 } 1023 1024 view->ConstrainClippingRegion(NULL); 1025 1026 view->BeginLineArray(4); 1027 if (orientation == B_HORIZONTAL) { 1028 view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor); 1029 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), 1030 edgeLightColor); 1031 barRect.InsetBy(0, 1); 1032 view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor); 1033 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), 1034 frameLightColor); 1035 barRect.InsetBy(0, 1); 1036 } else { 1037 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor); 1038 view->AddLine(barRect.RightTop(), barRect.RightBottom(), 1039 edgeLightColor); 1040 barRect.InsetBy(1, 0); 1041 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor); 1042 view->AddLine(barRect.RightTop(), barRect.RightBottom(), 1043 frameLightColor); 1044 barRect.InsetBy(1, 0); 1045 } 1046 view->EndLineArray(); 1047 1048 view->SetDrawingMode(oldMode); 1049 1050 _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint, 1051 orientation); 1052 } 1053 1054 1055 void 1056 BControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect, 1057 const rgb_color& base, uint32 flags, orientation orientation) 1058 { 1059 if (!rect.IsValid() || !rect.Intersects(updateRect)) 1060 return; 1061 1062 // figure out frame color 1063 rgb_color frameLightColor; 1064 rgb_color frameShadowColor; 1065 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 }; 1066 1067 if ((flags & B_FOCUSED) != 0) { 1068 // focused 1069 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 1070 frameShadowColor = frameLightColor; 1071 } else { 1072 // figure out the tints to be used 1073 float frameLightTint; 1074 float frameShadowTint; 1075 1076 if ((flags & B_DISABLED) != 0) { 1077 frameLightTint = 1.30; 1078 frameShadowTint = 1.35; 1079 shadowColor.alpha = 30; 1080 } else { 1081 frameLightTint = 1.6; 1082 frameShadowTint = 1.65; 1083 } 1084 1085 frameLightColor = tint_color(base, frameLightTint); 1086 frameShadowColor = tint_color(base, frameShadowTint); 1087 } 1088 1089 BRect originalRect(rect); 1090 rect.right--; 1091 rect.bottom--; 1092 1093 _DrawFrame(view, rect, frameLightColor, frameLightColor, 1094 frameShadowColor, frameShadowColor); 1095 1096 flags &= ~B_ACTIVATED; 1097 DrawButtonBackground(view, rect, updateRect, base, flags); 1098 1099 // thumb shadow 1100 view->SetDrawingMode(B_OP_ALPHA); 1101 view->SetHighColor(shadowColor); 1102 originalRect.left++; 1103 originalRect.top++; 1104 view->StrokeLine(originalRect.LeftBottom(), originalRect.RightBottom()); 1105 originalRect.bottom--; 1106 view->StrokeLine(originalRect.RightTop(), originalRect.RightBottom()); 1107 1108 // thumb edge 1109 if (orientation == B_HORIZONTAL) { 1110 rect.InsetBy(0, floorf(rect.Height() / 4)); 1111 rect.left = floorf((rect.left + rect.right) / 2); 1112 rect.right = rect.left + 1; 1113 shadowColor = tint_color(base, B_DARKEN_2_TINT); 1114 shadowColor.alpha = 128; 1115 view->SetHighColor(shadowColor); 1116 view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); 1117 rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT); 1118 lightColor.alpha = 128; 1119 view->SetHighColor(lightColor); 1120 view->StrokeLine(rect.RightTop(), rect.RightBottom()); 1121 } else { 1122 rect.InsetBy(floorf(rect.Width() / 4), 0); 1123 rect.top = floorf((rect.top + rect.bottom) / 2); 1124 rect.bottom = rect.top + 1; 1125 shadowColor = tint_color(base, B_DARKEN_2_TINT); 1126 shadowColor.alpha = 128; 1127 view->SetHighColor(shadowColor); 1128 view->StrokeLine(rect.LeftTop(), rect.RightTop()); 1129 rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT); 1130 lightColor.alpha = 128; 1131 view->SetHighColor(lightColor); 1132 view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); 1133 } 1134 1135 view->SetDrawingMode(B_OP_COPY); 1136 } 1137 1138 1139 void 1140 BControlLook::DrawSliderTriangle(BView* view, BRect& rect, 1141 const BRect& updateRect, const rgb_color& base, uint32 flags, 1142 orientation orientation) 1143 { 1144 DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation); 1145 } 1146 1147 1148 void 1149 BControlLook::DrawSliderTriangle(BView* view, BRect& rect, 1150 const BRect& updateRect, const rgb_color& base, const rgb_color& fill, 1151 uint32 flags, orientation orientation) 1152 { 1153 if (!rect.IsValid() || !rect.Intersects(updateRect)) 1154 return; 1155 1156 // figure out frame color 1157 rgb_color frameLightColor; 1158 rgb_color frameShadowColor; 1159 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 }; 1160 1161 float topTint = 0.49; 1162 float middleTint1 = 0.62; 1163 float middleTint2 = 0.76; 1164 float bottomTint = 0.90; 1165 1166 if ((flags & B_DISABLED) != 0) { 1167 topTint = (topTint + B_NO_TINT) / 2; 1168 middleTint1 = (middleTint1 + B_NO_TINT) / 2; 1169 middleTint2 = (middleTint2 + B_NO_TINT) / 2; 1170 bottomTint = (bottomTint + B_NO_TINT) / 2; 1171 } else if ((flags & B_HOVER) != 0) { 1172 topTint *= kHoverTintFactor; 1173 middleTint1 *= kHoverTintFactor; 1174 middleTint2 *= kHoverTintFactor; 1175 bottomTint *= kHoverTintFactor; 1176 } 1177 1178 if ((flags & B_FOCUSED) != 0) { 1179 // focused 1180 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 1181 frameShadowColor = frameLightColor; 1182 } else { 1183 // figure out the tints to be used 1184 float frameLightTint; 1185 float frameShadowTint; 1186 1187 if ((flags & B_DISABLED) != 0) { 1188 frameLightTint = 1.30; 1189 frameShadowTint = 1.35; 1190 shadowColor.alpha = 30; 1191 } else { 1192 frameLightTint = 1.6; 1193 frameShadowTint = 1.65; 1194 } 1195 1196 frameLightColor = tint_color(base, frameLightTint); 1197 frameShadowColor = tint_color(base, frameShadowTint); 1198 } 1199 1200 // make room for the shadow 1201 rect.right--; 1202 rect.bottom--; 1203 1204 uint32 viewFlags = view->Flags(); 1205 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); 1206 view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN); 1207 1208 float centerh = (rect.left + rect.right) / 2; 1209 float centerv = (rect.top + rect.bottom) / 2; 1210 1211 BShape shape; 1212 if (orientation == B_HORIZONTAL) { 1213 shape.MoveTo(BPoint(rect.left + 0.5, rect.bottom + 0.5)); 1214 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5)); 1215 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom - 1 + 0.5)); 1216 shape.LineTo(BPoint(centerh + 0.5, rect.top + 0.5)); 1217 shape.LineTo(BPoint(rect.left + 0.5, rect.bottom - 1 + 0.5)); 1218 } else { 1219 shape.MoveTo(BPoint(rect.right + 0.5, rect.top + 0.5)); 1220 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5)); 1221 shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.bottom + 0.5)); 1222 shape.LineTo(BPoint(rect.left + 0.5, centerv + 0.5)); 1223 shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.top + 0.5)); 1224 } 1225 shape.Close(); 1226 1227 view->MovePenTo(BPoint(1, 1)); 1228 1229 view->SetDrawingMode(B_OP_ALPHA); 1230 view->SetHighColor(shadowColor); 1231 view->StrokeShape(&shape); 1232 1233 view->MovePenTo(B_ORIGIN); 1234 1235 view->SetDrawingMode(B_OP_COPY); 1236 view->SetHighColor(frameLightColor); 1237 view->StrokeShape(&shape); 1238 1239 rect.InsetBy(1, 1); 1240 shape.Clear(); 1241 if (orientation == B_HORIZONTAL) { 1242 shape.MoveTo(BPoint(rect.left, rect.bottom + 1)); 1243 shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1)); 1244 shape.LineTo(BPoint(centerh + 0.5, rect.top)); 1245 } else { 1246 shape.MoveTo(BPoint(rect.right + 1, rect.top)); 1247 shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1)); 1248 shape.LineTo(BPoint(rect.left, centerv + 0.5)); 1249 } 1250 shape.Close(); 1251 1252 BGradientLinear gradient; 1253 if ((flags & B_DISABLED) != 0) { 1254 _MakeGradient(gradient, rect, fill, topTint, bottomTint); 1255 } else { 1256 _MakeGlossyGradient(gradient, rect, fill, topTint, middleTint1, 1257 middleTint2, bottomTint); 1258 } 1259 1260 view->FillShape(&shape, gradient); 1261 1262 view->SetFlags(viewFlags); 1263 } 1264 1265 1266 void 1267 BControlLook::DrawSliderHashMarks(BView* view, BRect& rect, 1268 const BRect& updateRect, const rgb_color& base, int32 count, 1269 hash_mark_location location, uint32 flags, orientation orientation) 1270 { 1271 if (!rect.IsValid() || !rect.Intersects(updateRect)) 1272 return; 1273 1274 rgb_color lightColor; 1275 rgb_color darkColor; 1276 1277 if ((flags & B_DISABLED) != 0) { 1278 lightColor = tint_color(base, 0.9); 1279 darkColor = tint_color(base, 1.07); 1280 } else { 1281 lightColor = tint_color(base, 0.8); 1282 darkColor = tint_color(base, 1.14); 1283 } 1284 1285 int32 hashMarkCount = std::max(count, (int32)2); 1286 // draw at least two hashmarks at min/max if 1287 // fHashMarks != B_HASH_MARKS_NONE 1288 float factor; 1289 float startPos; 1290 if (orientation == B_HORIZONTAL) { 1291 factor = (rect.Width() - 2) / (hashMarkCount - 1); 1292 startPos = rect.left + 1; 1293 } else { 1294 factor = (rect.Height() - 2) / (hashMarkCount - 1); 1295 startPos = rect.top + 1; 1296 } 1297 1298 if (location & B_HASH_MARKS_TOP) { 1299 view->BeginLineArray(hashMarkCount * 2); 1300 1301 if (orientation == B_HORIZONTAL) { 1302 float pos = startPos; 1303 for (int32 i = 0; i < hashMarkCount; i++) { 1304 view->AddLine(BPoint(pos, rect.top), 1305 BPoint(pos, rect.top + 4), darkColor); 1306 view->AddLine(BPoint(pos + 1, rect.top), 1307 BPoint(pos + 1, rect.top + 4), lightColor); 1308 1309 pos += factor; 1310 } 1311 } else { 1312 float pos = startPos; 1313 for (int32 i = 0; i < hashMarkCount; i++) { 1314 view->AddLine(BPoint(rect.left, pos), 1315 BPoint(rect.left + 4, pos), darkColor); 1316 view->AddLine(BPoint(rect.left, pos + 1), 1317 BPoint(rect.left + 4, pos + 1), lightColor); 1318 1319 pos += factor; 1320 } 1321 } 1322 1323 view->EndLineArray(); 1324 } 1325 1326 if ((location & B_HASH_MARKS_BOTTOM) != 0) { 1327 view->BeginLineArray(hashMarkCount * 2); 1328 1329 if (orientation == B_HORIZONTAL) { 1330 float pos = startPos; 1331 for (int32 i = 0; i < hashMarkCount; i++) { 1332 view->AddLine(BPoint(pos, rect.bottom - 4), 1333 BPoint(pos, rect.bottom), darkColor); 1334 view->AddLine(BPoint(pos + 1, rect.bottom - 4), 1335 BPoint(pos + 1, rect.bottom), lightColor); 1336 1337 pos += factor; 1338 } 1339 } else { 1340 float pos = startPos; 1341 for (int32 i = 0; i < hashMarkCount; i++) { 1342 view->AddLine(BPoint(rect.right - 4, pos), 1343 BPoint(rect.right, pos), darkColor); 1344 view->AddLine(BPoint(rect.right - 4, pos + 1), 1345 BPoint(rect.right, pos + 1), lightColor); 1346 1347 pos += factor; 1348 } 1349 } 1350 1351 view->EndLineArray(); 1352 } 1353 } 1354 1355 1356 void 1357 BControlLook::DrawActiveTab(BView* view, BRect& rect, const BRect& updateRect, 1358 const rgb_color& base, uint32 flags, uint32 borders) 1359 { 1360 if (!rect.IsValid() || !rect.Intersects(updateRect)) 1361 return; 1362 1363 // Snap the rectangle to pixels to avoid rounding errors. 1364 rect.left = floorf(rect.left); 1365 rect.right = floorf(rect.right); 1366 rect.top = floorf(rect.top); 1367 rect.bottom = floorf(rect.bottom); 1368 1369 // save the clipping constraints of the view 1370 view->PushState(); 1371 1372 // set clipping constraints to updateRect 1373 BRegion clipping(updateRect); 1374 view->ConstrainClippingRegion(&clipping); 1375 1376 rgb_color edgeShadowColor; 1377 rgb_color edgeLightColor; 1378 rgb_color frameShadowColor; 1379 rgb_color frameLightColor; 1380 rgb_color bevelShadowColor; 1381 rgb_color bevelLightColor; 1382 BGradientLinear fillGradient; 1383 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3)); 1384 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3)); 1385 1386 if ((flags & B_DISABLED) != 0) { 1387 edgeLightColor = base; 1388 edgeShadowColor = base; 1389 frameLightColor = tint_color(base, 1.25); 1390 frameShadowColor = tint_color(base, 1.30); 1391 bevelLightColor = tint_color(base, 0.8); 1392 bevelShadowColor = tint_color(base, 1.07); 1393 fillGradient.AddColor(tint_color(base, 0.85), 0); 1394 fillGradient.AddColor(base, 255); 1395 } else { 1396 edgeLightColor = tint_color(base, 0.80); 1397 edgeShadowColor = tint_color(base, 1.03); 1398 frameLightColor = tint_color(base, 1.30); 1399 frameShadowColor = tint_color(base, 1.30); 1400 bevelLightColor = tint_color(base, 0.6); 1401 bevelShadowColor = tint_color(base, 1.07); 1402 fillGradient.AddColor(tint_color(base, 0.75), 0); 1403 fillGradient.AddColor(tint_color(base, 1.03), 255); 1404 } 1405 1406 static const float kRoundCornerRadius = 4.0f; 1407 1408 // left top corner dimensions 1409 BRect leftTopCorner(rect); 1410 leftTopCorner.right = floorf(leftTopCorner.left + kRoundCornerRadius); 1411 leftTopCorner.bottom = floorf(rect.top + kRoundCornerRadius); 1412 clipping.Exclude(leftTopCorner); 1413 1414 // draw the left top corner 1415 _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base, 1416 edgeShadowColor, frameLightColor, bevelLightColor, 1417 fillGradient); 1418 1419 // right top corner dimensions 1420 BRect rightTopCorner(rect); 1421 rightTopCorner.right = floorf(rect.right); 1422 rightTopCorner.left = floorf(rightTopCorner.right - kRoundCornerRadius); 1423 rightTopCorner.bottom = floorf(rect.top + kRoundCornerRadius); 1424 clipping.Exclude(rightTopCorner); 1425 1426 // draw the right top corner 1427 _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base, 1428 edgeShadowColor, edgeLightColor, frameLightColor, 1429 frameShadowColor, bevelLightColor, bevelShadowColor, 1430 fillGradient); 1431 1432 // clip out the corners 1433 view->ConstrainClippingRegion(&clipping); 1434 1435 // draw the rest of frame and fill 1436 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, 1437 edgeLightColor, 1438 borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER)); 1439 if ((borders & B_LEFT_BORDER) == 0) 1440 rect.left++; 1441 if ((borders & B_RIGHT_BORDER) == 0) 1442 rect.right--; 1443 1444 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, 1445 frameShadowColor, B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER); 1446 1447 _DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor, 1448 bevelShadowColor); 1449 1450 view->FillRect(rect, fillGradient); 1451 1452 // restore the clipping constraints of the view 1453 view->PopState(); 1454 } 1455 1456 1457 void 1458 BControlLook::DrawInactiveTab(BView* view, BRect& rect, const BRect& updateRect, 1459 const rgb_color& base, uint32 flags, uint32 borders) 1460 { 1461 if (!rect.IsValid() || !rect.Intersects(updateRect)) 1462 return; 1463 1464 rgb_color edgeShadowColor; 1465 rgb_color edgeLightColor; 1466 rgb_color frameShadowColor; 1467 rgb_color frameLightColor; 1468 rgb_color bevelShadowColor; 1469 rgb_color bevelLightColor; 1470 BGradientLinear fillGradient; 1471 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3)); 1472 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3)); 1473 1474 if ((flags & B_DISABLED) != 0) { 1475 edgeLightColor = base; 1476 edgeShadowColor = base; 1477 frameLightColor = tint_color(base, 1.25); 1478 frameShadowColor = tint_color(base, 1.30); 1479 bevelLightColor = tint_color(base, 0.8); 1480 bevelShadowColor = tint_color(base, 1.07); 1481 fillGradient.AddColor(tint_color(base, 0.85), 0); 1482 fillGradient.AddColor(base, 255); 1483 } else { 1484 edgeLightColor = tint_color(base, 0.80); 1485 edgeShadowColor = tint_color(base, 1.03); 1486 frameLightColor = tint_color(base, 1.30); 1487 frameShadowColor = tint_color(base, 1.30); 1488 bevelLightColor = tint_color(base, 1.10); 1489 bevelShadowColor = tint_color(base, 1.17); 1490 fillGradient.AddColor(tint_color(base, 1.12), 0); 1491 fillGradient.AddColor(tint_color(base, 1.08), 255); 1492 } 1493 1494 // active tabs stand out at the top, but this is an inactive tab 1495 view->SetHighColor(base); 1496 view->FillRect(BRect(rect.left, rect.top, rect.right, rect.top + 4)); 1497 rect.top += 4; 1498 1499 // frame and fill 1500 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, 1501 edgeLightColor, 1502 borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER)); 1503 1504 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, 1505 frameShadowColor, 1506 borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER)); 1507 1508 if (rect.IsValid()) { 1509 _DrawFrame(view, rect, bevelShadowColor, bevelShadowColor, 1510 bevelLightColor, bevelLightColor, B_LEFT_BORDER & ~borders); 1511 } else { 1512 if ((B_LEFT_BORDER & ~borders) != 0) 1513 rect.left++; 1514 } 1515 1516 view->FillRect(rect, fillGradient); 1517 } 1518 1519 1520 void 1521 BControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect, 1522 const rgb_color& base, orientation orientation, uint32 flags, 1523 uint32 borders) 1524 { 1525 if (!rect.IsValid() || !rect.Intersects(updateRect)) 1526 return; 1527 1528 rgb_color background; 1529 if ((flags & (B_CLICKED | B_ACTIVATED)) != 0) 1530 background = tint_color(base, B_DARKEN_1_TINT); 1531 else 1532 background = base; 1533 1534 rgb_color light = tint_color(background, 0.6); 1535 rgb_color shadow = tint_color(background, 1.21); 1536 1537 // frame 1538 if (borders != 0 && rect.Width() > 3 && rect.Height() > 3) 1539 DrawRaisedBorder(view, rect, updateRect, background, flags, borders); 1540 1541 // dots and rest of background 1542 if (orientation == B_HORIZONTAL) { 1543 if (rect.Width() > 2) { 1544 // background on left/right 1545 BRegion region(rect); 1546 rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5); 1547 rect.right = rect.left + 1; 1548 region.Exclude(rect); 1549 view->SetHighColor(background); 1550 view->FillRegion(®ion); 1551 } 1552 1553 BPoint dot = rect.LeftTop(); 1554 BPoint stop = rect.LeftBottom(); 1555 int32 num = 1; 1556 while (dot.y <= stop.y) { 1557 rgb_color col1; 1558 rgb_color col2; 1559 switch (num) { 1560 case 1: 1561 col1 = background; 1562 col2 = background; 1563 break; 1564 case 2: 1565 col1 = shadow; 1566 col2 = background; 1567 break; 1568 case 3: 1569 default: 1570 col1 = background; 1571 col2 = light; 1572 num = 0; 1573 break; 1574 } 1575 view->SetHighColor(col1); 1576 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1577 view->SetHighColor(col2); 1578 dot.x++; 1579 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1580 dot.x -= 1.0; 1581 // next pixel 1582 num++; 1583 dot.y++; 1584 } 1585 } else { 1586 if (rect.Height() > 2) { 1587 // background on left/right 1588 BRegion region(rect); 1589 rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5); 1590 rect.bottom = rect.top + 1; 1591 region.Exclude(rect); 1592 view->SetHighColor(background); 1593 view->FillRegion(®ion); 1594 } 1595 1596 BPoint dot = rect.LeftTop(); 1597 BPoint stop = rect.RightTop(); 1598 int32 num = 1; 1599 while (dot.x <= stop.x) { 1600 rgb_color col1; 1601 rgb_color col2; 1602 switch (num) { 1603 case 1: 1604 col1 = background; 1605 col2 = background; 1606 break; 1607 case 2: 1608 col1 = shadow; 1609 col2 = background; 1610 break; 1611 case 3: 1612 default: 1613 col1 = background; 1614 col2 = light; 1615 num = 0; 1616 break; 1617 } 1618 view->SetHighColor(col1); 1619 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1620 view->SetHighColor(col2); 1621 dot.y++; 1622 view->StrokeLine(dot, dot, B_SOLID_HIGH); 1623 dot.y -= 1.0; 1624 // next pixel 1625 num++; 1626 dot.x++; 1627 } 1628 } 1629 } 1630 1631 1632 // #pragma mark - 1633 1634 1635 void 1636 BControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect, 1637 const rgb_color& base, border_style border, uint32 flags, uint32 borders) 1638 { 1639 if (border == B_NO_BORDER) 1640 return; 1641 1642 rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT); 1643 if ((flags & B_FOCUSED) != 0) 1644 scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 1645 1646 if (border == B_FANCY_BORDER) 1647 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); 1648 1649 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 1650 scrollbarFrameColor, scrollbarFrameColor, borders); 1651 } 1652 1653 1654 void 1655 BControlLook::DrawRaisedBorder(BView* view, BRect& rect, 1656 const BRect& updateRect, const rgb_color& base, uint32 flags, 1657 uint32 borders) 1658 { 1659 rgb_color lightColor; 1660 rgb_color shadowColor; 1661 1662 if ((flags & B_DISABLED) != 0) { 1663 lightColor = base; 1664 shadowColor = base; 1665 } else { 1666 lightColor = tint_color(base, 0.85); 1667 shadowColor = tint_color(base, 1.07); 1668 } 1669 1670 _DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor, 1671 borders); 1672 } 1673 1674 1675 void 1676 BControlLook::DrawTextControlBorder(BView* view, BRect& rect, 1677 const BRect& updateRect, const rgb_color& base, uint32 flags, 1678 uint32 borders) 1679 { 1680 if (!rect.Intersects(updateRect)) 1681 return; 1682 1683 rgb_color dark1BorderColor; 1684 rgb_color dark2BorderColor; 1685 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 1686 rgb_color invalidColor = ui_color(B_FAILURE_COLOR); 1687 1688 if ((flags & B_DISABLED) != 0) { 1689 _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders); 1690 1691 if ((flags & B_BLEND_FRAME) != 0) 1692 dark1BorderColor = (rgb_color){ 0, 0, 0, 40 }; 1693 else 1694 dark1BorderColor = tint_color(base, 1.15); 1695 dark2BorderColor = dark1BorderColor; 1696 } else if ((flags & B_CLICKED) != 0) { 1697 dark1BorderColor = tint_color(base, 1.50); 1698 dark2BorderColor = tint_color(base, 1.49); 1699 1700 // BCheckBox uses this to indicate the clicked state... 1701 _DrawFrame(view, rect, 1702 dark1BorderColor, dark1BorderColor, 1703 dark2BorderColor, dark2BorderColor); 1704 1705 dark2BorderColor = dark1BorderColor; 1706 } else { 1707 _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders); 1708 1709 if ((flags & B_BLEND_FRAME) != 0) { 1710 dark1BorderColor = (rgb_color){ 0, 0, 0, 102 }; 1711 dark2BorderColor = (rgb_color){ 0, 0, 0, 97 }; 1712 } else { 1713 dark1BorderColor = tint_color(base, 1.40); 1714 dark2BorderColor = tint_color(base, 1.38); 1715 } 1716 } 1717 1718 if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) { 1719 dark1BorderColor = navigationColor; 1720 dark2BorderColor = navigationColor; 1721 } 1722 1723 if ((flags & B_DISABLED) == 0 && (flags & B_INVALID) != 0) { 1724 dark1BorderColor = invalidColor; 1725 dark2BorderColor = invalidColor; 1726 } 1727 1728 if ((flags & B_BLEND_FRAME) != 0) { 1729 drawing_mode oldMode = view->DrawingMode(); 1730 view->SetDrawingMode(B_OP_ALPHA); 1731 1732 _DrawFrame(view, rect, 1733 dark1BorderColor, dark1BorderColor, 1734 dark2BorderColor, dark2BorderColor, borders); 1735 1736 view->SetDrawingMode(oldMode); 1737 } else { 1738 _DrawFrame(view, rect, 1739 dark1BorderColor, dark1BorderColor, 1740 dark2BorderColor, dark2BorderColor, borders); 1741 } 1742 } 1743 1744 1745 void 1746 BControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect, 1747 const rgb_color& base, uint32 borders) 1748 { 1749 rgb_color frameColor = tint_color(base, 1.30); 1750 rgb_color bevelLight = tint_color(base, 0.8); 1751 rgb_color bevelShadow = tint_color(base, 1.03); 1752 1753 _DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight, 1754 borders); 1755 1756 _DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor, 1757 borders); 1758 1759 _DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow, 1760 borders); 1761 } 1762 1763 1764 void 1765 BControlLook::DrawLabel(BView* view, const char* label, BRect rect, 1766 const BRect& updateRect, const rgb_color& base, uint32 flags, 1767 const rgb_color* textColor) 1768 { 1769 DrawLabel(view, label, NULL, rect, updateRect, base, flags, 1770 DefaultLabelAlignment(), textColor); 1771 } 1772 1773 1774 void 1775 BControlLook::DrawLabel(BView* view, const char* label, BRect rect, 1776 const BRect& updateRect, const rgb_color& base, uint32 flags, 1777 const BAlignment& alignment, const rgb_color* textColor) 1778 { 1779 DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment, 1780 textColor); 1781 } 1782 1783 1784 void 1785 BControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base, 1786 uint32 flags, const BPoint& where, const rgb_color* textColor) 1787 { 1788 // setup the text color 1789 1790 BWindow* window = view->Window(); 1791 bool isDesktop = window 1792 && window->Feel() == kPrivateDesktopWindowFeel 1793 && window->Look() == kPrivateDesktopWindowLook 1794 && view->Parent() 1795 && view->Parent()->Parent() == NULL 1796 && (flags & B_IGNORE_OUTLINE) == 0; 1797 1798 rgb_color low; 1799 rgb_color color; 1800 rgb_color glowColor; 1801 1802 if (textColor != NULL) 1803 glowColor = *textColor; 1804 else if ((flags & B_IS_CONTROL) != 0) 1805 glowColor = ui_color(B_CONTROL_TEXT_COLOR); 1806 else 1807 glowColor = ui_color(B_PANEL_TEXT_COLOR); 1808 1809 color = glowColor; 1810 1811 if (isDesktop) 1812 low = view->Parent()->ViewColor(); 1813 else 1814 low = base; 1815 1816 if ((flags & B_DISABLED) != 0) { 1817 color.red = (uint8)(((int32)low.red + color.red + 1) / 2); 1818 color.green = (uint8)(((int32)low.green + color.green + 1) / 2); 1819 color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2); 1820 } 1821 1822 drawing_mode oldMode = view->DrawingMode(); 1823 1824 if (isDesktop) { 1825 // drawing occurs on the desktop 1826 if (fCachedWorkspace != current_workspace()) { 1827 int8 indice = 0; 1828 int32 mask; 1829 bool tmpOutline; 1830 while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces", 1831 indice, &mask) == B_OK 1832 && fBackgroundInfo.FindBool("be:bgndimginfoerasetext", 1833 indice, &tmpOutline) == B_OK) { 1834 1835 if (((1 << current_workspace()) & mask) != 0) { 1836 fCachedOutline = tmpOutline; 1837 fCachedWorkspace = current_workspace(); 1838 break; 1839 } 1840 indice++; 1841 } 1842 } 1843 1844 if (fCachedOutline) { 1845 BFont font; 1846 view->GetFont(&font); 1847 1848 view->SetDrawingMode(B_OP_ALPHA); 1849 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 1850 // Draw glow or outline 1851 if (glowColor.Brightness() > 128) { 1852 font.SetFalseBoldWidth(2.0); 1853 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1854 1855 glowColor.alpha = 30; 1856 view->SetHighColor(glowColor); 1857 view->DrawString(label, where); 1858 1859 font.SetFalseBoldWidth(1.0); 1860 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1861 1862 glowColor.alpha = 65; 1863 view->SetHighColor(glowColor); 1864 view->DrawString(label, where); 1865 1866 font.SetFalseBoldWidth(0.0); 1867 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1868 } else { 1869 font.SetFalseBoldWidth(1.0); 1870 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1871 1872 glowColor.alpha = 30; 1873 view->SetHighColor(glowColor); 1874 view->DrawString(label, where); 1875 1876 font.SetFalseBoldWidth(0.0); 1877 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1878 1879 glowColor.alpha = 200; 1880 view->SetHighColor(glowColor); 1881 view->DrawString(label, BPoint(where.x + 1, where.y + 1)); 1882 } 1883 } 1884 } 1885 1886 view->SetHighColor(color); 1887 view->SetDrawingMode(B_OP_OVER); 1888 view->DrawString(label, where); 1889 view->SetDrawingMode(oldMode); 1890 } 1891 1892 1893 void 1894 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon, 1895 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags, 1896 const rgb_color* textColor) 1897 { 1898 DrawLabel(view, label, icon, rect, updateRect, base, flags, 1899 DefaultLabelAlignment(), textColor); 1900 } 1901 1902 1903 void 1904 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon, 1905 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags, 1906 const BAlignment& alignment, const rgb_color* textColor) 1907 { 1908 if (!rect.Intersects(updateRect)) 1909 return; 1910 1911 if (label == NULL && icon == NULL) 1912 return; 1913 1914 if (label == NULL) { 1915 // icon only 1916 BRect alignedRect = BLayoutUtils::AlignInFrame(rect, 1917 icon->Bounds().Size(), alignment); 1918 drawing_mode oldMode = view->DrawingMode(); 1919 view->SetDrawingMode(B_OP_OVER); 1920 view->DrawBitmap(icon, alignedRect.LeftTop()); 1921 view->SetDrawingMode(oldMode); 1922 return; 1923 } 1924 1925 // label, possibly with icon 1926 float availableWidth = rect.Width() + 1; 1927 float width = 0; 1928 float textOffset = 0; 1929 float height = 0; 1930 1931 if (icon != NULL) { 1932 width = icon->Bounds().Width() + DefaultLabelSpacing() + 1; 1933 height = icon->Bounds().Height() + 1; 1934 textOffset = width; 1935 availableWidth -= textOffset; 1936 } 1937 1938 // truncate the label if necessary and get the width and height 1939 BString truncatedLabel(label); 1940 1941 BFont font; 1942 view->GetFont(&font); 1943 1944 font.TruncateString(&truncatedLabel, B_TRUNCATE_END, availableWidth); 1945 width += ceilf(font.StringWidth(truncatedLabel.String())); 1946 1947 font_height fontHeight; 1948 font.GetHeight(&fontHeight); 1949 float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); 1950 height = std::max(height, textHeight); 1951 1952 // handle alignment 1953 BRect alignedRect(BLayoutUtils::AlignOnRect(rect, 1954 BSize(width - 1, height - 1), alignment)); 1955 1956 if (icon != NULL) { 1957 BPoint location(alignedRect.LeftTop()); 1958 if (icon->Bounds().Height() + 1 < height) 1959 location.y += ceilf((height - icon->Bounds().Height() - 1) / 2); 1960 1961 drawing_mode oldMode = view->DrawingMode(); 1962 view->SetDrawingMode(B_OP_OVER); 1963 view->DrawBitmap(icon, location); 1964 view->SetDrawingMode(oldMode); 1965 } 1966 1967 BPoint location(alignedRect.left + textOffset, 1968 alignedRect.top + ceilf(fontHeight.ascent)); 1969 if (textHeight < height) 1970 location.y += ceilf((height - textHeight) / 2); 1971 1972 DrawLabel(view, truncatedLabel.String(), base, flags, location, textColor); 1973 } 1974 1975 1976 void 1977 BControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left, 1978 float& _top, float& _right, float& _bottom) 1979 { 1980 // All frames have the same inset on each side. 1981 float inset = 0; 1982 1983 switch (frameType) { 1984 case B_BUTTON_FRAME: 1985 inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2; 1986 break; 1987 case B_GROUP_FRAME: 1988 case B_MENU_FIELD_FRAME: 1989 inset = 3; 1990 break; 1991 case B_SCROLL_VIEW_FRAME: 1992 case B_TEXT_CONTROL_FRAME: 1993 inset = 2; 1994 break; 1995 } 1996 1997 _left = inset; 1998 _top = inset; 1999 _right = inset; 2000 _bottom = inset; 2001 } 2002 2003 2004 void 2005 BControlLook::GetBackgroundInsets(background_type backgroundType, 2006 uint32 flags, float& _left, float& _top, float& _right, float& _bottom) 2007 { 2008 // Most backgrounds have the same inset on each side. 2009 float inset = 0; 2010 2011 switch (backgroundType) { 2012 case B_BUTTON_BACKGROUND: 2013 case B_MENU_BACKGROUND: 2014 case B_MENU_BAR_BACKGROUND: 2015 case B_MENU_FIELD_BACKGROUND: 2016 case B_MENU_ITEM_BACKGROUND: 2017 inset = 1; 2018 break; 2019 case B_BUTTON_WITH_POP_UP_BACKGROUND: 2020 _left = 1; 2021 _top = 1; 2022 _right = 1 + kButtonPopUpIndicatorWidth; 2023 _bottom = 1; 2024 return; 2025 case B_HORIZONTAL_SCROLL_BAR_BACKGROUND: 2026 _left = 2; 2027 _top = 0; 2028 _right = 1; 2029 _bottom = 0; 2030 return; 2031 case B_VERTICAL_SCROLL_BAR_BACKGROUND: 2032 _left = 0; 2033 _top = 2; 2034 _right = 0; 2035 _bottom = 1; 2036 return; 2037 } 2038 2039 _left = inset; 2040 _top = inset; 2041 _right = inset; 2042 _bottom = inset; 2043 } 2044 2045 2046 void 2047 BControlLook::GetInsets(frame_type frameType, background_type backgroundType, 2048 uint32 flags, float& _left, float& _top, float& _right, float& _bottom) 2049 { 2050 GetFrameInsets(frameType, flags, _left, _top, _right, _bottom); 2051 2052 float left, top, right, bottom; 2053 GetBackgroundInsets(backgroundType, flags, left, top, right, bottom); 2054 2055 _left += left; 2056 _top += top; 2057 _right += right; 2058 _bottom += bottom; 2059 } 2060 2061 2062 void 2063 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2064 const BRect& updateRect, const rgb_color& base, uint32 flags, 2065 uint32 borders, orientation orientation) 2066 { 2067 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, 2068 base, true, flags, borders, orientation); 2069 } 2070 2071 2072 void 2073 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2074 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 2075 uint32 borders, orientation orientation) 2076 { 2077 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius, 2078 radius, base, true, flags, borders, orientation); 2079 } 2080 2081 2082 void 2083 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2084 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2085 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2086 uint32 flags, uint32 borders, orientation orientation) 2087 { 2088 _DrawButtonBackground(view, rect, updateRect, leftTopRadius, 2089 rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags, 2090 borders, orientation); 2091 } 2092 2093 2094 void 2095 BControlLook::SetBackgroundInfo(const BMessage& backgroundInfo) 2096 { 2097 fBackgroundInfo = backgroundInfo; 2098 fCachedWorkspace = -1; 2099 } 2100 2101 2102 // #pragma mark - 2103 2104 2105 void 2106 BControlLook::_DrawButtonFrame(BView* view, BRect& rect, 2107 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2108 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2109 const rgb_color& background, float contrast, float brightness, 2110 uint32 flags, uint32 borders) 2111 { 2112 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2113 return; 2114 2115 // save the clipping constraints of the view 2116 view->PushState(); 2117 2118 // set clipping constraints to updateRect 2119 BRegion clipping(updateRect); 2120 view->ConstrainClippingRegion(&clipping); 2121 2122 // If the button is flat and neither activated nor otherwise highlighted 2123 // (mouse hovering or focussed), draw it flat. 2124 if ((flags & B_FLAT) != 0 2125 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 2126 && ((flags & (B_HOVER | B_FOCUSED)) == 0 2127 || (flags & B_DISABLED) != 0)) { 2128 _DrawFrame(view, rect, background, background, background, 2129 background, borders); 2130 _DrawFrame(view, rect, background, background, background, 2131 background, borders); 2132 view->PopState(); 2133 return; 2134 } 2135 2136 // outer edge colors 2137 rgb_color edgeLightColor; 2138 rgb_color edgeShadowColor; 2139 2140 // default button frame color 2141 // TODO: B_BLEND_FRAME 2142 float defaultIndicatorTint = 1.2; 2143 if ((flags & B_DISABLED) != 0) 2144 defaultIndicatorTint = (B_NO_TINT + defaultIndicatorTint) / 2; 2145 2146 rgb_color defaultIndicatorColor = tint_color(base, defaultIndicatorTint); 2147 rgb_color cornerBgColor; 2148 2149 drawing_mode oldMode = view->DrawingMode(); 2150 2151 if ((flags & B_DEFAULT_BUTTON) != 0) { 2152 defaultIndicatorColor = ui_color(B_CONTROL_HIGHLIGHT_COLOR); 2153 cornerBgColor = defaultIndicatorColor; 2154 edgeLightColor = _EdgeLightColor(defaultIndicatorColor, 2155 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), 2156 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags); 2157 edgeShadowColor = _EdgeShadowColor(defaultIndicatorColor, 2158 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), 2159 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags); 2160 2161 // draw default button indicator 2162 view->SetHighColor(background); 2163 view->FillRect(rect); 2164 view->SetHighColor(base); 2165 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 2166 rect.InsetBy(1, 1); 2167 2168 view->SetHighColor(defaultIndicatorColor); 2169 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 2170 rect.InsetBy(1, 1); 2171 2172 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 2173 rect.InsetBy(1, 1); 2174 } else { 2175 cornerBgColor = background; 2176 if ((flags & B_BLEND_FRAME) != 0) { 2177 // set the background color to transparent for the case 2178 // that we are on the desktop 2179 cornerBgColor.alpha = 0; 2180 view->SetDrawingMode(B_OP_ALPHA); 2181 } 2182 2183 edgeLightColor = _EdgeLightColor(background, 2184 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0), 2185 brightness * 1.0, flags); 2186 edgeShadowColor = _EdgeShadowColor(background, 2187 contrast * (flags & B_DISABLED) != 0 ? 0.0 : 1.0, 2188 brightness * 1.0, flags); 2189 } 2190 2191 // frame colors 2192 rgb_color frameLightColor = _FrameLightColor(base, flags); 2193 rgb_color frameShadowColor = _FrameShadowColor(base, flags); 2194 2195 // rounded corners 2196 2197 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 2198 && leftTopRadius > 0) { 2199 // draw left top rounded corner 2200 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 2201 floorf(rect.left + leftTopRadius), 2202 floorf(rect.top + leftTopRadius)); 2203 clipping.Exclude(leftTopCorner); 2204 _DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect, 2205 cornerBgColor, edgeShadowColor, frameLightColor); 2206 } 2207 2208 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 2209 && rightTopRadius > 0) { 2210 // draw right top rounded corner 2211 BRect rightTopCorner(floorf(rect.right - rightTopRadius), 2212 floorf(rect.top), floorf(rect.right), 2213 floorf(rect.top + rightTopRadius)); 2214 clipping.Exclude(rightTopCorner); 2215 _DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect, 2216 cornerBgColor, edgeShadowColor, edgeLightColor, 2217 frameLightColor, frameShadowColor); 2218 } 2219 2220 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2221 && leftBottomRadius > 0) { 2222 // draw left bottom rounded corner 2223 BRect leftBottomCorner(floorf(rect.left), 2224 floorf(rect.bottom - leftBottomRadius), 2225 floorf(rect.left + leftBottomRadius), floorf(rect.bottom)); 2226 clipping.Exclude(leftBottomCorner); 2227 _DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect, 2228 cornerBgColor, edgeShadowColor, edgeLightColor, 2229 frameLightColor, frameShadowColor); 2230 } 2231 2232 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2233 && rightBottomRadius > 0) { 2234 // draw right bottom rounded corner 2235 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius), 2236 floorf(rect.bottom - rightBottomRadius), floorf(rect.right), 2237 floorf(rect.bottom)); 2238 clipping.Exclude(rightBottomCorner); 2239 _DrawRoundCornerFrameRightBottom(view, rightBottomCorner, 2240 updateRect, cornerBgColor, edgeLightColor, frameShadowColor); 2241 } 2242 2243 // clip out the corners 2244 view->ConstrainClippingRegion(&clipping); 2245 2246 // draw outer edge 2247 if ((flags & B_DEFAULT_BUTTON) != 0) { 2248 _DrawOuterResessedFrame(view, rect, defaultIndicatorColor, 2249 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), 2250 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), 2251 flags, borders); 2252 } else { 2253 _DrawOuterResessedFrame(view, rect, background, 2254 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0), 2255 brightness * 1.0, flags, borders); 2256 } 2257 2258 view->SetDrawingMode(oldMode); 2259 2260 // draw frame 2261 if ((flags & B_BLEND_FRAME) != 0) { 2262 drawing_mode oldDrawingMode = view->DrawingMode(); 2263 view->SetDrawingMode(B_OP_ALPHA); 2264 2265 _DrawFrame(view, rect, frameLightColor, frameLightColor, 2266 frameShadowColor, frameShadowColor, borders); 2267 2268 view->SetDrawingMode(oldDrawingMode); 2269 } else { 2270 _DrawFrame(view, rect, frameLightColor, frameLightColor, 2271 frameShadowColor, frameShadowColor, borders); 2272 } 2273 2274 // restore the clipping constraints of the view 2275 view->PopState(); 2276 } 2277 2278 2279 void 2280 BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect, 2281 const rgb_color& base, float contrast, float brightness, uint32 flags, 2282 uint32 borders) 2283 { 2284 rgb_color edgeLightColor = _EdgeLightColor(base, contrast, 2285 brightness, flags); 2286 rgb_color edgeShadowColor = _EdgeShadowColor(base, contrast, 2287 brightness, flags); 2288 2289 if ((flags & B_BLEND_FRAME) != 0) { 2290 // assumes the background has already been painted 2291 drawing_mode oldDrawingMode = view->DrawingMode(); 2292 view->SetDrawingMode(B_OP_ALPHA); 2293 2294 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, 2295 edgeLightColor, edgeLightColor, borders); 2296 2297 view->SetDrawingMode(oldDrawingMode); 2298 } else { 2299 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, 2300 edgeLightColor, edgeLightColor, borders); 2301 } 2302 } 2303 2304 2305 void 2306 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, 2307 const rgb_color& top, const rgb_color& right, const rgb_color& bottom, 2308 uint32 borders) 2309 { 2310 view->BeginLineArray(4); 2311 2312 if (borders & B_LEFT_BORDER) { 2313 view->AddLine( 2314 BPoint(rect.left, rect.bottom), 2315 BPoint(rect.left, rect.top), left); 2316 rect.left++; 2317 } 2318 if (borders & B_TOP_BORDER) { 2319 view->AddLine( 2320 BPoint(rect.left, rect.top), 2321 BPoint(rect.right, rect.top), top); 2322 rect.top++; 2323 } 2324 if (borders & B_RIGHT_BORDER) { 2325 view->AddLine( 2326 BPoint(rect.right, rect.top), 2327 BPoint(rect.right, rect.bottom), right); 2328 rect.right--; 2329 } 2330 if (borders & B_BOTTOM_BORDER) { 2331 view->AddLine( 2332 BPoint(rect.left, rect.bottom), 2333 BPoint(rect.right, rect.bottom), bottom); 2334 rect.bottom--; 2335 } 2336 2337 view->EndLineArray(); 2338 } 2339 2340 2341 void 2342 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, 2343 const rgb_color& top, const rgb_color& right, const rgb_color& bottom, 2344 const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders) 2345 { 2346 view->BeginLineArray(6); 2347 2348 if (borders & B_TOP_BORDER) { 2349 if (borders & B_RIGHT_BORDER) { 2350 view->AddLine( 2351 BPoint(rect.left, rect.top), 2352 BPoint(rect.right - 1, rect.top), top); 2353 view->AddLine( 2354 BPoint(rect.right, rect.top), 2355 BPoint(rect.right, rect.top), rightTop); 2356 } else { 2357 view->AddLine( 2358 BPoint(rect.left, rect.top), 2359 BPoint(rect.right, rect.top), top); 2360 } 2361 rect.top++; 2362 } 2363 2364 if (borders & B_LEFT_BORDER) { 2365 view->AddLine( 2366 BPoint(rect.left, rect.top), 2367 BPoint(rect.left, rect.bottom - 1), left); 2368 view->AddLine( 2369 BPoint(rect.left, rect.bottom), 2370 BPoint(rect.left, rect.bottom), leftBottom); 2371 rect.left++; 2372 } 2373 2374 if (borders & B_BOTTOM_BORDER) { 2375 view->AddLine( 2376 BPoint(rect.left, rect.bottom), 2377 BPoint(rect.right, rect.bottom), bottom); 2378 rect.bottom--; 2379 } 2380 2381 if (borders & B_RIGHT_BORDER) { 2382 view->AddLine( 2383 BPoint(rect.right, rect.bottom), 2384 BPoint(rect.right, rect.top), right); 2385 rect.right--; 2386 } 2387 2388 view->EndLineArray(); 2389 } 2390 2391 2392 void 2393 BControlLook::_DrawButtonBackground(BView* view, BRect& rect, 2394 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2395 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2396 bool popupIndicator, uint32 flags, uint32 borders, orientation orientation) 2397 { 2398 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2399 return; 2400 2401 // save the clipping constraints of the view 2402 view->PushState(); 2403 2404 // set clipping constraints to updateRect 2405 BRegion clipping(updateRect); 2406 view->ConstrainClippingRegion(&clipping); 2407 2408 // If the button is flat and neither activated nor otherwise highlighted 2409 // (mouse hovering or focussed), draw it flat. 2410 if ((flags & B_FLAT) != 0 2411 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 2412 && ((flags & (B_HOVER | B_FOCUSED)) == 0 2413 || (flags & B_DISABLED) != 0)) { 2414 _DrawFlatButtonBackground(view, rect, updateRect, base, popupIndicator, 2415 flags, borders, orientation); 2416 } else { 2417 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, 2418 leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius, 2419 base, popupIndicator, flags, borders, orientation); 2420 } 2421 2422 // restore the clipping constraints of the view 2423 view->PopState(); 2424 } 2425 2426 2427 void 2428 BControlLook::_DrawFlatButtonBackground(BView* view, BRect& rect, 2429 const BRect& updateRect, const rgb_color& base, bool popupIndicator, 2430 uint32 flags, uint32 borders, orientation orientation) 2431 { 2432 _DrawFrame(view, rect, base, base, base, base, borders); 2433 // Not an actual frame, but the method insets our rect as needed. 2434 2435 view->SetHighColor(base); 2436 view->FillRect(rect); 2437 2438 if (popupIndicator) { 2439 BRect indicatorRect(rect); 2440 rect.right -= kButtonPopUpIndicatorWidth; 2441 indicatorRect.left = rect.right + 3; 2442 // 2 pixels for the separator 2443 2444 view->SetHighColor(base); 2445 view->FillRect(indicatorRect); 2446 2447 _DrawPopUpMarker(view, indicatorRect, base, flags); 2448 } 2449 } 2450 2451 2452 void 2453 BControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect, 2454 const BRect& updateRect, BRegion& clipping, float leftTopRadius, 2455 float rightTopRadius, float leftBottomRadius, float rightBottomRadius, 2456 const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders, 2457 orientation orientation) 2458 { 2459 // inner bevel colors 2460 rgb_color bevelLightColor = _BevelLightColor(base, flags); 2461 rgb_color bevelShadowColor = _BevelShadowColor(base, flags); 2462 2463 // button background color 2464 rgb_color buttonBgColor; 2465 if ((flags & B_DISABLED) != 0) 2466 buttonBgColor = tint_color(base, 0.7); 2467 else 2468 buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT); 2469 2470 // surface top gradient 2471 BGradientLinear fillGradient; 2472 _MakeButtonGradient(fillGradient, rect, base, flags, orientation); 2473 2474 // rounded corners 2475 2476 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 2477 && leftTopRadius > 0) { 2478 // draw left top rounded corner 2479 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 2480 floorf(rect.left + leftTopRadius - 2.0), 2481 floorf(rect.top + leftTopRadius - 2.0)); 2482 clipping.Exclude(leftTopCorner); 2483 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, 2484 bevelLightColor, fillGradient); 2485 } 2486 2487 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 2488 && rightTopRadius > 0) { 2489 // draw right top rounded corner 2490 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), 2491 floorf(rect.top), floorf(rect.right), 2492 floorf(rect.top + rightTopRadius - 2.0)); 2493 clipping.Exclude(rightTopCorner); 2494 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, 2495 updateRect, bevelLightColor, bevelShadowColor, fillGradient); 2496 } 2497 2498 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2499 && leftBottomRadius > 0) { 2500 // draw left bottom rounded corner 2501 BRect leftBottomCorner(floorf(rect.left), 2502 floorf(rect.bottom - leftBottomRadius + 2.0), 2503 floorf(rect.left + leftBottomRadius - 2.0), 2504 floorf(rect.bottom)); 2505 clipping.Exclude(leftBottomCorner); 2506 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, 2507 updateRect, bevelLightColor, bevelShadowColor, fillGradient); 2508 } 2509 2510 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2511 && rightBottomRadius > 0) { 2512 // draw right bottom rounded corner 2513 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), 2514 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), 2515 floorf(rect.bottom)); 2516 clipping.Exclude(rightBottomCorner); 2517 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, 2518 updateRect, bevelShadowColor, fillGradient); 2519 } 2520 2521 // clip out the corners 2522 view->ConstrainClippingRegion(&clipping); 2523 2524 // draw inner bevel 2525 2526 if ((flags & B_ACTIVATED) != 0) { 2527 view->BeginLineArray(4); 2528 2529 // shadow along left/top borders 2530 if (borders & B_LEFT_BORDER) { 2531 view->AddLine(BPoint(rect.left, rect.top), 2532 BPoint(rect.left, rect.bottom), bevelLightColor); 2533 rect.left++; 2534 } 2535 if (borders & B_TOP_BORDER) { 2536 view->AddLine(BPoint(rect.left, rect.top), 2537 BPoint(rect.right, rect.top), bevelLightColor); 2538 rect.top++; 2539 } 2540 2541 // softer shadow along left/top borders 2542 if (borders & B_LEFT_BORDER) { 2543 view->AddLine(BPoint(rect.left, rect.top), 2544 BPoint(rect.left, rect.bottom), bevelShadowColor); 2545 rect.left++; 2546 } 2547 if (borders & B_TOP_BORDER) { 2548 view->AddLine(BPoint(rect.left, rect.top), 2549 BPoint(rect.right, rect.top), bevelShadowColor); 2550 rect.top++; 2551 } 2552 2553 view->EndLineArray(); 2554 } else { 2555 _DrawFrame(view, rect, 2556 bevelLightColor, bevelLightColor, 2557 bevelShadowColor, bevelShadowColor, 2558 buttonBgColor, buttonBgColor, borders); 2559 } 2560 2561 if (popupIndicator) { 2562 BRect indicatorRect(rect); 2563 rect.right -= kButtonPopUpIndicatorWidth; 2564 indicatorRect.left = rect.right + 3; 2565 // 2 pixels for the separator 2566 2567 // Even when depressed we want the pop-up indicator background and 2568 // separator to cover the area up to the top. 2569 if ((flags & B_ACTIVATED) != 0) 2570 indicatorRect.top--; 2571 2572 // draw the separator 2573 rgb_color separatorBaseColor = base; 2574 if ((flags & B_ACTIVATED) != 0) 2575 separatorBaseColor = tint_color(base, B_DARKEN_1_TINT); 2576 2577 rgb_color separatorLightColor = _EdgeLightColor(separatorBaseColor, 2578 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags); 2579 rgb_color separatorShadowColor = _EdgeShadowColor(separatorBaseColor, 2580 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags); 2581 2582 view->BeginLineArray(2); 2583 2584 view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top), 2585 BPoint(indicatorRect.left - 2, indicatorRect.bottom), 2586 separatorShadowColor); 2587 view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top), 2588 BPoint(indicatorRect.left - 1, indicatorRect.bottom), 2589 separatorLightColor); 2590 2591 view->EndLineArray(); 2592 2593 // draw background and pop-up marker 2594 _DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect, 2595 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 0); 2596 2597 if ((flags & B_ACTIVATED) != 0) 2598 indicatorRect.top++; 2599 2600 _DrawPopUpMarker(view, indicatorRect, base, flags); 2601 } 2602 2603 // fill in the background 2604 view->FillRect(rect, fillGradient); 2605 } 2606 2607 2608 void 2609 BControlLook::_DrawPopUpMarker(BView* view, const BRect& rect, 2610 const rgb_color& base, uint32 flags) 2611 { 2612 BPoint center(roundf((rect.left + rect.right) / 2.0), 2613 roundf((rect.top + rect.bottom) / 2.0)); 2614 BPoint triangle[3]; 2615 triangle[0] = center + BPoint(-2.5, -0.5); 2616 triangle[1] = center + BPoint(2.5, -0.5); 2617 triangle[2] = center + BPoint(0.0, 2.0); 2618 2619 uint32 viewFlags = view->Flags(); 2620 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); 2621 2622 rgb_color markColor; 2623 if ((flags & B_DISABLED) != 0) 2624 markColor = tint_color(base, 1.35); 2625 else 2626 markColor = tint_color(base, 1.65); 2627 2628 view->SetHighColor(markColor); 2629 view->FillTriangle(triangle[0], triangle[1], triangle[2]); 2630 2631 view->SetFlags(viewFlags); 2632 } 2633 2634 2635 void 2636 BControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect, 2637 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2638 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2639 bool popupIndicator, uint32 flags) 2640 { 2641 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2642 return; 2643 2644 if (popupIndicator) { 2645 BRect leftRect(rect); 2646 leftRect.right -= 10; 2647 2648 BRect rightRect(rect); 2649 rightRect.left = rightRect.right - 9; 2650 2651 _DrawMenuFieldBackgroundInside(view, leftRect, updateRect, 2652 leftTopRadius, 0.0f, leftBottomRadius, 0.0f, base, flags, 2653 B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER); 2654 2655 _DrawMenuFieldBackgroundInside(view, rightRect, updateRect, 2656 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 2657 B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER); 2658 2659 _DrawPopUpMarker(view, rightRect, base, flags); 2660 2661 // draw a line on the left of the popup frame 2662 rgb_color bevelShadowColor = _BevelShadowColor(base, flags); 2663 view->SetHighColor(bevelShadowColor); 2664 BPoint leftTopCorner(floorf(rightRect.left - 1.0), 2665 floorf(rightRect.top - 1.0)); 2666 BPoint leftBottomCorner(floorf(rightRect.left - 1.0), 2667 floorf(rightRect.bottom + 1.0)); 2668 view->StrokeLine(leftTopCorner, leftBottomCorner); 2669 2670 rect = leftRect; 2671 } else { 2672 _DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius, 2673 rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags); 2674 } 2675 } 2676 2677 2678 void 2679 BControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect, 2680 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2681 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2682 uint32 flags, uint32 borders) 2683 { 2684 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2685 return; 2686 2687 // save the clipping constraints of the view 2688 view->PushState(); 2689 2690 // set clipping constraints to updateRect 2691 BRegion clipping(updateRect); 2692 view->ConstrainClippingRegion(&clipping); 2693 2694 // frame colors 2695 rgb_color frameLightColor = _FrameLightColor(base, flags); 2696 rgb_color frameShadowColor = _FrameShadowColor(base, flags); 2697 2698 // indicator background color 2699 rgb_color indicatorBase; 2700 if ((borders & B_LEFT_BORDER) != 0) 2701 indicatorBase = base; 2702 else { 2703 if ((flags & B_DISABLED) != 0) 2704 indicatorBase = tint_color(base, 1.05); 2705 else 2706 indicatorBase = tint_color(base, 1.12); 2707 } 2708 2709 // bevel colors 2710 rgb_color cornerColor = tint_color(indicatorBase, 0.85); 2711 rgb_color bevelColor1 = tint_color(indicatorBase, 0.3); 2712 rgb_color bevelColor2 = tint_color(indicatorBase, 0.5); 2713 rgb_color bevelColor3 = tint_color(indicatorBase, 1.03); 2714 2715 if ((flags & B_DISABLED) != 0) { 2716 cornerColor = tint_color(indicatorBase, 0.8); 2717 bevelColor1 = tint_color(indicatorBase, 0.7); 2718 bevelColor2 = tint_color(indicatorBase, 0.8); 2719 bevelColor3 = tint_color(indicatorBase, 1.01); 2720 } else { 2721 cornerColor = tint_color(indicatorBase, 0.85); 2722 bevelColor1 = tint_color(indicatorBase, 0.3); 2723 bevelColor2 = tint_color(indicatorBase, 0.5); 2724 bevelColor3 = tint_color(indicatorBase, 1.03); 2725 } 2726 2727 // surface top gradient 2728 BGradientLinear fillGradient; 2729 _MakeButtonGradient(fillGradient, rect, indicatorBase, flags); 2730 2731 // rounded corners 2732 2733 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 2734 && leftTopRadius > 0) { 2735 // draw left top rounded corner 2736 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 2737 floorf(rect.left + leftTopRadius - 2.0), 2738 floorf(rect.top + leftTopRadius - 2.0)); 2739 clipping.Exclude(leftTopCorner); 2740 2741 BRegion cornerClipping(leftTopCorner); 2742 view->ConstrainClippingRegion(&cornerClipping); 2743 2744 BRect ellipseRect(leftTopCorner); 2745 ellipseRect.InsetBy(-1.0, -1.0); 2746 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2747 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2748 2749 // draw the frame (again) 2750 view->SetHighColor(frameLightColor); 2751 view->FillEllipse(ellipseRect); 2752 2753 // draw the bevel and background 2754 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, 2755 bevelColor1, fillGradient); 2756 } 2757 2758 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 2759 && rightTopRadius > 0) { 2760 // draw right top rounded corner 2761 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), 2762 floorf(rect.top), floorf(rect.right), 2763 floorf(rect.top + rightTopRadius - 2.0)); 2764 clipping.Exclude(rightTopCorner); 2765 2766 BRegion cornerClipping(rightTopCorner); 2767 view->ConstrainClippingRegion(&cornerClipping); 2768 2769 BRect ellipseRect(rightTopCorner); 2770 ellipseRect.InsetBy(-1.0, -1.0); 2771 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2772 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2773 2774 // draw the frame (again) 2775 if (frameLightColor == frameShadowColor) { 2776 view->SetHighColor(frameLightColor); 2777 view->FillEllipse(ellipseRect); 2778 } else { 2779 BGradientLinear gradient; 2780 gradient.AddColor(frameLightColor, 0); 2781 gradient.AddColor(frameShadowColor, 255); 2782 gradient.SetStart(rightTopCorner.LeftTop()); 2783 gradient.SetEnd(rightTopCorner.RightBottom()); 2784 view->FillEllipse(ellipseRect, gradient); 2785 } 2786 2787 // draw the bevel and background 2788 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect, 2789 bevelColor1, bevelColor3, fillGradient); 2790 } 2791 2792 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2793 && leftBottomRadius > 0) { 2794 // draw left bottom rounded corner 2795 BRect leftBottomCorner(floorf(rect.left), 2796 floorf(rect.bottom - leftBottomRadius + 2.0), 2797 floorf(rect.left + leftBottomRadius - 2.0), 2798 floorf(rect.bottom)); 2799 clipping.Exclude(leftBottomCorner); 2800 2801 BRegion cornerClipping(leftBottomCorner); 2802 view->ConstrainClippingRegion(&cornerClipping); 2803 2804 BRect ellipseRect(leftBottomCorner); 2805 ellipseRect.InsetBy(-1.0, -1.0); 2806 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2807 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 2808 2809 // draw the frame (again) 2810 if (frameLightColor == frameShadowColor) { 2811 view->SetHighColor(frameLightColor); 2812 view->FillEllipse(ellipseRect); 2813 } else { 2814 BGradientLinear gradient; 2815 gradient.AddColor(frameLightColor, 0); 2816 gradient.AddColor(frameShadowColor, 255); 2817 gradient.SetStart(leftBottomCorner.LeftTop()); 2818 gradient.SetEnd(leftBottomCorner.RightBottom()); 2819 view->FillEllipse(ellipseRect, gradient); 2820 } 2821 2822 // draw the bevel and background 2823 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, 2824 updateRect, bevelColor2, bevelColor3, fillGradient); 2825 } 2826 2827 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2828 && rightBottomRadius > 0) { 2829 // draw right bottom rounded corner 2830 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), 2831 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), 2832 floorf(rect.bottom)); 2833 clipping.Exclude(rightBottomCorner); 2834 2835 BRegion cornerClipping(rightBottomCorner); 2836 view->ConstrainClippingRegion(&cornerClipping); 2837 2838 BRect ellipseRect(rightBottomCorner); 2839 ellipseRect.InsetBy(-1.0, -1.0); 2840 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2841 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 2842 2843 // draw the frame (again) 2844 view->SetHighColor(frameShadowColor); 2845 view->FillEllipse(ellipseRect); 2846 2847 // draw the bevel and background 2848 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, 2849 updateRect, bevelColor3, fillGradient); 2850 } 2851 2852 // clip out the corners 2853 view->ConstrainClippingRegion(&clipping); 2854 2855 // draw the bevel 2856 _DrawFrame(view, rect, 2857 bevelColor2, bevelColor1, 2858 bevelColor3, bevelColor3, 2859 cornerColor, cornerColor, 2860 borders); 2861 2862 // fill in the background 2863 view->FillRect(rect, fillGradient); 2864 2865 // restore the clipping constraints of the view 2866 view->PopState(); 2867 } 2868 2869 2870 void 2871 BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& cornerRect, 2872 const BRect& updateRect, const rgb_color& background, 2873 const rgb_color& edgeColor, const rgb_color& frameColor, 2874 const rgb_color& bevelColor, const BGradientLinear& fillGradient) 2875 { 2876 _DrawRoundCornerFrameLeftTop(view, cornerRect, updateRect, 2877 background, edgeColor, frameColor); 2878 _DrawRoundCornerBackgroundLeftTop(view, cornerRect, updateRect, 2879 bevelColor, fillGradient); 2880 } 2881 2882 2883 void 2884 BControlLook::_DrawRoundCornerFrameLeftTop(BView* view, BRect& cornerRect, 2885 const BRect& updateRect, const rgb_color& background, 2886 const rgb_color& edgeColor, const rgb_color& frameColor) 2887 { 2888 // constrain clipping region to corner 2889 BRegion clipping(cornerRect); 2890 view->ConstrainClippingRegion(&clipping); 2891 2892 // background 2893 view->SetHighColor(background); 2894 view->FillRect(cornerRect); 2895 2896 // outer edge 2897 BRect ellipseRect(cornerRect); 2898 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2899 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2900 2901 view->SetHighColor(edgeColor); 2902 view->FillEllipse(ellipseRect); 2903 2904 // frame 2905 ellipseRect.InsetBy(1, 1); 2906 cornerRect.left++; 2907 cornerRect.top++; 2908 view->SetHighColor(frameColor); 2909 view->FillEllipse(ellipseRect); 2910 2911 // prepare for bevel 2912 cornerRect.left++; 2913 cornerRect.top++; 2914 } 2915 2916 2917 void 2918 BControlLook::_DrawRoundCornerBackgroundLeftTop(BView* view, BRect& cornerRect, 2919 const BRect& updateRect, const rgb_color& bevelColor, 2920 const BGradientLinear& fillGradient) 2921 { 2922 // constrain clipping region to corner 2923 BRegion clipping(cornerRect); 2924 view->ConstrainClippingRegion(&clipping); 2925 2926 BRect ellipseRect(cornerRect); 2927 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2928 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2929 2930 // bevel 2931 view->SetHighColor(bevelColor); 2932 view->FillEllipse(ellipseRect); 2933 2934 // gradient 2935 ellipseRect.InsetBy(1, 1); 2936 view->FillEllipse(ellipseRect, fillGradient); 2937 } 2938 2939 2940 void 2941 BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& cornerRect, 2942 const BRect& updateRect, const rgb_color& background, 2943 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor, 2944 const rgb_color& frameTopColor, const rgb_color& frameRightColor, 2945 const rgb_color& bevelTopColor, const rgb_color& bevelRightColor, 2946 const BGradientLinear& fillGradient) 2947 { 2948 _DrawRoundCornerFrameRightTop(view, cornerRect, updateRect, 2949 background, edgeTopColor, edgeRightColor, frameTopColor, 2950 frameRightColor); 2951 _DrawRoundCornerBackgroundRightTop(view, cornerRect, updateRect, 2952 bevelTopColor, bevelRightColor, fillGradient); 2953 } 2954 2955 2956 void 2957 BControlLook::_DrawRoundCornerFrameRightTop(BView* view, BRect& cornerRect, 2958 const BRect& updateRect, const rgb_color& background, 2959 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor, 2960 const rgb_color& frameTopColor, const rgb_color& frameRightColor) 2961 { 2962 // constrain clipping region to corner 2963 BRegion clipping(cornerRect); 2964 view->ConstrainClippingRegion(&clipping); 2965 2966 // background 2967 view->SetHighColor(background); 2968 view->FillRect(cornerRect); 2969 2970 // outer edge 2971 BRect ellipseRect(cornerRect); 2972 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2973 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2974 2975 BGradientLinear gradient; 2976 gradient.AddColor(edgeTopColor, 0); 2977 gradient.AddColor(edgeRightColor, 255); 2978 gradient.SetStart(cornerRect.LeftTop()); 2979 gradient.SetEnd(cornerRect.RightBottom()); 2980 view->FillEllipse(ellipseRect, gradient); 2981 2982 // frame 2983 ellipseRect.InsetBy(1, 1); 2984 cornerRect.right--; 2985 cornerRect.top++; 2986 if (frameTopColor == frameRightColor) { 2987 view->SetHighColor(frameTopColor); 2988 view->FillEllipse(ellipseRect); 2989 } else { 2990 gradient.SetColor(0, frameTopColor); 2991 gradient.SetColor(1, frameRightColor); 2992 gradient.SetStart(cornerRect.LeftTop()); 2993 gradient.SetEnd(cornerRect.RightBottom()); 2994 view->FillEllipse(ellipseRect, gradient); 2995 } 2996 2997 // prepare for bevel 2998 cornerRect.right--; 2999 cornerRect.top++; 3000 } 3001 3002 3003 void 3004 BControlLook::_DrawRoundCornerBackgroundRightTop(BView* view, BRect& cornerRect, 3005 const BRect& updateRect, const rgb_color& bevelTopColor, 3006 const rgb_color& bevelRightColor, const BGradientLinear& fillGradient) 3007 { 3008 // constrain clipping region to corner 3009 BRegion clipping(cornerRect); 3010 view->ConstrainClippingRegion(&clipping); 3011 3012 BRect ellipseRect(cornerRect); 3013 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 3014 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 3015 3016 // bevel 3017 BGradientLinear gradient; 3018 gradient.AddColor(bevelTopColor, 0); 3019 gradient.AddColor(bevelRightColor, 255); 3020 gradient.SetStart(cornerRect.LeftTop()); 3021 gradient.SetEnd(cornerRect.RightBottom()); 3022 view->FillEllipse(ellipseRect, gradient); 3023 3024 // gradient 3025 ellipseRect.InsetBy(1, 1); 3026 view->FillEllipse(ellipseRect, fillGradient); 3027 } 3028 3029 3030 void 3031 BControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& cornerRect, 3032 const BRect& updateRect, const rgb_color& background, 3033 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor, 3034 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor, 3035 const rgb_color& bevelLeftColor, const rgb_color& bevelBottomColor, 3036 const BGradientLinear& fillGradient) 3037 { 3038 _DrawRoundCornerFrameLeftBottom(view, cornerRect, updateRect, 3039 background, edgeLeftColor, edgeBottomColor, frameLeftColor, 3040 frameBottomColor); 3041 _DrawRoundCornerBackgroundLeftBottom(view, cornerRect, updateRect, 3042 bevelLeftColor, bevelBottomColor, fillGradient); 3043 } 3044 3045 3046 void 3047 BControlLook::_DrawRoundCornerFrameLeftBottom(BView* view, BRect& cornerRect, 3048 const BRect& updateRect, const rgb_color& background, 3049 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor, 3050 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor) 3051 { 3052 // constrain clipping region to corner 3053 BRegion clipping(cornerRect); 3054 view->ConstrainClippingRegion(&clipping); 3055 3056 // background 3057 view->SetHighColor(background); 3058 view->FillRect(cornerRect); 3059 3060 // outer edge 3061 BRect ellipseRect(cornerRect); 3062 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 3063 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3064 3065 BGradientLinear gradient; 3066 gradient.AddColor(edgeLeftColor, 0); 3067 gradient.AddColor(edgeBottomColor, 255); 3068 gradient.SetStart(cornerRect.LeftTop()); 3069 gradient.SetEnd(cornerRect.RightBottom()); 3070 view->FillEllipse(ellipseRect, gradient); 3071 3072 // frame 3073 ellipseRect.InsetBy(1, 1); 3074 cornerRect.left++; 3075 cornerRect.bottom--; 3076 if (frameLeftColor == frameBottomColor) { 3077 view->SetHighColor(frameLeftColor); 3078 view->FillEllipse(ellipseRect); 3079 } else { 3080 gradient.SetColor(0, frameLeftColor); 3081 gradient.SetColor(1, frameBottomColor); 3082 gradient.SetStart(cornerRect.LeftTop()); 3083 gradient.SetEnd(cornerRect.RightBottom()); 3084 view->FillEllipse(ellipseRect, gradient); 3085 } 3086 3087 // prepare for bevel 3088 cornerRect.left++; 3089 cornerRect.bottom--; 3090 } 3091 3092 3093 void 3094 BControlLook::_DrawRoundCornerBackgroundLeftBottom(BView* view, BRect& cornerRect, 3095 const BRect& updateRect, const rgb_color& bevelLeftColor, 3096 const rgb_color& bevelBottomColor, const BGradientLinear& fillGradient) 3097 { 3098 // constrain clipping region to corner 3099 BRegion clipping(cornerRect); 3100 view->ConstrainClippingRegion(&clipping); 3101 3102 BRect ellipseRect(cornerRect); 3103 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 3104 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3105 3106 // bevel 3107 BGradientLinear gradient; 3108 gradient.AddColor(bevelLeftColor, 0); 3109 gradient.AddColor(bevelBottomColor, 255); 3110 gradient.SetStart(cornerRect.LeftTop()); 3111 gradient.SetEnd(cornerRect.RightBottom()); 3112 view->FillEllipse(ellipseRect, gradient); 3113 3114 // gradient 3115 ellipseRect.InsetBy(1, 1); 3116 view->FillEllipse(ellipseRect, fillGradient); 3117 } 3118 3119 3120 void 3121 BControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& cornerRect, 3122 const BRect& updateRect, const rgb_color& background, 3123 const rgb_color& edgeColor, const rgb_color& frameColor, 3124 const rgb_color& bevelColor, const BGradientLinear& fillGradient) 3125 { 3126 _DrawRoundCornerFrameRightBottom(view, cornerRect, updateRect, 3127 background, edgeColor, frameColor); 3128 _DrawRoundCornerBackgroundRightBottom(view, cornerRect, updateRect, 3129 bevelColor, fillGradient); 3130 } 3131 3132 3133 void 3134 BControlLook::_DrawRoundCornerFrameRightBottom(BView* view, BRect& cornerRect, 3135 const BRect& updateRect, const rgb_color& background, 3136 const rgb_color& edgeColor, const rgb_color& frameColor) 3137 { 3138 // constrain clipping region to corner 3139 BRegion clipping(cornerRect); 3140 view->ConstrainClippingRegion(&clipping); 3141 3142 // background 3143 view->SetHighColor(background); 3144 view->FillRect(cornerRect); 3145 3146 // outer edge 3147 BRect ellipseRect(cornerRect); 3148 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 3149 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3150 3151 view->SetHighColor(edgeColor); 3152 view->FillEllipse(ellipseRect); 3153 3154 // frame 3155 ellipseRect.InsetBy(1, 1); 3156 cornerRect.right--; 3157 cornerRect.bottom++; 3158 view->SetHighColor(frameColor); 3159 view->FillEllipse(ellipseRect); 3160 3161 // prepare for bevel 3162 cornerRect.left++; 3163 cornerRect.bottom--; 3164 } 3165 3166 3167 void 3168 BControlLook::_DrawRoundCornerBackgroundRightBottom(BView* view, 3169 BRect& cornerRect, const BRect& updateRect, const rgb_color& bevelColor, 3170 const BGradientLinear& fillGradient) 3171 { 3172 // constrain clipping region to corner 3173 BRegion clipping(cornerRect); 3174 view->ConstrainClippingRegion(&clipping); 3175 3176 BRect ellipseRect(cornerRect); 3177 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 3178 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3179 3180 // bevel 3181 view->SetHighColor(bevelColor); 3182 view->FillEllipse(ellipseRect); 3183 3184 // gradient 3185 ellipseRect.InsetBy(1, 1); 3186 view->FillEllipse(ellipseRect, fillGradient); 3187 } 3188 3189 3190 void 3191 BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect, 3192 const BRect& updateRect, 3193 const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor, 3194 const rgb_color& frameLightColor, const rgb_color& frameShadowColor, 3195 const rgb_color& fillLightColor, const rgb_color& fillShadowColor, 3196 float leftInset, float topInset, float rightInset, float bottomInset, 3197 orientation orientation) 3198 { 3199 if (!rect.IsValid() || !rect.Intersects(updateRect)) 3200 return; 3201 3202 BGradientLinear gradient; 3203 gradient.AddColor(edgeShadowColor, 0); 3204 gradient.AddColor(edgeLightColor, 255); 3205 gradient.SetStart(rect.LeftTop()); 3206 if (orientation == B_HORIZONTAL) 3207 gradient.SetEnd(rect.LeftBottom()); 3208 else 3209 gradient.SetEnd(rect.RightTop()); 3210 3211 view->FillEllipse(rect, gradient); 3212 3213 rect.left += leftInset; 3214 rect.top += topInset; 3215 rect.right += rightInset; 3216 rect.bottom += bottomInset; 3217 3218 gradient.MakeEmpty(); 3219 gradient.AddColor(frameShadowColor, 0); 3220 gradient.AddColor(frameLightColor, 255); 3221 gradient.SetStart(rect.LeftTop()); 3222 if (orientation == B_HORIZONTAL) 3223 gradient.SetEnd(rect.LeftBottom()); 3224 else 3225 gradient.SetEnd(rect.RightTop()); 3226 3227 view->FillEllipse(rect, gradient); 3228 3229 rect.left += leftInset; 3230 rect.top += topInset; 3231 rect.right += rightInset; 3232 rect.bottom += bottomInset; 3233 3234 gradient.MakeEmpty(); 3235 gradient.AddColor(fillShadowColor, 0); 3236 gradient.AddColor(fillLightColor, 255); 3237 gradient.SetStart(rect.LeftTop()); 3238 if (orientation == B_HORIZONTAL) 3239 gradient.SetEnd(rect.LeftBottom()); 3240 else 3241 gradient.SetEnd(rect.RightTop()); 3242 3243 view->FillEllipse(rect, gradient); 3244 } 3245 3246 3247 rgb_color 3248 BControlLook::_EdgeLightColor(const rgb_color& base, float contrast, 3249 float brightness, uint32 flags) 3250 { 3251 rgb_color edgeLightColor; 3252 3253 if ((flags & B_BLEND_FRAME) != 0) { 3254 uint8 alpha = uint8(20 * contrast); 3255 uint8 white = uint8(255 * brightness); 3256 3257 edgeLightColor = (rgb_color){ white, white, white, alpha }; 3258 } else { 3259 // colors 3260 float tintLight = kEdgeBevelLightTint; 3261 3262 if (contrast == 0.0) 3263 tintLight = B_NO_TINT; 3264 else if (contrast != 1.0) 3265 tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast; 3266 3267 edgeLightColor = tint_color(base, tintLight); 3268 3269 if (brightness < 1.0) { 3270 edgeLightColor.red = uint8(edgeLightColor.red * brightness); 3271 edgeLightColor.green = uint8(edgeLightColor.green * brightness); 3272 edgeLightColor.blue = uint8(edgeLightColor.blue * brightness); 3273 } 3274 } 3275 3276 return edgeLightColor; 3277 } 3278 3279 3280 rgb_color 3281 BControlLook::_EdgeShadowColor(const rgb_color& base, float contrast, 3282 float brightness, uint32 flags) 3283 { 3284 rgb_color edgeShadowColor; 3285 3286 if ((flags & B_BLEND_FRAME) != 0) { 3287 uint8 alpha = uint8(20 * contrast); 3288 edgeShadowColor = (rgb_color){ 0, 0, 0, alpha }; 3289 } else { 3290 float tintShadow = kEdgeBevelShadowTint; 3291 3292 if (contrast == 0.0) 3293 tintShadow = B_NO_TINT; 3294 else if (contrast != 1.0) 3295 tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast; 3296 3297 edgeShadowColor = tint_color(base, tintShadow); 3298 3299 if (brightness < 1.0) { 3300 edgeShadowColor.red = uint8(edgeShadowColor.red * brightness); 3301 edgeShadowColor.green = uint8(edgeShadowColor.green * brightness); 3302 edgeShadowColor.blue = uint8(edgeShadowColor.blue * brightness); 3303 } 3304 } 3305 3306 return edgeShadowColor; 3307 } 3308 3309 3310 rgb_color 3311 BControlLook::_FrameLightColor(const rgb_color& base, uint32 flags) 3312 { 3313 if ((flags & B_FOCUSED) != 0) 3314 return ui_color(B_KEYBOARD_NAVIGATION_COLOR); 3315 3316 if ((flags & B_ACTIVATED) != 0) 3317 return _FrameShadowColor(base, flags & ~B_ACTIVATED); 3318 3319 rgb_color frameLightColor; 3320 3321 if ((flags & B_DISABLED) != 0) { 3322 // TODO: B_BLEND_FRAME 3323 frameLightColor = tint_color(base, 1.145); 3324 3325 if ((flags & B_DEFAULT_BUTTON) != 0) 3326 frameLightColor = tint_color(frameLightColor, 1.14); 3327 } else { 3328 if ((flags & B_BLEND_FRAME) != 0) 3329 frameLightColor = (rgb_color){ 0, 0, 0, 75 }; 3330 else 3331 frameLightColor = tint_color(base, 1.33); 3332 3333 if ((flags & B_DEFAULT_BUTTON) != 0) 3334 frameLightColor = tint_color(frameLightColor, 1.35); 3335 } 3336 3337 return frameLightColor; 3338 } 3339 3340 3341 rgb_color 3342 BControlLook::_FrameShadowColor(const rgb_color& base, uint32 flags) 3343 { 3344 if ((flags & B_FOCUSED) != 0) 3345 return ui_color(B_KEYBOARD_NAVIGATION_COLOR); 3346 3347 if ((flags & B_ACTIVATED) != 0) 3348 return _FrameLightColor(base, flags & ~B_ACTIVATED); 3349 3350 rgb_color frameShadowColor; 3351 3352 if ((flags & B_DISABLED) != 0) { 3353 // TODO: B_BLEND_FRAME 3354 frameShadowColor = tint_color(base, 1.24); 3355 3356 if ((flags & B_DEFAULT_BUTTON) != 0) { 3357 frameShadowColor = tint_color(base, 1.145); 3358 frameShadowColor = tint_color(frameShadowColor, 1.12); 3359 } 3360 } else { 3361 if ((flags & B_DEFAULT_BUTTON) != 0) { 3362 if ((flags & B_BLEND_FRAME) != 0) 3363 frameShadowColor = (rgb_color){ 0, 0, 0, 75 }; 3364 else 3365 frameShadowColor = tint_color(base, 1.33); 3366 3367 frameShadowColor = tint_color(frameShadowColor, 1.5); 3368 } else { 3369 if ((flags & B_BLEND_FRAME) != 0) 3370 frameShadowColor = (rgb_color){ 0, 0, 0, 95 }; 3371 else 3372 frameShadowColor = tint_color(base, 1.47); 3373 } 3374 } 3375 3376 return frameShadowColor; 3377 } 3378 3379 3380 rgb_color 3381 BControlLook::_BevelLightColor(const rgb_color& base, uint32 flags) 3382 { 3383 rgb_color bevelLightColor = tint_color(base, 0.2); 3384 3385 if ((flags & B_DISABLED) != 0) 3386 bevelLightColor = tint_color(base, B_LIGHTEN_1_TINT); 3387 3388 if ((flags & B_ACTIVATED) != 0) 3389 bevelLightColor = tint_color(base, B_DARKEN_1_TINT); 3390 3391 return bevelLightColor; 3392 } 3393 3394 3395 rgb_color 3396 BControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags) 3397 { 3398 rgb_color bevelShadowColor = tint_color(base, 1.08); 3399 3400 if ((flags & B_DISABLED) != 0) 3401 bevelShadowColor = base; 3402 3403 if ((flags & B_ACTIVATED) != 0) 3404 bevelShadowColor = tint_color(base, B_DARKEN_1_TINT); 3405 3406 return bevelShadowColor; 3407 } 3408 3409 3410 void 3411 BControlLook::_FillGradient(BView* view, const BRect& rect, 3412 const rgb_color& base, float topTint, float bottomTint, 3413 orientation orientation) 3414 { 3415 BGradientLinear gradient; 3416 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); 3417 view->FillRect(rect, gradient); 3418 } 3419 3420 3421 void 3422 BControlLook::_FillGlossyGradient(BView* view, const BRect& rect, 3423 const rgb_color& base, float topTint, float middle1Tint, 3424 float middle2Tint, float bottomTint, orientation orientation) 3425 { 3426 BGradientLinear gradient; 3427 _MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint, 3428 middle2Tint, bottomTint, orientation); 3429 view->FillRect(rect, gradient); 3430 } 3431 3432 3433 void 3434 BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect, 3435 const rgb_color& base, float topTint, float bottomTint, 3436 orientation orientation) const 3437 { 3438 gradient.AddColor(tint_color(base, topTint), 0); 3439 gradient.AddColor(tint_color(base, bottomTint), 255); 3440 gradient.SetStart(rect.LeftTop()); 3441 if (orientation == B_HORIZONTAL) 3442 gradient.SetEnd(rect.LeftBottom()); 3443 else 3444 gradient.SetEnd(rect.RightTop()); 3445 } 3446 3447 3448 void 3449 BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect, 3450 const rgb_color& base, float topTint, float middle1Tint, 3451 float middle2Tint, float bottomTint, 3452 orientation orientation) const 3453 { 3454 gradient.AddColor(tint_color(base, topTint), 0); 3455 gradient.AddColor(tint_color(base, middle1Tint), 132); 3456 gradient.AddColor(tint_color(base, middle2Tint), 136); 3457 gradient.AddColor(tint_color(base, bottomTint), 255); 3458 gradient.SetStart(rect.LeftTop()); 3459 if (orientation == B_HORIZONTAL) 3460 gradient.SetEnd(rect.LeftBottom()); 3461 else 3462 gradient.SetEnd(rect.RightTop()); 3463 } 3464 3465 3466 void 3467 BControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect, 3468 const rgb_color& base, uint32 flags, orientation orientation) const 3469 { 3470 float topTint = 0.49; 3471 float middleTint1 = 0.62; 3472 float middleTint2 = 0.76; 3473 float bottomTint = 0.90; 3474 3475 if ((flags & B_ACTIVATED) != 0) { 3476 topTint = 1.11; 3477 bottomTint = 1.08; 3478 } 3479 3480 if ((flags & B_DISABLED) != 0) { 3481 topTint = (topTint + B_NO_TINT) / 2; 3482 middleTint1 = (middleTint1 + B_NO_TINT) / 2; 3483 middleTint2 = (middleTint2 + B_NO_TINT) / 2; 3484 bottomTint = (bottomTint + B_NO_TINT) / 2; 3485 } else if ((flags & B_HOVER) != 0) { 3486 topTint *= kHoverTintFactor; 3487 middleTint1 *= kHoverTintFactor; 3488 middleTint2 *= kHoverTintFactor; 3489 bottomTint *= kHoverTintFactor; 3490 } 3491 3492 if ((flags & B_ACTIVATED) != 0) { 3493 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); 3494 } else { 3495 _MakeGlossyGradient(gradient, rect, base, topTint, middleTint1, 3496 middleTint2, bottomTint, orientation); 3497 } 3498 } 3499 3500 3501 3502 bool 3503 BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base, 3504 rgb_color& color, uint32 flags) const 3505 { 3506 if ((flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED)) == 0) { 3507 // no mark to be drawn at all 3508 return false; 3509 } 3510 3511 color = ui_color(B_CONTROL_MARK_COLOR); 3512 3513 float mix = 1.0; 3514 3515 if ((flags & B_DISABLED) != 0) { 3516 // activated, but disabled 3517 mix = 0.4; 3518 } else if ((flags & B_CLICKED) != 0) { 3519 if ((flags & B_ACTIVATED) != 0) { 3520 // losing activation 3521 mix = 0.7; 3522 } else { 3523 // becoming activated (or losing partial activation) 3524 mix = 0.3; 3525 } 3526 } else if ((flags & B_PARTIALLY_ACTIVATED) != 0) { 3527 // partially activated 3528 mix = 0.5; 3529 } else { 3530 // simply activated 3531 } 3532 3533 color.red = uint8(color.red * mix + base.red * (1.0 - mix)); 3534 color.green = uint8(color.green * mix + base.green * (1.0 - mix)); 3535 color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix)); 3536 3537 return true; 3538 } 3539 3540 3541 // NOTE: May come from a add-on in the future. Initialized in 3542 // InterfaceDefs.cpp 3543 BControlLook* be_control_look = NULL; 3544 3545 3546 } // namespace BPrivate 3547