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