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 // Enforce proper use of desktop label colors. 1826 if(low.Brightness() < 100) { 1827 if (textColor == NULL) 1828 color = make_color(255, 255, 255); 1829 glowColor = make_color(0, 0, 0); 1830 } else { 1831 if (textColor == NULL) 1832 color = make_color(0, 0, 0); 1833 glowColor = make_color(255, 255, 255); 1834 } 1835 1836 // drawing occurs on the desktop 1837 if (fCachedWorkspace != current_workspace()) { 1838 int8 indice = 0; 1839 int32 mask; 1840 bool tmpOutline; 1841 while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces", 1842 indice, &mask) == B_OK 1843 && fBackgroundInfo.FindBool("be:bgndimginfoerasetext", 1844 indice, &tmpOutline) == B_OK) { 1845 1846 if (((1 << current_workspace()) & mask) != 0) { 1847 fCachedOutline = tmpOutline; 1848 fCachedWorkspace = current_workspace(); 1849 break; 1850 } 1851 indice++; 1852 } 1853 } 1854 1855 if (fCachedOutline) { 1856 BFont font; 1857 view->GetFont(&font); 1858 1859 view->SetDrawingMode(B_OP_ALPHA); 1860 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 1861 // Draw glow or outline 1862 if (glowColor.Brightness() > 128) { 1863 font.SetFalseBoldWidth(2.0); 1864 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1865 1866 glowColor.alpha = 30; 1867 view->SetHighColor(glowColor); 1868 view->DrawString(label, where); 1869 1870 font.SetFalseBoldWidth(1.0); 1871 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1872 1873 glowColor.alpha = 65; 1874 view->SetHighColor(glowColor); 1875 view->DrawString(label, where); 1876 1877 font.SetFalseBoldWidth(0.0); 1878 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1879 } else { 1880 font.SetFalseBoldWidth(1.0); 1881 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1882 1883 glowColor.alpha = 30; 1884 view->SetHighColor(glowColor); 1885 view->DrawString(label, where); 1886 1887 font.SetFalseBoldWidth(0.0); 1888 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH); 1889 1890 glowColor.alpha = 200; 1891 view->SetHighColor(glowColor); 1892 view->DrawString(label, BPoint(where.x + 1, where.y + 1)); 1893 } 1894 } 1895 } 1896 1897 view->SetHighColor(color); 1898 view->SetDrawingMode(B_OP_OVER); 1899 view->DrawString(label, where); 1900 view->SetDrawingMode(oldMode); 1901 } 1902 1903 1904 void 1905 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon, 1906 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags, 1907 const rgb_color* textColor) 1908 { 1909 DrawLabel(view, label, icon, rect, updateRect, base, flags, 1910 DefaultLabelAlignment(), textColor); 1911 } 1912 1913 1914 void 1915 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon, 1916 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags, 1917 const BAlignment& alignment, const rgb_color* textColor) 1918 { 1919 if (!rect.Intersects(updateRect)) 1920 return; 1921 1922 if (label == NULL && icon == NULL) 1923 return; 1924 1925 if (label == NULL) { 1926 // icon only 1927 BRect alignedRect = BLayoutUtils::AlignInFrame(rect, 1928 icon->Bounds().Size(), alignment); 1929 drawing_mode oldMode = view->DrawingMode(); 1930 view->SetDrawingMode(B_OP_OVER); 1931 view->DrawBitmap(icon, alignedRect.LeftTop()); 1932 view->SetDrawingMode(oldMode); 1933 return; 1934 } 1935 1936 // label, possibly with icon 1937 float availableWidth = rect.Width() + 1; 1938 float width = 0; 1939 float textOffset = 0; 1940 float height = 0; 1941 1942 if (icon != NULL) { 1943 width = icon->Bounds().Width() + DefaultLabelSpacing() + 1; 1944 height = icon->Bounds().Height() + 1; 1945 textOffset = width; 1946 availableWidth -= textOffset; 1947 } 1948 1949 // truncate the label if necessary and get the width and height 1950 BString truncatedLabel(label); 1951 1952 BFont font; 1953 view->GetFont(&font); 1954 1955 font.TruncateString(&truncatedLabel, B_TRUNCATE_END, availableWidth); 1956 width += ceilf(font.StringWidth(truncatedLabel.String())); 1957 1958 font_height fontHeight; 1959 font.GetHeight(&fontHeight); 1960 float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); 1961 height = std::max(height, textHeight); 1962 1963 // handle alignment 1964 BRect alignedRect(BLayoutUtils::AlignOnRect(rect, 1965 BSize(width - 1, height - 1), alignment)); 1966 1967 if (icon != NULL) { 1968 BPoint location(alignedRect.LeftTop()); 1969 if (icon->Bounds().Height() + 1 < height) 1970 location.y += ceilf((height - icon->Bounds().Height() - 1) / 2); 1971 1972 drawing_mode oldMode = view->DrawingMode(); 1973 view->SetDrawingMode(B_OP_OVER); 1974 view->DrawBitmap(icon, location); 1975 view->SetDrawingMode(oldMode); 1976 } 1977 1978 BPoint location(alignedRect.left + textOffset, 1979 alignedRect.top + ceilf(fontHeight.ascent)); 1980 if (textHeight < height) 1981 location.y += ceilf((height - textHeight) / 2); 1982 1983 DrawLabel(view, truncatedLabel.String(), base, flags, location, textColor); 1984 } 1985 1986 1987 void 1988 BControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left, 1989 float& _top, float& _right, float& _bottom) 1990 { 1991 // All frames have the same inset on each side. 1992 float inset = 0; 1993 1994 switch (frameType) { 1995 case B_BUTTON_FRAME: 1996 inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2; 1997 break; 1998 case B_GROUP_FRAME: 1999 case B_MENU_FIELD_FRAME: 2000 inset = 3; 2001 break; 2002 case B_SCROLL_VIEW_FRAME: 2003 case B_TEXT_CONTROL_FRAME: 2004 inset = 2; 2005 break; 2006 } 2007 2008 _left = inset; 2009 _top = inset; 2010 _right = inset; 2011 _bottom = inset; 2012 } 2013 2014 2015 void 2016 BControlLook::GetBackgroundInsets(background_type backgroundType, 2017 uint32 flags, float& _left, float& _top, float& _right, float& _bottom) 2018 { 2019 // Most backgrounds have the same inset on each side. 2020 float inset = 0; 2021 2022 switch (backgroundType) { 2023 case B_BUTTON_BACKGROUND: 2024 case B_MENU_BACKGROUND: 2025 case B_MENU_BAR_BACKGROUND: 2026 case B_MENU_FIELD_BACKGROUND: 2027 case B_MENU_ITEM_BACKGROUND: 2028 inset = 1; 2029 break; 2030 case B_BUTTON_WITH_POP_UP_BACKGROUND: 2031 _left = 1; 2032 _top = 1; 2033 _right = 1 + kButtonPopUpIndicatorWidth; 2034 _bottom = 1; 2035 return; 2036 case B_HORIZONTAL_SCROLL_BAR_BACKGROUND: 2037 _left = 2; 2038 _top = 0; 2039 _right = 1; 2040 _bottom = 0; 2041 return; 2042 case B_VERTICAL_SCROLL_BAR_BACKGROUND: 2043 _left = 0; 2044 _top = 2; 2045 _right = 0; 2046 _bottom = 1; 2047 return; 2048 } 2049 2050 _left = inset; 2051 _top = inset; 2052 _right = inset; 2053 _bottom = inset; 2054 } 2055 2056 2057 void 2058 BControlLook::GetInsets(frame_type frameType, background_type backgroundType, 2059 uint32 flags, float& _left, float& _top, float& _right, float& _bottom) 2060 { 2061 GetFrameInsets(frameType, flags, _left, _top, _right, _bottom); 2062 2063 float left, top, right, bottom; 2064 GetBackgroundInsets(backgroundType, flags, left, top, right, bottom); 2065 2066 _left += left; 2067 _top += top; 2068 _right += right; 2069 _bottom += bottom; 2070 } 2071 2072 2073 void 2074 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2075 const BRect& updateRect, const rgb_color& base, uint32 flags, 2076 uint32 borders, orientation orientation) 2077 { 2078 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, 2079 base, true, flags, borders, orientation); 2080 } 2081 2082 2083 void 2084 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2085 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 2086 uint32 borders, orientation orientation) 2087 { 2088 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius, 2089 radius, base, true, flags, borders, orientation); 2090 } 2091 2092 2093 void 2094 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 2095 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2096 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2097 uint32 flags, uint32 borders, orientation orientation) 2098 { 2099 _DrawButtonBackground(view, rect, updateRect, leftTopRadius, 2100 rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags, 2101 borders, orientation); 2102 } 2103 2104 2105 void 2106 BControlLook::SetBackgroundInfo(const BMessage& backgroundInfo) 2107 { 2108 fBackgroundInfo = backgroundInfo; 2109 fCachedWorkspace = -1; 2110 } 2111 2112 2113 // #pragma mark - 2114 2115 2116 void 2117 BControlLook::_DrawButtonFrame(BView* view, BRect& rect, 2118 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2119 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2120 const rgb_color& background, float contrast, float brightness, 2121 uint32 flags, uint32 borders) 2122 { 2123 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2124 return; 2125 2126 // save the clipping constraints of the view 2127 view->PushState(); 2128 2129 // set clipping constraints to updateRect 2130 BRegion clipping(updateRect); 2131 view->ConstrainClippingRegion(&clipping); 2132 2133 // If the button is flat and neither activated nor otherwise highlighted 2134 // (mouse hovering or focussed), draw it flat. 2135 if ((flags & B_FLAT) != 0 2136 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 2137 && ((flags & (B_HOVER | B_FOCUSED)) == 0 2138 || (flags & B_DISABLED) != 0)) { 2139 _DrawFrame(view, rect, background, background, background, 2140 background, borders); 2141 _DrawFrame(view, rect, background, background, background, 2142 background, borders); 2143 view->PopState(); 2144 return; 2145 } 2146 2147 // outer edge colors 2148 rgb_color edgeLightColor; 2149 rgb_color edgeShadowColor; 2150 2151 // default button frame color 2152 rgb_color defaultIndicatorColor = ui_color(B_CONTROL_BORDER_COLOR); 2153 rgb_color cornerBgColor; 2154 2155 if ((flags & B_DISABLED) != 0) { 2156 defaultIndicatorColor = disable_color(defaultIndicatorColor, 2157 background); 2158 } 2159 2160 drawing_mode oldMode = view->DrawingMode(); 2161 2162 if ((flags & B_DEFAULT_BUTTON) != 0) { 2163 cornerBgColor = defaultIndicatorColor; 2164 edgeLightColor = _EdgeLightColor(defaultIndicatorColor, 2165 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), 2166 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags); 2167 edgeShadowColor = _EdgeShadowColor(defaultIndicatorColor, 2168 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), 2169 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags); 2170 2171 // draw default button indicator 2172 // Allow a 1-pixel border of the background to come through. 2173 rect.InsetBy(1, 1); 2174 2175 view->SetHighColor(defaultIndicatorColor); 2176 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 2177 rect.InsetBy(1, 1); 2178 2179 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 2180 rect.InsetBy(1, 1); 2181 } else { 2182 cornerBgColor = background; 2183 if ((flags & B_BLEND_FRAME) != 0) { 2184 // set the background color to transparent for the case 2185 // that we are on the desktop 2186 cornerBgColor.alpha = 0; 2187 view->SetDrawingMode(B_OP_ALPHA); 2188 } 2189 2190 edgeLightColor = _EdgeLightColor(background, 2191 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0), 2192 brightness * 1.0, flags); 2193 edgeShadowColor = _EdgeShadowColor(background, 2194 contrast * (flags & B_DISABLED) != 0 ? 0.0 : 1.0, 2195 brightness * 1.0, flags); 2196 } 2197 2198 // frame colors 2199 rgb_color frameLightColor = _FrameLightColor(base, flags); 2200 rgb_color frameShadowColor = _FrameShadowColor(base, flags); 2201 2202 // rounded corners 2203 2204 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 2205 && leftTopRadius > 0) { 2206 // draw left top rounded corner 2207 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 2208 floorf(rect.left + leftTopRadius), 2209 floorf(rect.top + leftTopRadius)); 2210 clipping.Exclude(leftTopCorner); 2211 _DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect, 2212 cornerBgColor, edgeShadowColor, frameLightColor); 2213 } 2214 2215 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 2216 && rightTopRadius > 0) { 2217 // draw right top rounded corner 2218 BRect rightTopCorner(floorf(rect.right - rightTopRadius), 2219 floorf(rect.top), floorf(rect.right), 2220 floorf(rect.top + rightTopRadius)); 2221 clipping.Exclude(rightTopCorner); 2222 _DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect, 2223 cornerBgColor, edgeShadowColor, edgeLightColor, 2224 frameLightColor, frameShadowColor); 2225 } 2226 2227 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2228 && leftBottomRadius > 0) { 2229 // draw left bottom rounded corner 2230 BRect leftBottomCorner(floorf(rect.left), 2231 floorf(rect.bottom - leftBottomRadius), 2232 floorf(rect.left + leftBottomRadius), floorf(rect.bottom)); 2233 clipping.Exclude(leftBottomCorner); 2234 _DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect, 2235 cornerBgColor, edgeShadowColor, edgeLightColor, 2236 frameLightColor, frameShadowColor); 2237 } 2238 2239 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2240 && rightBottomRadius > 0) { 2241 // draw right bottom rounded corner 2242 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius), 2243 floorf(rect.bottom - rightBottomRadius), floorf(rect.right), 2244 floorf(rect.bottom)); 2245 clipping.Exclude(rightBottomCorner); 2246 _DrawRoundCornerFrameRightBottom(view, rightBottomCorner, 2247 updateRect, cornerBgColor, edgeLightColor, frameShadowColor); 2248 } 2249 2250 // clip out the corners 2251 view->ConstrainClippingRegion(&clipping); 2252 2253 // draw outer edge 2254 if ((flags & B_DEFAULT_BUTTON) != 0) { 2255 _DrawOuterResessedFrame(view, rect, defaultIndicatorColor, 2256 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), 2257 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), 2258 flags, borders); 2259 } else { 2260 _DrawOuterResessedFrame(view, rect, background, 2261 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0), 2262 brightness * 1.0, flags, borders); 2263 } 2264 2265 view->SetDrawingMode(oldMode); 2266 2267 // draw frame 2268 if ((flags & B_BLEND_FRAME) != 0) { 2269 drawing_mode oldDrawingMode = view->DrawingMode(); 2270 view->SetDrawingMode(B_OP_ALPHA); 2271 2272 _DrawFrame(view, rect, frameLightColor, frameLightColor, 2273 frameShadowColor, frameShadowColor, borders); 2274 2275 view->SetDrawingMode(oldDrawingMode); 2276 } else { 2277 _DrawFrame(view, rect, frameLightColor, frameLightColor, 2278 frameShadowColor, frameShadowColor, borders); 2279 } 2280 2281 // restore the clipping constraints of the view 2282 view->PopState(); 2283 } 2284 2285 2286 void 2287 BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect, 2288 const rgb_color& base, float contrast, float brightness, uint32 flags, 2289 uint32 borders) 2290 { 2291 rgb_color edgeLightColor = _EdgeLightColor(base, contrast, 2292 brightness, flags); 2293 rgb_color edgeShadowColor = _EdgeShadowColor(base, contrast, 2294 brightness, flags); 2295 2296 if ((flags & B_BLEND_FRAME) != 0) { 2297 // assumes the background has already been painted 2298 drawing_mode oldDrawingMode = view->DrawingMode(); 2299 view->SetDrawingMode(B_OP_ALPHA); 2300 2301 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, 2302 edgeLightColor, edgeLightColor, borders); 2303 2304 view->SetDrawingMode(oldDrawingMode); 2305 } else { 2306 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, 2307 edgeLightColor, edgeLightColor, borders); 2308 } 2309 } 2310 2311 2312 void 2313 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, 2314 const rgb_color& top, const rgb_color& right, const rgb_color& bottom, 2315 uint32 borders) 2316 { 2317 view->BeginLineArray(4); 2318 2319 if (borders & B_LEFT_BORDER) { 2320 view->AddLine( 2321 BPoint(rect.left, rect.bottom), 2322 BPoint(rect.left, rect.top), left); 2323 rect.left++; 2324 } 2325 if (borders & B_TOP_BORDER) { 2326 view->AddLine( 2327 BPoint(rect.left, rect.top), 2328 BPoint(rect.right, rect.top), top); 2329 rect.top++; 2330 } 2331 if (borders & B_RIGHT_BORDER) { 2332 view->AddLine( 2333 BPoint(rect.right, rect.top), 2334 BPoint(rect.right, rect.bottom), right); 2335 rect.right--; 2336 } 2337 if (borders & B_BOTTOM_BORDER) { 2338 view->AddLine( 2339 BPoint(rect.left, rect.bottom), 2340 BPoint(rect.right, rect.bottom), bottom); 2341 rect.bottom--; 2342 } 2343 2344 view->EndLineArray(); 2345 } 2346 2347 2348 void 2349 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left, 2350 const rgb_color& top, const rgb_color& right, const rgb_color& bottom, 2351 const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders) 2352 { 2353 view->BeginLineArray(6); 2354 2355 if (borders & B_TOP_BORDER) { 2356 if (borders & B_RIGHT_BORDER) { 2357 view->AddLine( 2358 BPoint(rect.left, rect.top), 2359 BPoint(rect.right - 1, rect.top), top); 2360 view->AddLine( 2361 BPoint(rect.right, rect.top), 2362 BPoint(rect.right, rect.top), rightTop); 2363 } else { 2364 view->AddLine( 2365 BPoint(rect.left, rect.top), 2366 BPoint(rect.right, rect.top), top); 2367 } 2368 rect.top++; 2369 } 2370 2371 if (borders & B_LEFT_BORDER) { 2372 view->AddLine( 2373 BPoint(rect.left, rect.top), 2374 BPoint(rect.left, rect.bottom - 1), left); 2375 view->AddLine( 2376 BPoint(rect.left, rect.bottom), 2377 BPoint(rect.left, rect.bottom), leftBottom); 2378 rect.left++; 2379 } 2380 2381 if (borders & B_BOTTOM_BORDER) { 2382 view->AddLine( 2383 BPoint(rect.left, rect.bottom), 2384 BPoint(rect.right, rect.bottom), bottom); 2385 rect.bottom--; 2386 } 2387 2388 if (borders & B_RIGHT_BORDER) { 2389 view->AddLine( 2390 BPoint(rect.right, rect.bottom), 2391 BPoint(rect.right, rect.top), right); 2392 rect.right--; 2393 } 2394 2395 view->EndLineArray(); 2396 } 2397 2398 2399 void 2400 BControlLook::_DrawButtonBackground(BView* view, BRect& rect, 2401 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2402 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2403 bool popupIndicator, uint32 flags, uint32 borders, orientation orientation) 2404 { 2405 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2406 return; 2407 2408 // save the clipping constraints of the view 2409 view->PushState(); 2410 2411 // set clipping constraints to updateRect 2412 BRegion clipping(updateRect); 2413 view->ConstrainClippingRegion(&clipping); 2414 2415 // If the button is flat and neither activated nor otherwise highlighted 2416 // (mouse hovering or focussed), draw it flat. 2417 if ((flags & B_FLAT) != 0 2418 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 2419 && ((flags & (B_HOVER | B_FOCUSED)) == 0 2420 || (flags & B_DISABLED) != 0)) { 2421 _DrawFlatButtonBackground(view, rect, updateRect, base, popupIndicator, 2422 flags, borders, orientation); 2423 } else { 2424 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, 2425 leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius, 2426 base, popupIndicator, flags, borders, orientation); 2427 } 2428 2429 // restore the clipping constraints of the view 2430 view->PopState(); 2431 } 2432 2433 2434 void 2435 BControlLook::_DrawFlatButtonBackground(BView* view, BRect& rect, 2436 const BRect& updateRect, const rgb_color& base, bool popupIndicator, 2437 uint32 flags, uint32 borders, orientation orientation) 2438 { 2439 _DrawFrame(view, rect, base, base, base, base, borders); 2440 // Not an actual frame, but the method insets our rect as needed. 2441 2442 view->SetHighColor(base); 2443 view->FillRect(rect); 2444 2445 if (popupIndicator) { 2446 BRect indicatorRect(rect); 2447 rect.right -= kButtonPopUpIndicatorWidth; 2448 indicatorRect.left = rect.right + 3; 2449 // 2 pixels for the separator 2450 2451 view->SetHighColor(base); 2452 view->FillRect(indicatorRect); 2453 2454 _DrawPopUpMarker(view, indicatorRect, base, flags); 2455 } 2456 } 2457 2458 2459 void 2460 BControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect, 2461 const BRect& updateRect, BRegion& clipping, float leftTopRadius, 2462 float rightTopRadius, float leftBottomRadius, float rightBottomRadius, 2463 const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders, 2464 orientation orientation) 2465 { 2466 // inner bevel colors 2467 rgb_color bevelLightColor = _BevelLightColor(base, flags); 2468 rgb_color bevelShadowColor = _BevelShadowColor(base, flags); 2469 2470 // button background color 2471 rgb_color buttonBgColor; 2472 if ((flags & B_DISABLED) != 0) 2473 buttonBgColor = tint_color(base, 0.7); 2474 else 2475 buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT); 2476 2477 // surface top gradient 2478 BGradientLinear fillGradient; 2479 _MakeButtonGradient(fillGradient, rect, base, flags, orientation); 2480 2481 // rounded corners 2482 2483 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 2484 && leftTopRadius > 0) { 2485 // draw left top rounded corner 2486 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 2487 floorf(rect.left + leftTopRadius - 2.0), 2488 floorf(rect.top + leftTopRadius - 2.0)); 2489 clipping.Exclude(leftTopCorner); 2490 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, 2491 bevelLightColor, fillGradient); 2492 } 2493 2494 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 2495 && rightTopRadius > 0) { 2496 // draw right top rounded corner 2497 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), 2498 floorf(rect.top), floorf(rect.right), 2499 floorf(rect.top + rightTopRadius - 2.0)); 2500 clipping.Exclude(rightTopCorner); 2501 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, 2502 updateRect, bevelLightColor, bevelShadowColor, fillGradient); 2503 } 2504 2505 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2506 && leftBottomRadius > 0) { 2507 // draw left bottom rounded corner 2508 BRect leftBottomCorner(floorf(rect.left), 2509 floorf(rect.bottom - leftBottomRadius + 2.0), 2510 floorf(rect.left + leftBottomRadius - 2.0), 2511 floorf(rect.bottom)); 2512 clipping.Exclude(leftBottomCorner); 2513 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, 2514 updateRect, bevelLightColor, bevelShadowColor, fillGradient); 2515 } 2516 2517 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2518 && rightBottomRadius > 0) { 2519 // draw right bottom rounded corner 2520 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), 2521 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), 2522 floorf(rect.bottom)); 2523 clipping.Exclude(rightBottomCorner); 2524 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, 2525 updateRect, bevelShadowColor, fillGradient); 2526 } 2527 2528 // clip out the corners 2529 view->ConstrainClippingRegion(&clipping); 2530 2531 // draw inner bevel 2532 2533 if ((flags & B_ACTIVATED) != 0) { 2534 view->BeginLineArray(4); 2535 2536 // shadow along left/top borders 2537 if (borders & B_LEFT_BORDER) { 2538 view->AddLine(BPoint(rect.left, rect.top), 2539 BPoint(rect.left, rect.bottom), bevelLightColor); 2540 rect.left++; 2541 } 2542 if (borders & B_TOP_BORDER) { 2543 view->AddLine(BPoint(rect.left, rect.top), 2544 BPoint(rect.right, rect.top), bevelLightColor); 2545 rect.top++; 2546 } 2547 2548 // softer shadow along left/top borders 2549 if (borders & B_LEFT_BORDER) { 2550 view->AddLine(BPoint(rect.left, rect.top), 2551 BPoint(rect.left, rect.bottom), bevelShadowColor); 2552 rect.left++; 2553 } 2554 if (borders & B_TOP_BORDER) { 2555 view->AddLine(BPoint(rect.left, rect.top), 2556 BPoint(rect.right, rect.top), bevelShadowColor); 2557 rect.top++; 2558 } 2559 2560 view->EndLineArray(); 2561 } else { 2562 _DrawFrame(view, rect, 2563 bevelLightColor, bevelLightColor, 2564 bevelShadowColor, bevelShadowColor, 2565 buttonBgColor, buttonBgColor, borders); 2566 } 2567 2568 if (popupIndicator) { 2569 BRect indicatorRect(rect); 2570 rect.right -= kButtonPopUpIndicatorWidth; 2571 indicatorRect.left = rect.right + 3; 2572 // 2 pixels for the separator 2573 2574 // Even when depressed we want the pop-up indicator background and 2575 // separator to cover the area up to the top. 2576 if ((flags & B_ACTIVATED) != 0) 2577 indicatorRect.top--; 2578 2579 // draw the separator 2580 rgb_color separatorBaseColor = base; 2581 if ((flags & B_ACTIVATED) != 0) 2582 separatorBaseColor = tint_color(base, B_DARKEN_1_TINT); 2583 2584 rgb_color separatorLightColor = _EdgeLightColor(separatorBaseColor, 2585 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags); 2586 rgb_color separatorShadowColor = _EdgeShadowColor(separatorBaseColor, 2587 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags); 2588 2589 view->BeginLineArray(2); 2590 2591 view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top), 2592 BPoint(indicatorRect.left - 2, indicatorRect.bottom), 2593 separatorShadowColor); 2594 view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top), 2595 BPoint(indicatorRect.left - 1, indicatorRect.bottom), 2596 separatorLightColor); 2597 2598 view->EndLineArray(); 2599 2600 // draw background and pop-up marker 2601 _DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect, 2602 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 0); 2603 2604 if ((flags & B_ACTIVATED) != 0) 2605 indicatorRect.top++; 2606 2607 _DrawPopUpMarker(view, indicatorRect, base, flags); 2608 } 2609 2610 // fill in the background 2611 view->FillRect(rect, fillGradient); 2612 } 2613 2614 2615 void 2616 BControlLook::_DrawPopUpMarker(BView* view, const BRect& rect, 2617 const rgb_color& base, uint32 flags) 2618 { 2619 BPoint center(roundf((rect.left + rect.right) / 2.0), 2620 roundf((rect.top + rect.bottom) / 2.0)); 2621 BPoint triangle[3]; 2622 triangle[0] = center + BPoint(-2.5, -0.5); 2623 triangle[1] = center + BPoint(2.5, -0.5); 2624 triangle[2] = center + BPoint(0.0, 2.0); 2625 2626 uint32 viewFlags = view->Flags(); 2627 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); 2628 2629 rgb_color markColor; 2630 if ((flags & B_DISABLED) != 0) 2631 markColor = tint_color(base, 1.35); 2632 else 2633 markColor = tint_color(base, 1.65); 2634 2635 view->SetHighColor(markColor); 2636 view->FillTriangle(triangle[0], triangle[1], triangle[2]); 2637 2638 view->SetFlags(viewFlags); 2639 } 2640 2641 2642 void 2643 BControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect, 2644 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2645 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2646 bool popupIndicator, uint32 flags) 2647 { 2648 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2649 return; 2650 2651 if (popupIndicator) { 2652 BRect leftRect(rect); 2653 leftRect.right -= 10; 2654 2655 BRect rightRect(rect); 2656 rightRect.left = rightRect.right - 9; 2657 2658 _DrawMenuFieldBackgroundInside(view, leftRect, updateRect, 2659 leftTopRadius, 0.0f, leftBottomRadius, 0.0f, base, flags, 2660 B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER); 2661 2662 _DrawMenuFieldBackgroundInside(view, rightRect, updateRect, 2663 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 2664 B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER); 2665 2666 _DrawPopUpMarker(view, rightRect, base, flags); 2667 2668 // draw a line on the left of the popup frame 2669 rgb_color bevelShadowColor = _BevelShadowColor(base, flags); 2670 view->SetHighColor(bevelShadowColor); 2671 BPoint leftTopCorner(floorf(rightRect.left - 1.0), 2672 floorf(rightRect.top - 1.0)); 2673 BPoint leftBottomCorner(floorf(rightRect.left - 1.0), 2674 floorf(rightRect.bottom + 1.0)); 2675 view->StrokeLine(leftTopCorner, leftBottomCorner); 2676 2677 rect = leftRect; 2678 } else { 2679 _DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius, 2680 rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags); 2681 } 2682 } 2683 2684 2685 void 2686 BControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect, 2687 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 2688 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 2689 uint32 flags, uint32 borders) 2690 { 2691 if (!rect.IsValid() || !rect.Intersects(updateRect)) 2692 return; 2693 2694 // save the clipping constraints of the view 2695 view->PushState(); 2696 2697 // set clipping constraints to updateRect 2698 BRegion clipping(updateRect); 2699 view->ConstrainClippingRegion(&clipping); 2700 2701 // frame colors 2702 rgb_color frameLightColor = _FrameLightColor(base, flags); 2703 rgb_color frameShadowColor = _FrameShadowColor(base, flags); 2704 2705 // indicator background color 2706 rgb_color indicatorBase; 2707 if ((borders & B_LEFT_BORDER) != 0) 2708 indicatorBase = base; 2709 else { 2710 if ((flags & B_DISABLED) != 0) 2711 indicatorBase = tint_color(base, 1.05); 2712 else 2713 indicatorBase = tint_color(base, 1.12); 2714 } 2715 2716 // bevel colors 2717 rgb_color cornerColor = tint_color(indicatorBase, 0.85); 2718 rgb_color bevelColor1 = tint_color(indicatorBase, 0.3); 2719 rgb_color bevelColor2 = tint_color(indicatorBase, 0.5); 2720 rgb_color bevelColor3 = tint_color(indicatorBase, 1.03); 2721 2722 if ((flags & B_DISABLED) != 0) { 2723 cornerColor = tint_color(indicatorBase, 0.8); 2724 bevelColor1 = tint_color(indicatorBase, 0.7); 2725 bevelColor2 = tint_color(indicatorBase, 0.8); 2726 bevelColor3 = tint_color(indicatorBase, 1.01); 2727 } else { 2728 cornerColor = tint_color(indicatorBase, 0.85); 2729 bevelColor1 = tint_color(indicatorBase, 0.3); 2730 bevelColor2 = tint_color(indicatorBase, 0.5); 2731 bevelColor3 = tint_color(indicatorBase, 1.03); 2732 } 2733 2734 // surface top gradient 2735 BGradientLinear fillGradient; 2736 _MakeButtonGradient(fillGradient, rect, indicatorBase, flags); 2737 2738 // rounded corners 2739 2740 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 2741 && leftTopRadius > 0) { 2742 // draw left top rounded corner 2743 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 2744 floorf(rect.left + leftTopRadius - 2.0), 2745 floorf(rect.top + leftTopRadius - 2.0)); 2746 clipping.Exclude(leftTopCorner); 2747 2748 BRegion cornerClipping(leftTopCorner); 2749 view->ConstrainClippingRegion(&cornerClipping); 2750 2751 BRect ellipseRect(leftTopCorner); 2752 ellipseRect.InsetBy(-1.0, -1.0); 2753 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2754 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2755 2756 // draw the frame (again) 2757 view->SetHighColor(frameLightColor); 2758 view->FillEllipse(ellipseRect); 2759 2760 // draw the bevel and background 2761 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, 2762 bevelColor1, fillGradient); 2763 } 2764 2765 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 2766 && rightTopRadius > 0) { 2767 // draw right top rounded corner 2768 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), 2769 floorf(rect.top), floorf(rect.right), 2770 floorf(rect.top + rightTopRadius - 2.0)); 2771 clipping.Exclude(rightTopCorner); 2772 2773 BRegion cornerClipping(rightTopCorner); 2774 view->ConstrainClippingRegion(&cornerClipping); 2775 2776 BRect ellipseRect(rightTopCorner); 2777 ellipseRect.InsetBy(-1.0, -1.0); 2778 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2779 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2780 2781 // draw the frame (again) 2782 if (frameLightColor == frameShadowColor) { 2783 view->SetHighColor(frameLightColor); 2784 view->FillEllipse(ellipseRect); 2785 } else { 2786 BGradientLinear gradient; 2787 gradient.AddColor(frameLightColor, 0); 2788 gradient.AddColor(frameShadowColor, 255); 2789 gradient.SetStart(rightTopCorner.LeftTop()); 2790 gradient.SetEnd(rightTopCorner.RightBottom()); 2791 view->FillEllipse(ellipseRect, gradient); 2792 } 2793 2794 // draw the bevel and background 2795 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect, 2796 bevelColor1, bevelColor3, fillGradient); 2797 } 2798 2799 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2800 && leftBottomRadius > 0) { 2801 // draw left bottom rounded corner 2802 BRect leftBottomCorner(floorf(rect.left), 2803 floorf(rect.bottom - leftBottomRadius + 2.0), 2804 floorf(rect.left + leftBottomRadius - 2.0), 2805 floorf(rect.bottom)); 2806 clipping.Exclude(leftBottomCorner); 2807 2808 BRegion cornerClipping(leftBottomCorner); 2809 view->ConstrainClippingRegion(&cornerClipping); 2810 2811 BRect ellipseRect(leftBottomCorner); 2812 ellipseRect.InsetBy(-1.0, -1.0); 2813 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2814 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 2815 2816 // draw the frame (again) 2817 if (frameLightColor == frameShadowColor) { 2818 view->SetHighColor(frameLightColor); 2819 view->FillEllipse(ellipseRect); 2820 } else { 2821 BGradientLinear gradient; 2822 gradient.AddColor(frameLightColor, 0); 2823 gradient.AddColor(frameShadowColor, 255); 2824 gradient.SetStart(leftBottomCorner.LeftTop()); 2825 gradient.SetEnd(leftBottomCorner.RightBottom()); 2826 view->FillEllipse(ellipseRect, gradient); 2827 } 2828 2829 // draw the bevel and background 2830 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, 2831 updateRect, bevelColor2, bevelColor3, fillGradient); 2832 } 2833 2834 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2835 && rightBottomRadius > 0) { 2836 // draw right bottom rounded corner 2837 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), 2838 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), 2839 floorf(rect.bottom)); 2840 clipping.Exclude(rightBottomCorner); 2841 2842 BRegion cornerClipping(rightBottomCorner); 2843 view->ConstrainClippingRegion(&cornerClipping); 2844 2845 BRect ellipseRect(rightBottomCorner); 2846 ellipseRect.InsetBy(-1.0, -1.0); 2847 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2848 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 2849 2850 // draw the frame (again) 2851 view->SetHighColor(frameShadowColor); 2852 view->FillEllipse(ellipseRect); 2853 2854 // draw the bevel and background 2855 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, 2856 updateRect, bevelColor3, fillGradient); 2857 } 2858 2859 // clip out the corners 2860 view->ConstrainClippingRegion(&clipping); 2861 2862 // draw the bevel 2863 _DrawFrame(view, rect, 2864 bevelColor2, bevelColor1, 2865 bevelColor3, bevelColor3, 2866 cornerColor, cornerColor, 2867 borders); 2868 2869 // fill in the background 2870 view->FillRect(rect, fillGradient); 2871 2872 // restore the clipping constraints of the view 2873 view->PopState(); 2874 } 2875 2876 2877 void 2878 BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& cornerRect, 2879 const BRect& updateRect, const rgb_color& background, 2880 const rgb_color& edgeColor, const rgb_color& frameColor, 2881 const rgb_color& bevelColor, const BGradientLinear& fillGradient) 2882 { 2883 _DrawRoundCornerFrameLeftTop(view, cornerRect, updateRect, 2884 background, edgeColor, frameColor); 2885 _DrawRoundCornerBackgroundLeftTop(view, cornerRect, updateRect, 2886 bevelColor, fillGradient); 2887 } 2888 2889 2890 void 2891 BControlLook::_DrawRoundCornerFrameLeftTop(BView* view, BRect& cornerRect, 2892 const BRect& updateRect, const rgb_color& background, 2893 const rgb_color& edgeColor, const rgb_color& frameColor) 2894 { 2895 // constrain clipping region to corner 2896 BRegion clipping(cornerRect); 2897 view->ConstrainClippingRegion(&clipping); 2898 2899 // background 2900 view->SetHighColor(background); 2901 view->FillRect(cornerRect); 2902 2903 // outer edge 2904 BRect ellipseRect(cornerRect); 2905 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2906 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2907 2908 view->SetHighColor(edgeColor); 2909 view->FillEllipse(ellipseRect); 2910 2911 // frame 2912 ellipseRect.InsetBy(1, 1); 2913 cornerRect.left++; 2914 cornerRect.top++; 2915 view->SetHighColor(frameColor); 2916 view->FillEllipse(ellipseRect); 2917 2918 // prepare for bevel 2919 cornerRect.left++; 2920 cornerRect.top++; 2921 } 2922 2923 2924 void 2925 BControlLook::_DrawRoundCornerBackgroundLeftTop(BView* view, BRect& cornerRect, 2926 const BRect& updateRect, const rgb_color& bevelColor, 2927 const BGradientLinear& fillGradient) 2928 { 2929 // constrain clipping region to corner 2930 BRegion clipping(cornerRect); 2931 view->ConstrainClippingRegion(&clipping); 2932 2933 BRect ellipseRect(cornerRect); 2934 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2935 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2936 2937 // bevel 2938 view->SetHighColor(bevelColor); 2939 view->FillEllipse(ellipseRect); 2940 2941 // gradient 2942 ellipseRect.InsetBy(1, 1); 2943 view->FillEllipse(ellipseRect, fillGradient); 2944 } 2945 2946 2947 void 2948 BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& cornerRect, 2949 const BRect& updateRect, const rgb_color& background, 2950 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor, 2951 const rgb_color& frameTopColor, const rgb_color& frameRightColor, 2952 const rgb_color& bevelTopColor, const rgb_color& bevelRightColor, 2953 const BGradientLinear& fillGradient) 2954 { 2955 _DrawRoundCornerFrameRightTop(view, cornerRect, updateRect, 2956 background, edgeTopColor, edgeRightColor, frameTopColor, 2957 frameRightColor); 2958 _DrawRoundCornerBackgroundRightTop(view, cornerRect, updateRect, 2959 bevelTopColor, bevelRightColor, fillGradient); 2960 } 2961 2962 2963 void 2964 BControlLook::_DrawRoundCornerFrameRightTop(BView* view, BRect& cornerRect, 2965 const BRect& updateRect, const rgb_color& background, 2966 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor, 2967 const rgb_color& frameTopColor, const rgb_color& frameRightColor) 2968 { 2969 // constrain clipping region to corner 2970 BRegion clipping(cornerRect); 2971 view->ConstrainClippingRegion(&clipping); 2972 2973 // background 2974 view->SetHighColor(background); 2975 view->FillRect(cornerRect); 2976 2977 // outer edge 2978 BRect ellipseRect(cornerRect); 2979 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2980 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 2981 2982 BGradientLinear gradient; 2983 gradient.AddColor(edgeTopColor, 0); 2984 gradient.AddColor(edgeRightColor, 255); 2985 gradient.SetStart(cornerRect.LeftTop()); 2986 gradient.SetEnd(cornerRect.RightBottom()); 2987 view->FillEllipse(ellipseRect, gradient); 2988 2989 // frame 2990 ellipseRect.InsetBy(1, 1); 2991 cornerRect.right--; 2992 cornerRect.top++; 2993 if (frameTopColor == frameRightColor) { 2994 view->SetHighColor(frameTopColor); 2995 view->FillEllipse(ellipseRect); 2996 } else { 2997 gradient.SetColor(0, frameTopColor); 2998 gradient.SetColor(1, frameRightColor); 2999 gradient.SetStart(cornerRect.LeftTop()); 3000 gradient.SetEnd(cornerRect.RightBottom()); 3001 view->FillEllipse(ellipseRect, gradient); 3002 } 3003 3004 // prepare for bevel 3005 cornerRect.right--; 3006 cornerRect.top++; 3007 } 3008 3009 3010 void 3011 BControlLook::_DrawRoundCornerBackgroundRightTop(BView* view, BRect& cornerRect, 3012 const BRect& updateRect, const rgb_color& bevelTopColor, 3013 const rgb_color& bevelRightColor, const BGradientLinear& fillGradient) 3014 { 3015 // constrain clipping region to corner 3016 BRegion clipping(cornerRect); 3017 view->ConstrainClippingRegion(&clipping); 3018 3019 BRect ellipseRect(cornerRect); 3020 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 3021 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 3022 3023 // bevel 3024 BGradientLinear gradient; 3025 gradient.AddColor(bevelTopColor, 0); 3026 gradient.AddColor(bevelRightColor, 255); 3027 gradient.SetStart(cornerRect.LeftTop()); 3028 gradient.SetEnd(cornerRect.RightBottom()); 3029 view->FillEllipse(ellipseRect, gradient); 3030 3031 // gradient 3032 ellipseRect.InsetBy(1, 1); 3033 view->FillEllipse(ellipseRect, fillGradient); 3034 } 3035 3036 3037 void 3038 BControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& cornerRect, 3039 const BRect& updateRect, const rgb_color& background, 3040 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor, 3041 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor, 3042 const rgb_color& bevelLeftColor, const rgb_color& bevelBottomColor, 3043 const BGradientLinear& fillGradient) 3044 { 3045 _DrawRoundCornerFrameLeftBottom(view, cornerRect, updateRect, 3046 background, edgeLeftColor, edgeBottomColor, frameLeftColor, 3047 frameBottomColor); 3048 _DrawRoundCornerBackgroundLeftBottom(view, cornerRect, updateRect, 3049 bevelLeftColor, bevelBottomColor, fillGradient); 3050 } 3051 3052 3053 void 3054 BControlLook::_DrawRoundCornerFrameLeftBottom(BView* view, BRect& cornerRect, 3055 const BRect& updateRect, const rgb_color& background, 3056 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor, 3057 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor) 3058 { 3059 // constrain clipping region to corner 3060 BRegion clipping(cornerRect); 3061 view->ConstrainClippingRegion(&clipping); 3062 3063 // background 3064 view->SetHighColor(background); 3065 view->FillRect(cornerRect); 3066 3067 // outer edge 3068 BRect ellipseRect(cornerRect); 3069 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 3070 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3071 3072 BGradientLinear gradient; 3073 gradient.AddColor(edgeLeftColor, 0); 3074 gradient.AddColor(edgeBottomColor, 255); 3075 gradient.SetStart(cornerRect.LeftTop()); 3076 gradient.SetEnd(cornerRect.RightBottom()); 3077 view->FillEllipse(ellipseRect, gradient); 3078 3079 // frame 3080 ellipseRect.InsetBy(1, 1); 3081 cornerRect.left++; 3082 cornerRect.bottom--; 3083 if (frameLeftColor == frameBottomColor) { 3084 view->SetHighColor(frameLeftColor); 3085 view->FillEllipse(ellipseRect); 3086 } else { 3087 gradient.SetColor(0, frameLeftColor); 3088 gradient.SetColor(1, frameBottomColor); 3089 gradient.SetStart(cornerRect.LeftTop()); 3090 gradient.SetEnd(cornerRect.RightBottom()); 3091 view->FillEllipse(ellipseRect, gradient); 3092 } 3093 3094 // prepare for bevel 3095 cornerRect.left++; 3096 cornerRect.bottom--; 3097 } 3098 3099 3100 void 3101 BControlLook::_DrawRoundCornerBackgroundLeftBottom(BView* view, BRect& cornerRect, 3102 const BRect& updateRect, const rgb_color& bevelLeftColor, 3103 const rgb_color& bevelBottomColor, const BGradientLinear& fillGradient) 3104 { 3105 // constrain clipping region to corner 3106 BRegion clipping(cornerRect); 3107 view->ConstrainClippingRegion(&clipping); 3108 3109 BRect ellipseRect(cornerRect); 3110 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 3111 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3112 3113 // bevel 3114 BGradientLinear gradient; 3115 gradient.AddColor(bevelLeftColor, 0); 3116 gradient.AddColor(bevelBottomColor, 255); 3117 gradient.SetStart(cornerRect.LeftTop()); 3118 gradient.SetEnd(cornerRect.RightBottom()); 3119 view->FillEllipse(ellipseRect, gradient); 3120 3121 // gradient 3122 ellipseRect.InsetBy(1, 1); 3123 view->FillEllipse(ellipseRect, fillGradient); 3124 } 3125 3126 3127 void 3128 BControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& cornerRect, 3129 const BRect& updateRect, const rgb_color& background, 3130 const rgb_color& edgeColor, const rgb_color& frameColor, 3131 const rgb_color& bevelColor, const BGradientLinear& fillGradient) 3132 { 3133 _DrawRoundCornerFrameRightBottom(view, cornerRect, updateRect, 3134 background, edgeColor, frameColor); 3135 _DrawRoundCornerBackgroundRightBottom(view, cornerRect, updateRect, 3136 bevelColor, fillGradient); 3137 } 3138 3139 3140 void 3141 BControlLook::_DrawRoundCornerFrameRightBottom(BView* view, BRect& cornerRect, 3142 const BRect& updateRect, const rgb_color& background, 3143 const rgb_color& edgeColor, const rgb_color& frameColor) 3144 { 3145 // constrain clipping region to corner 3146 BRegion clipping(cornerRect); 3147 view->ConstrainClippingRegion(&clipping); 3148 3149 // background 3150 view->SetHighColor(background); 3151 view->FillRect(cornerRect); 3152 3153 // outer edge 3154 BRect ellipseRect(cornerRect); 3155 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 3156 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3157 3158 view->SetHighColor(edgeColor); 3159 view->FillEllipse(ellipseRect); 3160 3161 // frame 3162 ellipseRect.InsetBy(1, 1); 3163 cornerRect.right--; 3164 cornerRect.bottom++; 3165 view->SetHighColor(frameColor); 3166 view->FillEllipse(ellipseRect); 3167 3168 // prepare for bevel 3169 cornerRect.left++; 3170 cornerRect.bottom--; 3171 } 3172 3173 3174 void 3175 BControlLook::_DrawRoundCornerBackgroundRightBottom(BView* view, 3176 BRect& cornerRect, const BRect& updateRect, const rgb_color& bevelColor, 3177 const BGradientLinear& fillGradient) 3178 { 3179 // constrain clipping region to corner 3180 BRegion clipping(cornerRect); 3181 view->ConstrainClippingRegion(&clipping); 3182 3183 BRect ellipseRect(cornerRect); 3184 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 3185 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 3186 3187 // bevel 3188 view->SetHighColor(bevelColor); 3189 view->FillEllipse(ellipseRect); 3190 3191 // gradient 3192 ellipseRect.InsetBy(1, 1); 3193 view->FillEllipse(ellipseRect, fillGradient); 3194 } 3195 3196 3197 void 3198 BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect, 3199 const BRect& updateRect, 3200 const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor, 3201 const rgb_color& frameLightColor, const rgb_color& frameShadowColor, 3202 const rgb_color& fillLightColor, const rgb_color& fillShadowColor, 3203 float leftInset, float topInset, float rightInset, float bottomInset, 3204 orientation orientation) 3205 { 3206 if (!rect.IsValid() || !rect.Intersects(updateRect)) 3207 return; 3208 3209 BGradientLinear gradient; 3210 gradient.AddColor(edgeShadowColor, 0); 3211 gradient.AddColor(edgeLightColor, 255); 3212 gradient.SetStart(rect.LeftTop()); 3213 if (orientation == B_HORIZONTAL) 3214 gradient.SetEnd(rect.LeftBottom()); 3215 else 3216 gradient.SetEnd(rect.RightTop()); 3217 3218 view->FillEllipse(rect, gradient); 3219 3220 rect.left += leftInset; 3221 rect.top += topInset; 3222 rect.right += rightInset; 3223 rect.bottom += bottomInset; 3224 3225 gradient.MakeEmpty(); 3226 gradient.AddColor(frameShadowColor, 0); 3227 gradient.AddColor(frameLightColor, 255); 3228 gradient.SetStart(rect.LeftTop()); 3229 if (orientation == B_HORIZONTAL) 3230 gradient.SetEnd(rect.LeftBottom()); 3231 else 3232 gradient.SetEnd(rect.RightTop()); 3233 3234 view->FillEllipse(rect, gradient); 3235 3236 rect.left += leftInset; 3237 rect.top += topInset; 3238 rect.right += rightInset; 3239 rect.bottom += bottomInset; 3240 3241 gradient.MakeEmpty(); 3242 gradient.AddColor(fillShadowColor, 0); 3243 gradient.AddColor(fillLightColor, 255); 3244 gradient.SetStart(rect.LeftTop()); 3245 if (orientation == B_HORIZONTAL) 3246 gradient.SetEnd(rect.LeftBottom()); 3247 else 3248 gradient.SetEnd(rect.RightTop()); 3249 3250 view->FillEllipse(rect, gradient); 3251 } 3252 3253 3254 rgb_color 3255 BControlLook::_EdgeLightColor(const rgb_color& base, float contrast, 3256 float brightness, uint32 flags) 3257 { 3258 rgb_color edgeLightColor; 3259 3260 if ((flags & B_BLEND_FRAME) != 0) { 3261 uint8 alpha = uint8(20 * contrast); 3262 uint8 white = uint8(255 * brightness); 3263 3264 edgeLightColor = (rgb_color){ white, white, white, alpha }; 3265 } else { 3266 // colors 3267 float tintLight = kEdgeBevelLightTint; 3268 3269 if (contrast == 0.0) 3270 tintLight = B_NO_TINT; 3271 else if (contrast != 1.0) 3272 tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast; 3273 3274 edgeLightColor = tint_color(base, tintLight); 3275 3276 if (brightness < 1.0) { 3277 edgeLightColor.red = uint8(edgeLightColor.red * brightness); 3278 edgeLightColor.green = uint8(edgeLightColor.green * brightness); 3279 edgeLightColor.blue = uint8(edgeLightColor.blue * brightness); 3280 } 3281 } 3282 3283 return edgeLightColor; 3284 } 3285 3286 3287 rgb_color 3288 BControlLook::_EdgeShadowColor(const rgb_color& base, float contrast, 3289 float brightness, uint32 flags) 3290 { 3291 rgb_color edgeShadowColor; 3292 3293 if ((flags & B_BLEND_FRAME) != 0) { 3294 uint8 alpha = uint8(20 * contrast); 3295 edgeShadowColor = (rgb_color){ 0, 0, 0, alpha }; 3296 } else { 3297 float tintShadow = kEdgeBevelShadowTint; 3298 3299 if (contrast == 0.0) 3300 tintShadow = B_NO_TINT; 3301 else if (contrast != 1.0) 3302 tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast; 3303 3304 edgeShadowColor = tint_color(base, tintShadow); 3305 3306 if (brightness < 1.0) { 3307 edgeShadowColor.red = uint8(edgeShadowColor.red * brightness); 3308 edgeShadowColor.green = uint8(edgeShadowColor.green * brightness); 3309 edgeShadowColor.blue = uint8(edgeShadowColor.blue * brightness); 3310 } 3311 } 3312 3313 return edgeShadowColor; 3314 } 3315 3316 3317 rgb_color 3318 BControlLook::_FrameLightColor(const rgb_color& base, uint32 flags) 3319 { 3320 if ((flags & B_FOCUSED) != 0) 3321 return ui_color(B_KEYBOARD_NAVIGATION_COLOR); 3322 3323 if ((flags & B_ACTIVATED) != 0) 3324 return _FrameShadowColor(base, flags & ~B_ACTIVATED); 3325 3326 rgb_color frameLightColor; 3327 3328 if ((flags & B_DISABLED) != 0) { 3329 // TODO: B_BLEND_FRAME 3330 frameLightColor = tint_color(base, 1.145); 3331 3332 if ((flags & B_DEFAULT_BUTTON) != 0) 3333 frameLightColor = tint_color(frameLightColor, 1.14); 3334 } else { 3335 if ((flags & B_BLEND_FRAME) != 0) 3336 frameLightColor = (rgb_color){ 0, 0, 0, 75 }; 3337 else 3338 frameLightColor = tint_color(base, 1.33); 3339 3340 if ((flags & B_DEFAULT_BUTTON) != 0) 3341 frameLightColor = tint_color(frameLightColor, 1.35); 3342 } 3343 3344 return frameLightColor; 3345 } 3346 3347 3348 rgb_color 3349 BControlLook::_FrameShadowColor(const rgb_color& base, uint32 flags) 3350 { 3351 if ((flags & B_FOCUSED) != 0) 3352 return ui_color(B_KEYBOARD_NAVIGATION_COLOR); 3353 3354 if ((flags & B_ACTIVATED) != 0) 3355 return _FrameLightColor(base, flags & ~B_ACTIVATED); 3356 3357 rgb_color frameShadowColor; 3358 3359 if ((flags & B_DISABLED) != 0) { 3360 // TODO: B_BLEND_FRAME 3361 frameShadowColor = tint_color(base, 1.24); 3362 3363 if ((flags & B_DEFAULT_BUTTON) != 0) { 3364 frameShadowColor = tint_color(base, 1.145); 3365 frameShadowColor = tint_color(frameShadowColor, 1.12); 3366 } 3367 } else { 3368 if ((flags & B_DEFAULT_BUTTON) != 0) { 3369 if ((flags & B_BLEND_FRAME) != 0) 3370 frameShadowColor = (rgb_color){ 0, 0, 0, 75 }; 3371 else 3372 frameShadowColor = tint_color(base, 1.33); 3373 3374 frameShadowColor = tint_color(frameShadowColor, 1.5); 3375 } else { 3376 if ((flags & B_BLEND_FRAME) != 0) 3377 frameShadowColor = (rgb_color){ 0, 0, 0, 95 }; 3378 else 3379 frameShadowColor = tint_color(base, 1.47); 3380 } 3381 } 3382 3383 return frameShadowColor; 3384 } 3385 3386 3387 rgb_color 3388 BControlLook::_BevelLightColor(const rgb_color& base, uint32 flags) 3389 { 3390 rgb_color bevelLightColor = tint_color(base, 0.2); 3391 3392 if ((flags & B_DISABLED) != 0) 3393 bevelLightColor = tint_color(base, B_LIGHTEN_1_TINT); 3394 3395 if ((flags & B_ACTIVATED) != 0) 3396 bevelLightColor = tint_color(base, B_DARKEN_1_TINT); 3397 3398 return bevelLightColor; 3399 } 3400 3401 3402 rgb_color 3403 BControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags) 3404 { 3405 rgb_color bevelShadowColor = tint_color(base, 1.08); 3406 3407 if ((flags & B_DISABLED) != 0) 3408 bevelShadowColor = base; 3409 3410 if ((flags & B_ACTIVATED) != 0) 3411 bevelShadowColor = tint_color(base, B_DARKEN_1_TINT); 3412 3413 return bevelShadowColor; 3414 } 3415 3416 3417 void 3418 BControlLook::_FillGradient(BView* view, const BRect& rect, 3419 const rgb_color& base, float topTint, float bottomTint, 3420 orientation orientation) 3421 { 3422 BGradientLinear gradient; 3423 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); 3424 view->FillRect(rect, gradient); 3425 } 3426 3427 3428 void 3429 BControlLook::_FillGlossyGradient(BView* view, const BRect& rect, 3430 const rgb_color& base, float topTint, float middle1Tint, 3431 float middle2Tint, float bottomTint, orientation orientation) 3432 { 3433 BGradientLinear gradient; 3434 _MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint, 3435 middle2Tint, bottomTint, orientation); 3436 view->FillRect(rect, gradient); 3437 } 3438 3439 3440 void 3441 BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect, 3442 const rgb_color& base, float topTint, float bottomTint, 3443 orientation orientation) const 3444 { 3445 gradient.AddColor(tint_color(base, topTint), 0); 3446 gradient.AddColor(tint_color(base, bottomTint), 255); 3447 gradient.SetStart(rect.LeftTop()); 3448 if (orientation == B_HORIZONTAL) 3449 gradient.SetEnd(rect.LeftBottom()); 3450 else 3451 gradient.SetEnd(rect.RightTop()); 3452 } 3453 3454 3455 void 3456 BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect, 3457 const rgb_color& base, float topTint, float middle1Tint, 3458 float middle2Tint, float bottomTint, 3459 orientation orientation) const 3460 { 3461 gradient.AddColor(tint_color(base, topTint), 0); 3462 gradient.AddColor(tint_color(base, middle1Tint), 132); 3463 gradient.AddColor(tint_color(base, middle2Tint), 136); 3464 gradient.AddColor(tint_color(base, bottomTint), 255); 3465 gradient.SetStart(rect.LeftTop()); 3466 if (orientation == B_HORIZONTAL) 3467 gradient.SetEnd(rect.LeftBottom()); 3468 else 3469 gradient.SetEnd(rect.RightTop()); 3470 } 3471 3472 3473 void 3474 BControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect, 3475 const rgb_color& base, uint32 flags, orientation orientation) const 3476 { 3477 float topTint = 0.49; 3478 float middleTint1 = 0.62; 3479 float middleTint2 = 0.76; 3480 float bottomTint = 0.90; 3481 3482 if ((flags & B_ACTIVATED) != 0) { 3483 topTint = 1.11; 3484 bottomTint = 1.08; 3485 } 3486 3487 if ((flags & B_DISABLED) != 0) { 3488 topTint = (topTint + B_NO_TINT) / 2; 3489 middleTint1 = (middleTint1 + B_NO_TINT) / 2; 3490 middleTint2 = (middleTint2 + B_NO_TINT) / 2; 3491 bottomTint = (bottomTint + B_NO_TINT) / 2; 3492 } else if ((flags & B_HOVER) != 0) { 3493 topTint *= kHoverTintFactor; 3494 middleTint1 *= kHoverTintFactor; 3495 middleTint2 *= kHoverTintFactor; 3496 bottomTint *= kHoverTintFactor; 3497 } 3498 3499 if ((flags & B_ACTIVATED) != 0) { 3500 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); 3501 } else { 3502 _MakeGlossyGradient(gradient, rect, base, topTint, middleTint1, 3503 middleTint2, bottomTint, orientation); 3504 } 3505 } 3506 3507 3508 3509 bool 3510 BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base, 3511 rgb_color& color, uint32 flags) const 3512 { 3513 if ((flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED)) == 0) { 3514 // no mark to be drawn at all 3515 return false; 3516 } 3517 3518 color = ui_color(B_CONTROL_MARK_COLOR); 3519 3520 float mix = 1.0; 3521 3522 if ((flags & B_DISABLED) != 0) { 3523 // activated, but disabled 3524 mix = 0.4; 3525 } else if ((flags & B_CLICKED) != 0) { 3526 if ((flags & B_ACTIVATED) != 0) { 3527 // losing activation 3528 mix = 0.7; 3529 } else { 3530 // becoming activated (or losing partial activation) 3531 mix = 0.3; 3532 } 3533 } else if ((flags & B_PARTIALLY_ACTIVATED) != 0) { 3534 // partially activated 3535 mix = 0.5; 3536 } else { 3537 // simply activated 3538 } 3539 3540 color.red = uint8(color.red * mix + base.red * (1.0 - mix)); 3541 color.green = uint8(color.green * mix + base.green * (1.0 - mix)); 3542 color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix)); 3543 3544 return true; 3545 } 3546 3547 3548 // NOTE: May come from a add-on in the future. Initialized in 3549 // InterfaceDefs.cpp 3550 BControlLook* be_control_look = NULL; 3551 3552 3553 } // namespace BPrivate 3554