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