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