1 /* 2 * Copyright 2021-2024 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus, superstippi@gmx.de 7 * John Scipione, jscipione@gmail.com 8 * Nahuel Tello, ntello@unarix.com.ar 9 */ 10 11 12 /*! FlatControlLook flat Haiku */ 13 14 15 #include "FlatControlLook.h" 16 17 #include <algorithm> 18 #include <cmath> 19 #include <new> 20 #include <stdio.h> 21 22 #include <GradientLinear.h> 23 #include <Rect.h> 24 #include <Region.h> 25 #include <View.h> 26 #include <WindowPrivate.h> 27 28 29 namespace BPrivate { 30 31 static const float kEdgeBevelLightTint = 1.0; 32 static const float kEdgeBevelShadowTint = 1.0; 33 static const float kHoverTintFactor = 0.55; 34 static const float kRadius = 3.0f; 35 36 static const float kButtonPopUpIndicatorWidth = 11; 37 38 39 FlatControlLook::FlatControlLook() 40 : HaikuControlLook() 41 { 42 } 43 44 45 FlatControlLook::~FlatControlLook() 46 { 47 } 48 49 50 // #pragma mark - 51 52 53 void 54 FlatControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, 55 const rgb_color& base, const rgb_color& background, uint32 flags, 56 uint32 borders) 57 { 58 _DrawButtonFrame(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, background, 59 1.0, 1.0, flags, borders); 60 } 61 62 63 void 64 FlatControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, 65 float radius, const rgb_color& base, const rgb_color& background, uint32 flags, 66 uint32 borders) 67 { 68 _DrawButtonFrame(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, background, 69 1.0, 1.0, flags, borders); 70 } 71 72 73 void 74 FlatControlLook::DrawButtonFrame(BView* view, BRect& rect, 75 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 76 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 77 const rgb_color& background, uint32 flags, 78 uint32 borders) 79 { 80 _DrawButtonFrame(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, background, 81 1.0, 1.0, flags, borders); 82 } 83 84 85 void 86 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, 87 const BRect& updateRect, const rgb_color& base, uint32 flags, 88 uint32 borders, orientation orientation) 89 { 90 _DrawButtonBackground(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, false, 91 flags, borders, orientation); 92 } 93 94 95 void 96 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, 97 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 98 uint32 borders, orientation orientation) 99 { 100 _DrawButtonBackground(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, false, 101 flags, borders, orientation); 102 } 103 104 105 void 106 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, 107 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 108 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 109 uint32 flags, uint32 borders, orientation orientation) 110 { 111 _DrawButtonBackground(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, false, 112 flags, borders, orientation); 113 } 114 115 116 void 117 FlatControlLook::DrawMenuBarBackground(BView* view, BRect& rect, const BRect& updateRect, 118 const rgb_color& base, uint32 flags, uint32 borders) 119 { 120 if (!ShouldDraw(view, rect, updateRect)) 121 return; 122 123 // the surface edges 124 125 // colors 126 float topTint = 1.0; 127 float bottomTint = 1.0; 128 129 rgb_color customColor = base; 130 bool isEnabled = (flags & B_DISABLED) != 0; 131 bool isFocused = (flags & B_FOCUSED) != 0; 132 133 if (isEnabled || isFocused) { 134 customColor = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.0); 135 rgb_color bevelColor1 = tint_color(customColor, 1.0); 136 rgb_color bevelColor2 = tint_color(customColor, 1.0); 137 138 topTint = 1.0; 139 bottomTint = 1.0; 140 141 _DrawFrame(view, rect, 142 bevelColor1, bevelColor1, 143 bevelColor2, bevelColor2, 144 borders & B_TOP_BORDER); 145 } else { 146 rgb_color cornerColor = tint_color(customColor, 1.0); 147 rgb_color bevelColorTop = tint_color(customColor, 1.0); 148 rgb_color bevelColorLeft = tint_color(customColor, 1.0); 149 rgb_color bevelColorRightBottom = tint_color(customColor, 1.0); 150 151 topTint = 1.0; 152 bottomTint = 1.0; 153 154 _DrawFrame(view, rect, 155 bevelColorLeft, bevelColorTop, 156 bevelColorRightBottom, bevelColorRightBottom, 157 cornerColor, cornerColor, 158 borders); 159 } 160 161 // draw surface top 162 _FillGradient(view, rect, customColor, topTint, bottomTint); 163 } 164 165 166 void 167 FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 168 const BRect& updateRect, const rgb_color& base, 169 const rgb_color& background, uint32 flags, uint32 borders) 170 { 171 _DrawButtonFrame(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, background, 172 1.0, 1.0, flags, borders); 173 } 174 175 176 void 177 FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 178 const BRect& updateRect, float radius, const rgb_color& base, 179 const rgb_color& background, uint32 flags, uint32 borders) 180 { 181 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius, base, background, 1.0, 182 1.0, flags, borders); 183 } 184 185 186 void 187 FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 188 const BRect& updateRect, float leftTopRadius, 189 float rightTopRadius, float leftBottomRadius, 190 float rightBottomRadius, const rgb_color& base, 191 const rgb_color& background, uint32 flags, uint32 borders) 192 { 193 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius, leftBottomRadius, 194 rightBottomRadius, base, background, 1.0, 1.0, flags, borders); 195 } 196 197 198 void 199 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 200 const BRect& updateRect, const rgb_color& base, bool popupIndicator, 201 uint32 flags) 202 { 203 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, 204 base, popupIndicator, flags); 205 } 206 207 208 void 209 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 210 const BRect& updateRect, const rgb_color& base, uint32 flags, 211 uint32 borders) 212 { 213 _DrawMenuFieldBackgroundInside(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, 214 flags, borders); 215 } 216 217 218 void 219 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 220 const BRect& updateRect, float radius, const rgb_color& base, 221 bool popupIndicator, uint32 flags) 222 { 223 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius, 224 radius, radius, base, popupIndicator, flags); 225 } 226 227 228 void 229 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 230 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 231 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 232 bool popupIndicator, uint32 flags) 233 { 234 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius, 235 rightTopRadius, leftBottomRadius, rightBottomRadius, base, 236 popupIndicator, flags); 237 } 238 239 240 void 241 FlatControlLook::DrawMenuBackground(BView* view, BRect& rect, 242 const BRect& updateRect, const rgb_color& base, uint32 flags, 243 uint32 borders) 244 { 245 if (!ShouldDraw(view, rect, updateRect)) 246 return; 247 248 // surface top color 249 rgb_color background = tint_color(base, 1.0); 250 251 // inner bevel colors 252 rgb_color bevelColor; 253 254 bevelColor = tint_color(background, 1.0); 255 256 // draw inner bevel 257 _DrawFrame(view, rect, 258 bevelColor, bevelColor, 259 bevelColor, bevelColor, 260 borders); 261 262 // draw surface top 263 view->SetHighColor(background); 264 view->FillRect(rect); 265 } 266 267 268 void 269 FlatControlLook::DrawMenuItemBackground(BView* view, BRect& rect, 270 const BRect& updateRect, const rgb_color& base, uint32 flags, 271 uint32 borders) 272 { 273 if (!ShouldDraw(view, rect, updateRect)) 274 return; 275 276 // surface edges 277 float topTint; 278 float bottomTint; 279 rgb_color selectedColor = base; 280 281 if ((flags & B_ACTIVATED) != 0) { 282 topTint = 0.94; 283 bottomTint = 1.1; 284 } else if ((flags & B_DISABLED) != 0) { 285 topTint = 1.0; 286 bottomTint = 1.0; 287 } else { 288 topTint = 0.95; 289 bottomTint = 1.1; 290 } 291 292 rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint); 293 294 // draw surface edges 295 _DrawFrame(view, rect, 296 bevelShadowColor, bevelShadowColor, 297 bevelShadowColor, bevelShadowColor, 298 borders); 299 300 // draw surface top 301 view->SetLowColor(selectedColor); 302 _FillGradient(view, rect, selectedColor, topTint, bottomTint); 303 } 304 305 306 void 307 FlatControlLook::DrawScrollBarBorder(BView* view, BRect rect, 308 const BRect& updateRect, const rgb_color& base, uint32 flags, 309 orientation orientation) 310 { 311 if (!ShouldDraw(view, rect, updateRect)) 312 return; 313 314 view->PushState(); 315 316 // set clipping constraints to rect 317 view->ClipToRect(rect); 318 319 bool isEnabled = (flags & B_DISABLED) == 0; 320 bool isFocused = (flags & B_FOCUSED) != 0; 321 322 view->SetHighColor(tint_color(base, 1.2)); 323 324 // stroke a line around the entire scrollbar 325 // take care of border highlighting, scroll target is focus view 326 if (isEnabled && isFocused) { 327 rgb_color borderColor = tint_color(base, 1.2); 328 rgb_color highlightColor = tint_color(base, 1.2); 329 330 view->BeginLineArray(4); 331 332 view->AddLine(BPoint(rect.left + 1, rect.bottom), 333 BPoint(rect.right, rect.bottom), borderColor); 334 view->AddLine(BPoint(rect.right, rect.top + 1), 335 BPoint(rect.right, rect.bottom - 1), borderColor); 336 337 if (orientation == B_HORIZONTAL) { 338 view->AddLine(BPoint(rect.left, rect.top + 1), 339 BPoint(rect.left, rect.bottom), borderColor); 340 } else { 341 view->AddLine(BPoint(rect.left, rect.top), 342 BPoint(rect.left, rect.bottom), highlightColor); 343 } 344 345 if (orientation == B_HORIZONTAL) { 346 view->AddLine(BPoint(rect.left, rect.top), 347 BPoint(rect.right, rect.top), highlightColor); 348 } else { 349 view->AddLine(BPoint(rect.left + 1, rect.top), 350 BPoint(rect.right, rect.top), borderColor); 351 } 352 353 view->EndLineArray(); 354 } else 355 view->StrokeRect(rect); 356 357 view->PopState(); 358 } 359 360 361 void 362 FlatControlLook::DrawScrollBarButton(BView* view, BRect rect, 363 const BRect& updateRect, const rgb_color& base, uint32 flags, 364 int32 direction, orientation orientation, bool down) 365 { 366 if (!ShouldDraw(view, rect, updateRect)) 367 return; 368 369 rgb_color arrowColor; 370 371 bool isEnabled = (flags & B_DISABLED) == 0; 372 373 if (isEnabled) { 374 arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.6); 375 // if the base color is too dark, then lets make it lighter 376 if (base.IsDark()) { 377 arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.3);; 378 } 379 } else { 380 arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.4); 381 // if the base color is too dark, then lets make it lighter 382 if (base.IsDark()) { 383 arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.5);; 384 } 385 } 386 387 // clip to button 388 view->PushState(); 389 view->ClipToRect(rect); 390 391 flags &= ~B_FLAT; 392 393 DrawScrollBarBackground(view, rect, updateRect, base, flags, orientation); 394 rect.InsetBy(1, 1); 395 DrawArrowShape(view, rect, updateRect, arrowColor, direction, flags, 1.0f); 396 397 // revert clipping constraints 398 view->PopState(); 399 } 400 401 402 void 403 FlatControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, 404 BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, 405 orientation orientation) 406 { 407 DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); 408 DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); 409 } 410 411 412 void 413 FlatControlLook::DrawScrollBarBackground(BView* view, BRect& rect, 414 const BRect& updateRect, const rgb_color& base, uint32 flags, 415 orientation orientation) 416 { 417 if (!ShouldDraw(view, rect, updateRect)) 418 return; 419 420 view->PushState(); 421 422 // set clipping constraints to rect 423 view->ClipToRect(rect); 424 425 bool isEnabled = (flags & B_DISABLED) == 0; 426 427 // fill background, we'll draw arrows and thumb on top 428 view->SetDrawingMode(B_OP_COPY); 429 430 float gradient1Tint = 1.08; 431 float gradient2Tint = 0.95; 432 433 if (orientation == B_HORIZONTAL) { 434 // dark vertical line on left edge 435 // fill 436 if (rect.Width() >= 0) { 437 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, 438 orientation); 439 } 440 } else { 441 // dark vertical line on top edge 442 // fill 443 if (rect.Height() >= 0) { 444 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, 445 orientation); 446 } 447 } 448 449 view->PopState(); 450 } 451 452 453 void 454 FlatControlLook::DrawScrollBarThumb(BView* view, BRect& rect, 455 const BRect& updateRect, const rgb_color& base, uint32 flags, 456 orientation orientation, uint32 knobStyle) 457 { 458 if (!ShouldDraw(view, rect, updateRect)) 459 return; 460 461 view->PushState(); 462 463 // set clipping constraints to rect 464 view->ClipToRect(rect); 465 466 // flags 467 bool isEnabled = (flags & B_DISABLED) == 0; 468 469 // colors 470 rgb_color thumbColor = tint_color(ui_color(B_SCROLL_BAR_THUMB_COLOR), 1.09); 471 rgb_color base_panel = ui_color(B_PANEL_BACKGROUND_COLOR); 472 473 rgb_color light, dark, dark1, dark2; 474 light = tint_color(base_panel, B_DARKEN_1_TINT); 475 dark = tint_color(base_panel, B_DARKEN_1_TINT); 476 dark1 = tint_color(base_panel, B_DARKEN_1_TINT); 477 dark2 = tint_color(base_panel, B_DARKEN_1_TINT); 478 479 // draw thumb over background 480 view->SetDrawingMode(B_OP_OVER); 481 view->SetHighColor(dark1); 482 483 // draw scroll thumb 484 if (isEnabled) { 485 // fill the clickable surface of the thumb 486 // set clipping constraints to updateRect 487 BRegion clipping(updateRect); 488 DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation); 489 if (orientation == B_HORIZONTAL) 490 rect.InsetBy(0, 2); 491 else 492 rect.InsetBy(2, 0); 493 view->SetHighColor(base_panel); 494 view->FillRect(rect); 495 496 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, kRadius + 1, kRadius + 1, 497 kRadius + 1, kRadius + 1, thumbColor, false, flags, B_ALL_BORDERS, orientation); 498 } else { 499 DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation); 500 } 501 502 knobStyle = B_KNOB_LINES; // Hard set of the knobstyle 503 504 // draw knob style 505 if (knobStyle != B_KNOB_NONE && isEnabled) { 506 rgb_color knobLight = isEnabled 507 ? tint_color(thumbColor, 0.85) 508 : tint_color(base_panel, 1.05); 509 rgb_color knobDark = isEnabled 510 ? tint_color(thumbColor, 1.35) 511 : tint_color(base_panel, 1.05); 512 513 if (knobStyle == B_KNOB_DOTS) { 514 // draw dots on the scroll bar thumb 515 float hcenter = rect.left + rect.Width() / 2; 516 float vmiddle = rect.top + rect.Height() / 2; 517 BRect knob(hcenter, vmiddle, hcenter, vmiddle); 518 519 if (orientation == B_HORIZONTAL) { 520 view->SetHighColor(knobDark); 521 view->FillRect(knob); 522 view->SetHighColor(knobLight); 523 view->FillRect(knob.OffsetByCopy(1, 1)); 524 525 float spacer = rect.Height(); 526 527 if (rect.left + 3 < hcenter - spacer) { 528 view->SetHighColor(knobDark); 529 view->FillRect(knob.OffsetByCopy(-spacer, 0)); 530 view->SetHighColor(knobLight); 531 view->FillRect(knob.OffsetByCopy(-spacer + 1, 1)); 532 } 533 534 if (rect.right - 3 > hcenter + spacer) { 535 view->SetHighColor(knobDark); 536 view->FillRect(knob.OffsetByCopy(spacer, 0)); 537 view->SetHighColor(knobLight); 538 view->FillRect(knob.OffsetByCopy(spacer + 1, 1)); 539 } 540 } else { 541 // B_VERTICAL 542 view->SetHighColor(knobDark); 543 view->FillRect(knob); 544 view->SetHighColor(knobLight); 545 view->FillRect(knob.OffsetByCopy(1, 1)); 546 547 float spacer = rect.Width(); 548 549 if (rect.top + 3 < vmiddle - spacer) { 550 view->SetHighColor(knobDark); 551 view->FillRect(knob.OffsetByCopy(0, -spacer)); 552 view->SetHighColor(knobLight); 553 view->FillRect(knob.OffsetByCopy(1, -spacer + 1)); 554 } 555 556 if (rect.bottom - 3 > vmiddle + spacer) { 557 view->SetHighColor(knobDark); 558 view->FillRect(knob.OffsetByCopy(0, spacer)); 559 view->SetHighColor(knobLight); 560 view->FillRect(knob.OffsetByCopy(1, spacer + 1)); 561 } 562 } 563 } else if (knobStyle == B_KNOB_LINES && isEnabled) { 564 // draw lines on the scroll bar thumb 565 if (orientation == B_HORIZONTAL) { 566 float middle = rect.Width() / 2; 567 568 view->BeginLineArray(6); 569 view->AddLine( 570 BPoint(rect.left + middle - 3, rect.top + 2), 571 BPoint(rect.left + middle - 3, rect.bottom - 2), 572 knobDark); 573 view->AddLine( 574 BPoint(rect.left + middle, rect.top + 2), 575 BPoint(rect.left + middle, rect.bottom - 2), 576 knobDark); 577 view->AddLine( 578 BPoint(rect.left + middle + 3, rect.top + 2), 579 BPoint(rect.left + middle + 3, rect.bottom - 2), 580 knobDark); 581 view->AddLine( 582 BPoint(rect.left + middle - 2, rect.top + 2), 583 BPoint(rect.left + middle - 2, rect.bottom - 2), 584 knobLight); 585 view->AddLine( 586 BPoint(rect.left + middle + 1, rect.top + 2), 587 BPoint(rect.left + middle + 1, rect.bottom - 2), 588 knobLight); 589 view->AddLine( 590 BPoint(rect.left + middle + 4, rect.top + 2), 591 BPoint(rect.left + middle + 4, rect.bottom - 2), 592 knobLight); 593 view->EndLineArray(); 594 } else { 595 // B_VERTICAL 596 float middle = rect.Height() / 2; 597 598 view->BeginLineArray(6); 599 view->AddLine( 600 BPoint(rect.left + 2, rect.top + middle - 3), 601 BPoint(rect.right - 2, rect.top + middle - 3), 602 knobDark); 603 view->AddLine( 604 BPoint(rect.left + 2, rect.top + middle), 605 BPoint(rect.right - 2, rect.top + middle), 606 knobDark); 607 view->AddLine( 608 BPoint(rect.left + 2, rect.top + middle + 3), 609 BPoint(rect.right - 2, rect.top + middle + 3), 610 knobDark); 611 view->AddLine( 612 BPoint(rect.left + 2, rect.top + middle - 2), 613 BPoint(rect.right - 2, rect.top + middle - 2), 614 knobLight); 615 view->AddLine( 616 BPoint(rect.left + 2, rect.top + middle + 1), 617 BPoint(rect.right - 2, rect.top + middle + 1), 618 knobLight); 619 view->AddLine( 620 BPoint(rect.left + 2, rect.top + middle + 4), 621 BPoint(rect.right - 2, rect.top + middle + 4), 622 knobLight); 623 view->EndLineArray(); 624 } 625 } 626 } 627 628 view->PopState(); 629 } 630 631 632 void 633 FlatControlLook::DrawScrollViewFrame(BView* view, BRect& rect, 634 const BRect& updateRect, BRect verticalScrollBarFrame, 635 BRect horizontalScrollBarFrame, const rgb_color& base, 636 border_style borderStyle, uint32 flags, uint32 _borders) 637 { 638 // calculate scroll corner rect before messing with the "rect" 639 BRect scrollCornerFillRect(rect.right, rect.bottom, 640 rect.right, rect.bottom); 641 642 if (horizontalScrollBarFrame.IsValid()) 643 scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1; 644 645 if (verticalScrollBarFrame.IsValid()) 646 scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1; 647 648 if (borderStyle == B_NO_BORDER) { 649 if (scrollCornerFillRect.IsValid()) { 650 view->SetHighColor(base); 651 view->FillRect(scrollCornerFillRect); 652 } 653 return; 654 } 655 656 bool excludeScrollCorner = borderStyle == B_FANCY_BORDER 657 && horizontalScrollBarFrame.IsValid() 658 && verticalScrollBarFrame.IsValid(); 659 660 uint32 borders = _borders; 661 if (excludeScrollCorner) { 662 rect.bottom = horizontalScrollBarFrame.top; 663 rect.right = verticalScrollBarFrame.left; 664 borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER); 665 } 666 667 rgb_color scrollbarFrameColor = tint_color(base, 1.2); 668 669 if (borderStyle == B_FANCY_BORDER) 670 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); 671 672 if ((flags & B_FOCUSED) != 0) { 673 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 674 scrollbarFrameColor, scrollbarFrameColor, borders); 675 } else { 676 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 677 scrollbarFrameColor, scrollbarFrameColor, borders); 678 } 679 680 if (excludeScrollCorner) { 681 horizontalScrollBarFrame.InsetBy(-1, -1); 682 683 // do not overdraw the top edge 684 horizontalScrollBarFrame.top += 2; 685 borders = _borders; 686 borders &= ~B_TOP_BORDER; 687 _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base, 688 1.0, 1.0, flags, borders); 689 _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor, 690 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, 691 borders); 692 693 verticalScrollBarFrame.InsetBy(-1, -1); 694 695 // do not overdraw the left edge 696 verticalScrollBarFrame.left += 2; 697 borders = _borders; 698 borders &= ~B_LEFT_BORDER; 699 _DrawOuterResessedFrame(view, verticalScrollBarFrame, base, 700 1.0, 1.0, flags, borders); 701 _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor, 702 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, 703 borders); 704 705 // exclude recessed frame 706 scrollCornerFillRect.top++; 707 scrollCornerFillRect.left++; 708 } 709 710 if (scrollCornerFillRect.IsValid()) { 711 view->SetHighColor(base); 712 view->FillRect(scrollCornerFillRect); 713 } 714 } 715 716 717 rgb_color 718 FlatControlLook::SliderBarColor(const rgb_color& base) 719 { 720 return base.IsLight() ? tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.05) : 721 tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 0.95); 722 } 723 724 725 void 726 FlatControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 727 const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor, 728 float sliderScale, uint32 flags, orientation orientation) 729 { 730 if (!ShouldDraw(view, rect, updateRect)) 731 return; 732 733 // separate the bar in two sides 734 float sliderPosition; 735 BRect leftBarSide = rect; 736 BRect rightBarSide = rect; 737 738 if (orientation == B_HORIZONTAL) { 739 sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2) 740 * sliderScale); 741 leftBarSide.right = sliderPosition - 1; 742 rightBarSide.left = sliderPosition; 743 } else { 744 // NOTE: position is reverse of coords 745 sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2) 746 * (1.0 - sliderScale)); 747 leftBarSide.top = sliderPosition; 748 rightBarSide.bottom = sliderPosition - 1; 749 } 750 751 // fill the background for the corners, exclude the middle bar for now 752 view->PushState(); 753 view->ClipToRect(rightBarSide); 754 755 DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags, orientation); 756 757 view->PopState(); 758 759 view->PushState(); 760 view->ClipToRect(leftBarSide); 761 762 DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags, 763 orientation); 764 765 // restore the clipping constraints of the view 766 view->PopState(); 767 } 768 769 770 void 771 FlatControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 772 const rgb_color& base, rgb_color fillColor, uint32 flags, 773 orientation orientation) 774 { 775 if (!ShouldDraw(view, rect, updateRect)) 776 return; 777 778 // separate the rect into corners 779 BRect leftCorner(rect); 780 BRect rightCorner(rect); 781 BRect barRect(rect); 782 783 if (orientation == B_HORIZONTAL) { 784 leftCorner.right = leftCorner.left + leftCorner.Height(); 785 rightCorner.left = rightCorner.right - rightCorner.Height(); 786 barRect.left += ceilf(barRect.Height() / 2); 787 barRect.right -= ceilf(barRect.Height() / 2); 788 } else { 789 leftCorner.bottom = leftCorner.top + leftCorner.Width(); 790 rightCorner.top = rightCorner.bottom - rightCorner.Width(); 791 barRect.top += ceilf(barRect.Width() / 2); 792 barRect.bottom -= ceilf(barRect.Width() / 2); 793 } 794 795 // fill the background for the corners, exclude the middle bar for now 796 view->PushState(); 797 view->ClipToRect(rect); 798 view->ClipToInverseRect(barRect); 799 800 if ((flags & B_BLEND_FRAME) == 0) { 801 view->SetHighColor(base); 802 view->FillRect(rect); 803 } 804 805 // figure out the tints to be used 806 float edgeLightTint; 807 float edgeShadowTint; 808 float frameLightTint; 809 float frameShadowTint; 810 float fillLightTint; 811 float fillShadowTint; 812 uint8 edgeLightAlpha; 813 uint8 edgeShadowAlpha; 814 uint8 frameLightAlpha; 815 uint8 frameShadowAlpha; 816 817 if ((flags & B_DISABLED) != 0) { 818 edgeLightTint = 1.0; 819 edgeShadowTint = 1.0; 820 frameLightTint = 1.05; 821 frameShadowTint = 1.05; 822 fillLightTint = 0.8; 823 fillShadowTint = 0.8; 824 edgeLightAlpha = 12; 825 edgeShadowAlpha = 12; 826 frameLightAlpha = 40; 827 frameShadowAlpha = 45; 828 829 fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6); 830 fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6); 831 fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6); 832 } else { 833 edgeLightTint = 1.0; 834 edgeShadowTint = 1.0; 835 frameLightTint = 1.20; 836 frameShadowTint = 1.20; 837 fillLightTint = 0.9; 838 fillShadowTint = 0.9; 839 edgeLightAlpha = 15; 840 edgeShadowAlpha = 15; 841 frameLightAlpha = 102; 842 frameShadowAlpha = 117; 843 } 844 845 rgb_color edgeLightColor; 846 rgb_color edgeShadowColor; 847 rgb_color frameLightColor; 848 rgb_color frameShadowColor; 849 rgb_color fillLightColor = tint_color(fillColor, fillLightTint); 850 rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint); 851 852 drawing_mode oldMode = view->DrawingMode(); 853 854 if ((flags & B_BLEND_FRAME) != 0) { 855 edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha }; 856 edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha }; 857 frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha }; 858 frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha }; 859 860 view->SetDrawingMode(B_OP_ALPHA); 861 } else { 862 edgeLightColor = tint_color(base, edgeLightTint); 863 edgeShadowColor = tint_color(base, edgeShadowTint); 864 frameLightColor = tint_color(fillColor, frameLightTint); 865 frameShadowColor = tint_color(fillColor, frameShadowTint); 866 } 867 868 if (orientation == B_HORIZONTAL) { 869 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, 870 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 871 fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation); 872 873 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, 874 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 875 fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation); 876 } else { 877 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, 878 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 879 fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation); 880 881 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, 882 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 883 fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation); 884 } 885 886 view->PopState(); 887 888 view->BeginLineArray(4); 889 if (orientation == B_HORIZONTAL) { 890 view->AddLine(barRect.LeftTop(), barRect.RightTop(), 891 edgeShadowColor); 892 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), 893 edgeLightColor); 894 barRect.InsetBy(0, 1); 895 view->AddLine(barRect.LeftTop(), barRect.RightTop(), 896 frameShadowColor); 897 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), 898 frameLightColor); 899 barRect.InsetBy(0, 1); 900 } else { 901 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), 902 edgeShadowColor); 903 view->AddLine(barRect.RightTop(), barRect.RightBottom(), 904 edgeLightColor); 905 barRect.InsetBy(1, 0); 906 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), 907 frameShadowColor); 908 view->AddLine(barRect.RightTop(), barRect.RightBottom(), 909 frameLightColor); 910 barRect.InsetBy(1, 0); 911 } 912 view->EndLineArray(); 913 914 view->SetDrawingMode(oldMode); 915 916 _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint, 917 orientation); 918 } 919 920 921 void 922 FlatControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect, 923 const rgb_color& base, uint32 flags, orientation orientation) 924 { 925 if (!ShouldDraw(view, rect, updateRect)) 926 return; 927 928 rgb_color thumbColor = tint_color(ui_color(B_SCROLL_BAR_THUMB_COLOR), 1.0); 929 930 // figure out frame color 931 rgb_color frameLightColor; 932 rgb_color frameShadowColor; 933 rgb_color shadowColor; 934 935 if (base.IsLight()) 936 shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.5); 937 else 938 shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.55); 939 940 if ((flags & B_FOCUSED) != 0) { 941 // focused 942 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 943 frameShadowColor = frameLightColor; 944 } else { 945 // figure out the tints to be used 946 float frameLightTint; 947 float frameShadowTint; 948 949 if ((flags & B_DISABLED) != 0) { 950 frameLightTint = 1.30; 951 frameShadowTint = 1.35; 952 shadowColor.alpha = 30; 953 } else { 954 frameLightTint = 1.6; 955 frameShadowTint = 1.65; 956 } 957 958 frameLightColor = tint_color(base, frameLightTint); 959 frameShadowColor = tint_color(base, frameShadowTint); 960 } 961 962 BRect originalRect(rect); 963 rect.right--; 964 rect.bottom--; 965 966 _DrawFrame(view, rect, shadowColor, shadowColor, shadowColor, shadowColor); 967 968 flags &= ~B_ACTIVATED; 969 flags &= ~B_FLAT; 970 DrawScrollBarBackground(view, rect, updateRect, base, flags, orientation); 971 972 // thumb edge 973 if (orientation == B_HORIZONTAL) { 974 rect.InsetBy(0, floorf(rect.Height() / 4)); 975 rect.left = floorf((rect.left + rect.right) / 2); 976 rect.right = rect.left; 977 shadowColor = tint_color(thumbColor, 1.5); 978 view->SetHighColor(shadowColor); 979 view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); 980 rgb_color lightColor = tint_color(thumbColor, 1.0); 981 view->SetHighColor(lightColor); 982 view->StrokeLine(rect.RightTop(), rect.RightBottom()); 983 } else { 984 rect.InsetBy(floorf(rect.Width() / 4), 0); 985 rect.top = floorf((rect.top + rect.bottom) / 2); 986 rect.bottom = rect.top + 1; 987 shadowColor = tint_color(thumbColor, 1.5); 988 view->SetHighColor(shadowColor); 989 view->StrokeLine(rect.LeftTop(), rect.RightTop()); 990 rgb_color lightColor = tint_color(thumbColor, 1.0); 991 view->SetHighColor(lightColor); 992 view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); 993 } 994 995 view->SetDrawingMode(B_OP_COPY); 996 } 997 998 999 void 1000 FlatControlLook::DrawActiveTab(BView* view, BRect& rect, 1001 const BRect& updateRect, const rgb_color& base, uint32 flags, 1002 uint32 borders, uint32 side, int32, int32, int32, int32) 1003 { 1004 if (!ShouldDraw(view, rect, updateRect)) 1005 return; 1006 1007 // Snap the rectangle to pixels to avoid rounding errors. 1008 rect.left = floorf(rect.left); 1009 rect.right = floorf(rect.right); 1010 rect.top = floorf(rect.top); 1011 rect.bottom = floorf(rect.bottom); 1012 1013 // save the clipping constraints of the view 1014 view->PushState(); 1015 1016 // set clipping constraints to rect 1017 view->ClipToRect(rect); 1018 1019 rgb_color edgeShadowColor; 1020 rgb_color edgeLightColor; 1021 rgb_color frameShadowColor; 1022 rgb_color frameLightColor; 1023 rgb_color bevelShadowColor; 1024 rgb_color bevelLightColor; 1025 BGradientLinear fillGradient; 1026 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3)); 1027 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3)); 1028 1029 if ((flags & B_DISABLED) != 0) { 1030 edgeLightColor = base; 1031 edgeShadowColor = base; 1032 frameLightColor = tint_color(base, 1.0); 1033 frameShadowColor = tint_color(base, 1.30); 1034 bevelLightColor = tint_color(base, 0.8); 1035 bevelShadowColor = tint_color(base, 1.07); 1036 fillGradient.AddColor(tint_color(base, 0.85), 0); 1037 fillGradient.AddColor(base, 255); 1038 } else { 1039 edgeLightColor = tint_color(base, 0.95); 1040 edgeShadowColor = tint_color(base, 1.03); 1041 frameLightColor = tint_color(base, 1.30); 1042 frameShadowColor = tint_color(base, 1.30); 1043 bevelLightColor = tint_color(base, 0.9); 1044 bevelShadowColor = tint_color(base, 1.07); 1045 fillGradient.AddColor(tint_color(base, 0.95), 0); 1046 fillGradient.AddColor(tint_color(base, 1.0), 255); 1047 } 1048 1049 static const float kRoundCornerRadius = 2.0f; 1050 1051 // left top corner dimensions 1052 BRect leftTopCorner(rect); 1053 leftTopCorner.right = floorf(leftTopCorner.left + kRoundCornerRadius); 1054 leftTopCorner.bottom = floorf(rect.top + kRoundCornerRadius); 1055 1056 // right top corner dimensions 1057 BRect rightTopCorner(rect); 1058 rightTopCorner.left = floorf(rightTopCorner.right - kRoundCornerRadius); 1059 rightTopCorner.bottom = floorf(rect.top + kRoundCornerRadius); 1060 1061 // left bottom corner dimensions 1062 BRect leftBottomCorner(rect); 1063 leftBottomCorner.right = floorf(leftBottomCorner.left + kRoundCornerRadius); 1064 leftBottomCorner.top = floorf(rect.bottom - kRoundCornerRadius); 1065 1066 // right bottom corner dimensions 1067 BRect rightBottomCorner(rect); 1068 rightBottomCorner.left = floorf(rightBottomCorner.right 1069 - kRoundCornerRadius); 1070 rightBottomCorner.top = floorf(rect.bottom - kRoundCornerRadius); 1071 1072 BRect roundCorner[2]; 1073 1074 switch (side) { 1075 case B_TOP_BORDER: 1076 roundCorner[0] = leftTopCorner; 1077 roundCorner[1] = rightTopCorner; 1078 1079 // draw the left top corner 1080 _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base, 1081 edgeShadowColor, frameLightColor, bevelLightColor, 1082 fillGradient); 1083 // draw the right top corner 1084 _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base, 1085 edgeShadowColor, edgeLightColor, frameLightColor, 1086 frameShadowColor, bevelLightColor, bevelShadowColor, 1087 fillGradient); 1088 break; 1089 case B_BOTTOM_BORDER: 1090 roundCorner[0] = leftBottomCorner; 1091 roundCorner[1] = rightBottomCorner; 1092 1093 // draw the left bottom corner 1094 _DrawRoundCornerLeftBottom(view, leftBottomCorner, updateRect, base, 1095 edgeShadowColor, edgeLightColor, frameLightColor, 1096 frameShadowColor, bevelLightColor, bevelShadowColor, 1097 fillGradient); 1098 // draw the right bottom corner 1099 _DrawRoundCornerRightBottom(view, rightBottomCorner, updateRect, 1100 base, edgeLightColor, frameShadowColor, bevelShadowColor, 1101 fillGradient); 1102 break; 1103 case B_LEFT_BORDER: 1104 roundCorner[0] = leftTopCorner; 1105 roundCorner[1] = leftBottomCorner; 1106 1107 // draw the left top corner 1108 _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base, 1109 edgeShadowColor, frameLightColor, bevelLightColor, 1110 fillGradient); 1111 // draw the left bottom corner 1112 _DrawRoundCornerLeftBottom(view, leftBottomCorner, updateRect, base, 1113 edgeShadowColor, edgeLightColor, frameLightColor, 1114 frameShadowColor, bevelLightColor, bevelShadowColor, 1115 fillGradient); 1116 break; 1117 case B_RIGHT_BORDER: 1118 roundCorner[0] = rightTopCorner; 1119 roundCorner[1] = rightBottomCorner; 1120 1121 // draw the right top corner 1122 _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base, 1123 edgeShadowColor, edgeLightColor, frameLightColor, 1124 frameShadowColor, bevelLightColor, bevelShadowColor, 1125 fillGradient); 1126 // draw the right bottom corner 1127 _DrawRoundCornerRightBottom(view, rightBottomCorner, updateRect, 1128 base, edgeLightColor, frameShadowColor, bevelShadowColor, 1129 fillGradient); 1130 break; 1131 } 1132 1133 // clip out the corners 1134 view->ClipToInverseRect(roundCorner[0]); 1135 view->ClipToInverseRect(roundCorner[1]); 1136 1137 uint32 bordersToDraw = 0; 1138 switch (side) { 1139 case B_TOP_BORDER: 1140 bordersToDraw = (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER); 1141 break; 1142 case B_BOTTOM_BORDER: 1143 bordersToDraw = (B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER); 1144 break; 1145 case B_LEFT_BORDER: 1146 bordersToDraw = (B_LEFT_BORDER | B_BOTTOM_BORDER | B_TOP_BORDER); 1147 break; 1148 case B_RIGHT_BORDER: 1149 bordersToDraw = (B_RIGHT_BORDER | B_BOTTOM_BORDER | B_TOP_BORDER); 1150 break; 1151 } 1152 1153 // draw the rest of frame and fill 1154 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, 1155 edgeLightColor, borders); 1156 if (side == B_TOP_BORDER || side == B_BOTTOM_BORDER) { 1157 if ((borders & B_LEFT_BORDER) == 0) 1158 rect.left++; 1159 if ((borders & B_RIGHT_BORDER) == 0) 1160 rect.right--; 1161 } else if (side == B_LEFT_BORDER || side == B_RIGHT_BORDER) { 1162 if ((borders & B_TOP_BORDER) == 0) 1163 rect.top++; 1164 if ((borders & B_BOTTOM_BORDER) == 0) 1165 rect.bottom--; 1166 } 1167 1168 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, 1169 frameShadowColor, bordersToDraw); 1170 1171 _DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor, 1172 bevelShadowColor); 1173 1174 view->FillRect(rect, fillGradient); 1175 1176 // restore the clipping constraints of the view 1177 view->PopState(); 1178 } 1179 1180 1181 void 1182 FlatControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect, 1183 const rgb_color& base, orientation orientation, uint32 flags, 1184 uint32 borders) 1185 { 1186 if (!ShouldDraw(view, rect, updateRect)) 1187 return; 1188 1189 rgb_color background; 1190 if ((flags & (B_CLICKED | B_ACTIVATED)) != 0) 1191 background = tint_color(base, B_DARKEN_1_TINT); 1192 else 1193 background = base; 1194 1195 rgb_color light = tint_color(background, 1.9); 1196 rgb_color shadow = tint_color(background, 1.9); 1197 1198 // frame 1199 if (borders != 0 && rect.Width() > 3 && rect.Height() > 3) 1200 DrawRaisedBorder(view, rect, updateRect, background, flags, borders); 1201 1202 // dots and rest of background 1203 if (orientation == B_HORIZONTAL) { 1204 if (rect.Width() > 2) { 1205 // background on left/right 1206 BRegion region(rect); 1207 rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5); 1208 rect.right = rect.left + 1; 1209 region.Exclude(rect); 1210 view->SetHighColor(background); 1211 view->FillRegion(®ion); 1212 } 1213 1214 BPoint dot = rect.LeftTop(); 1215 BPoint stop = rect.LeftBottom(); 1216 int32 num = 1; 1217 while (dot.y <= stop.y) { 1218 rgb_color col1; 1219 rgb_color col2; 1220 switch (num) { 1221 case 1: 1222 col1 = background; 1223 col2 = background; 1224 break; 1225 case 2: 1226 col1 = shadow; 1227 col2 = background; 1228 break; 1229 case 3: 1230 default: 1231 col1 = background; 1232 col2 = light; 1233 num = 0; 1234 break; 1235 } 1236 view->SetHighColor(col1); 1237 view->StrokeLine(dot, dot, B_SOLID_LOW); 1238 view->SetHighColor(col2); 1239 dot.x++; 1240 view->StrokeLine(dot, dot, B_SOLID_LOW); 1241 dot.x -= 1.0; 1242 // next pixel 1243 num++; 1244 dot.y++; 1245 } 1246 } else { 1247 if (rect.Height() > 2) { 1248 // background on left/right 1249 BRegion region(rect); 1250 rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5); 1251 rect.bottom = rect.top + 1; 1252 region.Exclude(rect); 1253 view->SetHighColor(background); 1254 view->FillRegion(®ion); 1255 } 1256 1257 BPoint dot = rect.LeftTop(); 1258 BPoint stop = rect.RightTop(); 1259 int32 num = 1; 1260 while (dot.x <= stop.x) { 1261 rgb_color col1; 1262 rgb_color col2; 1263 switch (num) { 1264 case 1: 1265 col1 = background; 1266 col2 = background; 1267 break; 1268 case 2: 1269 col1 = shadow; 1270 col2 = background; 1271 break; 1272 case 3: 1273 default: 1274 col1 = background; 1275 col2 = light; 1276 num = 0; 1277 break; 1278 } 1279 view->SetHighColor(col1); 1280 view->StrokeLine(dot, dot, B_SOLID_LOW); 1281 view->SetHighColor(col2); 1282 dot.y++; 1283 view->StrokeLine(dot, dot, B_SOLID_LOW); 1284 dot.y -= 1.0; 1285 // next pixel 1286 num++; 1287 dot.x++; 1288 } 1289 } 1290 } 1291 1292 1293 // #pragma mark - 1294 1295 1296 void 1297 FlatControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect, 1298 const rgb_color& base, border_style borderStyle, uint32 flags, 1299 uint32 borders) 1300 { 1301 if (borderStyle == B_NO_BORDER) 1302 return; 1303 1304 rgb_color scrollbarFrameColor = tint_color(base, 1.0); 1305 1306 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 1307 scrollbarFrameColor, scrollbarFrameColor, borders); 1308 } 1309 1310 1311 void 1312 FlatControlLook::DrawRaisedBorder(BView* view, BRect& rect, 1313 const BRect& updateRect, const rgb_color& base, uint32 flags, 1314 uint32 borders) 1315 { 1316 _DrawFrame(view, rect, base, base, base, base, borders); 1317 } 1318 1319 1320 void 1321 FlatControlLook::DrawTextControlBorder(BView* view, BRect& rect, 1322 const BRect& updateRect, const rgb_color& base, uint32 flags, 1323 uint32 borders) 1324 { 1325 if (!ShouldDraw(view, rect, updateRect)) 1326 return; 1327 1328 rgb_color dark1BorderColor; 1329 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 1330 rgb_color invalidColor = ui_color(B_FAILURE_COLOR); 1331 rgb_color documentBackground = ui_color(B_DOCUMENT_BACKGROUND_COLOR); 1332 rgb_color customColor2 = tint_color(documentBackground, 1.0); 1333 dark1BorderColor = tint_color(customColor2, 0.5); 1334 1335 if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) { 1336 if (base.IsDark()) 1337 documentBackground = tint_color(documentBackground, 0.9); 1338 else 1339 documentBackground = tint_color(documentBackground, 1.5); 1340 } 1341 1342 if ((flags & B_DISABLED) == 0 && (flags & B_INVALID) != 0) 1343 documentBackground = tint_color(invalidColor, 0.5); 1344 1345 if ((flags & B_BLEND_FRAME) != 0) { 1346 drawing_mode oldMode = view->DrawingMode(); 1347 view->SetDrawingMode(B_OP_ALPHA); 1348 1349 _DrawButtonFrame(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, 1350 documentBackground, base, false, false, flags, borders); 1351 1352 view->SetDrawingMode(oldMode); 1353 } else { 1354 1355 _DrawButtonFrame(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, 1356 documentBackground, base, false, false, flags, borders); 1357 } 1358 } 1359 1360 1361 void 1362 FlatControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect, 1363 const rgb_color& base, uint32 borders) 1364 { 1365 rgb_color frameColor = tint_color(base, 1.1); 1366 1367 if (base.IsDark()) 1368 frameColor = tint_color(base, 0.95); 1369 1370 // Draws only one flat frame: 1371 _DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor, borders); 1372 } 1373 1374 1375 void 1376 FlatControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 1377 const BRect& updateRect, const rgb_color& base, uint32 flags, 1378 uint32 borders, orientation orientation) 1379 { 1380 _DrawButtonBackground(view, rect, updateRect, kRadius, kRadius, kRadius, kRadius, base, true, 1381 flags, borders, orientation); 1382 } 1383 1384 1385 void 1386 FlatControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 1387 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 1388 uint32 borders, orientation orientation) 1389 { 1390 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius, 1391 radius, base, true, flags, borders, orientation); 1392 } 1393 1394 1395 void 1396 FlatControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, 1397 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 1398 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 1399 uint32 flags, uint32 borders, orientation orientation) 1400 { 1401 _DrawButtonBackground(view, rect, updateRect, leftTopRadius, 1402 rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags, 1403 borders, orientation); 1404 } 1405 1406 1407 // #pragma mark - 1408 1409 1410 void 1411 FlatControlLook::_DrawButtonFrame(BView* view, BRect& rect, 1412 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 1413 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 1414 const rgb_color& background, float contrast, float brightness, 1415 uint32 flags, uint32 borders) 1416 { 1417 if (!ShouldDraw(view, rect, updateRect)) 1418 return; 1419 1420 rgb_color customColor = background; // custom color for borders 1421 rgb_color customColor2 = tint_color(background, 1.3); 1422 1423 if (base.IsDark()) 1424 customColor2 = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.5); 1425 1426 1427 // save the clipping constraints of the view 1428 view->PushState(); 1429 1430 // set clipping constraints to rect 1431 view->ClipToRect(rect); 1432 1433 // If the button is flat and neither activated nor otherwise highlighted 1434 // (mouse hovering or focussed), draw it flat. 1435 if ((flags & B_FLAT) != 0 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 1436 && ((flags & (B_HOVER | B_FOCUSED)) == 0 || (flags & B_DISABLED) != 0)) { 1437 _DrawFrame(view, rect, background, background, background, background, borders); 1438 _DrawFrame(view, rect, background, background, background, background, borders); 1439 view->PopState(); 1440 return; 1441 } 1442 1443 // outer edge colors 1444 rgb_color edgeLightColor; 1445 rgb_color edgeShadowColor; 1446 1447 // default button frame color 1448 rgb_color defaultIndicatorColor = ui_color(B_WINDOW_TAB_COLOR); 1449 rgb_color cornerBgColor = background; 1450 1451 if ((flags & B_DISABLED) != 0) { 1452 defaultIndicatorColor = disable_color(defaultIndicatorColor, background); 1453 } 1454 1455 drawing_mode oldMode = view->DrawingMode(); 1456 1457 if ((flags & B_DEFAULT_BUTTON) != 0) { 1458 cornerBgColor = background; 1459 edgeLightColor = background; 1460 edgeShadowColor = background; 1461 1462 // Draw default button indicator 1463 // Allow a 1-pixel border of the background to come through. 1464 rect.InsetBy(1, 1); 1465 1466 view->SetHighColor(defaultIndicatorColor); 1467 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 1468 rect.InsetBy(1, 1); 1469 1470 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); 1471 rect.InsetBy(1, 1); 1472 } else { 1473 cornerBgColor = background; 1474 if ((flags & B_BLEND_FRAME) != 0) { 1475 // set the background color to transparent for the case 1476 // that we are on the desktop 1477 cornerBgColor.alpha = 0; 1478 view->SetDrawingMode(B_OP_ALPHA); 1479 } 1480 } 1481 1482 // frame colors 1483 rgb_color frameLightColor = customColor2; // _FrameLightColor(base, flags); 1484 rgb_color frameShadowColor = customColor2; // _FrameShadowColor(base, flags); 1485 edgeLightColor = background; 1486 edgeShadowColor = background; 1487 1488 // rounded corners 1489 1490 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 1491 && leftTopRadius > 0) { 1492 // draw left top rounded corner 1493 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 1494 floorf(rect.left + leftTopRadius), 1495 floorf(rect.top + leftTopRadius)); 1496 BRect cornerRect(leftTopCorner); 1497 _DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect, 1498 cornerBgColor, edgeShadowColor, frameLightColor); 1499 view->ClipToInverseRect(cornerRect); 1500 } 1501 1502 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 1503 && rightTopRadius > 0) { 1504 // draw right top rounded corner 1505 BRect rightTopCorner(floorf(rect.right - rightTopRadius), 1506 floorf(rect.top), floorf(rect.right), 1507 floorf(rect.top + rightTopRadius)); 1508 BRect cornerRect(rightTopCorner); 1509 _DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect, 1510 cornerBgColor, edgeShadowColor, edgeLightColor, 1511 frameLightColor, frameShadowColor); 1512 view->ClipToInverseRect(cornerRect); 1513 } 1514 1515 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 1516 && leftBottomRadius > 0) { 1517 // draw left bottom rounded corner 1518 BRect leftBottomCorner(floorf(rect.left), 1519 floorf(rect.bottom - leftBottomRadius), 1520 floorf(rect.left + leftBottomRadius), floorf(rect.bottom)); 1521 BRect cornerRect(leftBottomCorner); 1522 _DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect, 1523 cornerBgColor, edgeShadowColor, edgeLightColor, 1524 frameLightColor, frameShadowColor); 1525 view->ClipToInverseRect(cornerRect); 1526 } 1527 1528 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 1529 && rightBottomRadius > 0) { 1530 // draw right bottom rounded corner 1531 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius), 1532 floorf(rect.bottom - rightBottomRadius), floorf(rect.right), 1533 floorf(rect.bottom)); 1534 BRect cornerRect(rightBottomCorner); 1535 _DrawRoundCornerFrameRightBottom(view, rightBottomCorner, 1536 updateRect, cornerBgColor, edgeLightColor, frameShadowColor); 1537 view->ClipToInverseRect(cornerRect); 1538 } 1539 1540 // draw outer edge 1541 if ((flags & B_DEFAULT_BUTTON) != 0) { 1542 _DrawOuterResessedFrame(view, rect, background, 0, 0, flags, borders); 1543 } else { 1544 if ((flags & B_FOCUSED) != 0) 1545 _DrawOuterResessedFrame(view, rect, tint_color(background, 1.15), 0, 0); 1546 else 1547 _DrawOuterResessedFrame(view, rect, background, 0, 0, flags, borders); 1548 } 1549 1550 view->SetDrawingMode(oldMode); 1551 1552 // draw frame 1553 if ((flags & B_BLEND_FRAME) != 0) { 1554 drawing_mode oldDrawingMode = view->DrawingMode(); 1555 view->SetDrawingMode(B_OP_ALPHA); 1556 1557 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, frameShadowColor, 1558 borders); 1559 1560 view->SetDrawingMode(oldDrawingMode); 1561 } else { 1562 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, frameShadowColor, 1563 borders); 1564 } 1565 1566 // restore the clipping constraints of the view 1567 view->PopState(); 1568 } 1569 1570 1571 void 1572 FlatControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect, 1573 const rgb_color& base, float contrast, float brightness, uint32 flags, 1574 uint32 borders) 1575 { 1576 rgb_color edgeLightColor = tint_color(base, 1.04); 1577 rgb_color edgeShadowColor = tint_color(base, 1.04); 1578 1579 if ((flags & B_BLEND_FRAME) != 0) { 1580 // assumes the background has already been painted 1581 drawing_mode oldDrawingMode = view->DrawingMode(); 1582 view->SetDrawingMode(B_OP_ALPHA); 1583 1584 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, edgeLightColor, 1585 borders); 1586 1587 view->SetDrawingMode(oldDrawingMode); 1588 } else { 1589 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, edgeLightColor, 1590 borders); 1591 } 1592 } 1593 1594 1595 void 1596 FlatControlLook::_DrawButtonBackground(BView* view, BRect& rect, 1597 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 1598 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 1599 bool popupIndicator, uint32 flags, uint32 borders, orientation orientation) 1600 { 1601 rgb_color customColor = base; 1602 1603 if (!ShouldDraw(view, rect, updateRect)) 1604 return; 1605 1606 // save the clipping constraints of the view 1607 view->PushState(); 1608 1609 // set clipping constraints to updateRect 1610 view->ClipToRect(rect); 1611 1612 // If is a default button, set backcolor to the tab color. 1613 if ((flags & B_DEFAULT_BUTTON) != 0) 1614 { 1615 rgb_color textcolor = ui_color(B_CONTROL_TEXT_COLOR); 1616 // if the text color is too light, then make it using B_WINDOW_TAB_COLOR 1617 if (textcolor.red + textcolor.green + textcolor.blue >= 128 * 3) 1618 customColor = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.4); 1619 else 1620 customColor = ui_color(B_WINDOW_TAB_COLOR); 1621 } 1622 1623 // If the button is flat and neither activated nor otherwise highlighted 1624 // (mouse hovering or focussed), draw it flat. 1625 if ((flags & B_FLAT) != 0 1626 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 1627 && ((flags & (B_HOVER | B_FOCUSED)) == 0 1628 || (flags & B_DISABLED) != 0)) { 1629 _DrawFlatButtonBackground(view, rect, updateRect, customColor, popupIndicator, 1630 flags, borders, orientation); 1631 } else { 1632 BRegion clipping(rect); 1633 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, 1634 leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius, 1635 customColor, popupIndicator, flags, borders, orientation); 1636 } 1637 1638 // restore the clipping constraints of the view 1639 view->PopState(); 1640 } 1641 1642 1643 void 1644 FlatControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect, 1645 const BRect& updateRect, BRegion& clipping, float leftTopRadius, 1646 float rightTopRadius, float leftBottomRadius, float rightBottomRadius, 1647 const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders, 1648 orientation orientation) 1649 { 1650 // inner bevel colors 1651 rgb_color bevelLightColor = _BevelLightColor(base, flags); 1652 rgb_color bevelShadowColor = _BevelShadowColor(base, flags); 1653 1654 // button background color 1655 rgb_color buttonBgColor; 1656 1657 buttonBgColor = tint_color(base, 1.04); 1658 1659 // surface top gradient 1660 BGradientLinear fillGradient; 1661 _MakeButtonGradient(fillGradient, rect, base, flags, orientation); 1662 1663 // rounded corners 1664 1665 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 1666 && leftTopRadius > 0) { 1667 // draw left top rounded corner 1668 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 1669 floorf(rect.left + leftTopRadius - 2.0), 1670 floorf(rect.top + leftTopRadius - 2.0)); 1671 clipping.Exclude(leftTopCorner); 1672 BRect cornerRect(leftTopCorner); 1673 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, 1674 bevelLightColor, fillGradient); 1675 view->ClipToInverseRect(cornerRect); 1676 } 1677 1678 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 1679 && rightTopRadius > 0) { 1680 // draw right top rounded corner 1681 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), 1682 floorf(rect.top), floorf(rect.right), 1683 floorf(rect.top + rightTopRadius - 2.0)); 1684 clipping.Exclude(rightTopCorner); 1685 BRect cornerRect(rightTopCorner); 1686 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, 1687 updateRect, bevelLightColor, bevelShadowColor, fillGradient); 1688 view->ClipToInverseRect(cornerRect); 1689 } 1690 1691 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 1692 && leftBottomRadius > 0) { 1693 // draw left bottom rounded corner 1694 BRect leftBottomCorner(floorf(rect.left), 1695 floorf(rect.bottom - leftBottomRadius + 2.0), 1696 floorf(rect.left + leftBottomRadius - 2.0), 1697 floorf(rect.bottom)); 1698 clipping.Exclude(leftBottomCorner); 1699 BRect cornerRect(leftBottomCorner); 1700 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, 1701 updateRect, bevelLightColor, bevelShadowColor, fillGradient); 1702 view->ClipToInverseRect(cornerRect); 1703 } 1704 1705 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 1706 && rightBottomRadius > 0) { 1707 // draw right bottom rounded corner 1708 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), 1709 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), 1710 floorf(rect.bottom)); 1711 clipping.Exclude(rightBottomCorner); 1712 BRect cornerRect(rightBottomCorner); 1713 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, 1714 updateRect, bevelShadowColor, fillGradient); 1715 view->ClipToInverseRect(cornerRect); 1716 } 1717 1718 // draw inner bevel 1719 1720 if ((flags & B_ACTIVATED) != 0) { 1721 view->BeginLineArray(4); 1722 1723 // shadow along left/top borders 1724 if (borders & B_LEFT_BORDER) { 1725 view->AddLine(BPoint(rect.left, rect.top), 1726 BPoint(rect.left, rect.bottom), buttonBgColor); 1727 rect.left++; 1728 } 1729 if (borders & B_TOP_BORDER) { 1730 view->AddLine(BPoint(rect.left, rect.top), 1731 BPoint(rect.right, rect.top), buttonBgColor); 1732 rect.top++; 1733 } 1734 1735 // softer shadow along left/top borders 1736 if (borders & B_LEFT_BORDER) { 1737 view->AddLine(BPoint(rect.left, rect.top), 1738 BPoint(rect.left, rect.bottom), buttonBgColor); 1739 rect.left++; 1740 } 1741 if (borders & B_TOP_BORDER) { 1742 view->AddLine(BPoint(rect.left, rect.top), 1743 BPoint(rect.right, rect.top), buttonBgColor); 1744 rect.top++; 1745 } 1746 1747 view->EndLineArray(); 1748 } else { 1749 _DrawFrame(view, rect, 1750 buttonBgColor, buttonBgColor, 1751 buttonBgColor, buttonBgColor, 1752 buttonBgColor, buttonBgColor, borders); 1753 } 1754 1755 if (popupIndicator) { 1756 BRect indicatorRect(rect); 1757 rect.right -= kButtonPopUpIndicatorWidth; 1758 indicatorRect.left = rect.right + 3; 1759 // 2 pixels for the separator 1760 1761 // Even when depressed we want the pop-up indicator background and 1762 // separator to cover the area up to the top. 1763 if ((flags & B_ACTIVATED) != 0) 1764 indicatorRect.top--; 1765 1766 // draw the separator 1767 rgb_color separatorBaseColor = base; 1768 if ((flags & B_ACTIVATED) != 0) 1769 separatorBaseColor = tint_color(base, B_DARKEN_1_TINT); 1770 1771 // rgb_color separatorLightColor = tint_color(base, B_DARKEN_1_TINT); 1772 rgb_color separatorShadowColor = tint_color(base, B_DARKEN_1_TINT); 1773 1774 view->BeginLineArray(2); 1775 1776 view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top), 1777 BPoint(indicatorRect.left - 2, indicatorRect.bottom), 1778 separatorShadowColor); 1779 view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top), 1780 BPoint(indicatorRect.left - 1, indicatorRect.bottom), 1781 separatorShadowColor); 1782 1783 view->EndLineArray(); 1784 1785 // draw background and pop-up marker 1786 _DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect, kRadius, rightTopRadius, 1787 kRadius, rightBottomRadius, base, flags, 0); 1788 1789 if ((flags & B_ACTIVATED) != 0) 1790 indicatorRect.top++; 1791 1792 _DrawPopUpMarker(view, indicatorRect, ui_color(B_MENU_ITEM_TEXT_COLOR), flags); 1793 } 1794 1795 // fill in the background 1796 view->FillRect(rect, fillGradient); 1797 } 1798 1799 1800 void 1801 FlatControlLook::_DrawPopUpMarker(BView* view, const BRect& rect, 1802 const rgb_color& base, uint32 flags) 1803 { 1804 BPoint center(roundf((rect.left + rect.right) / 2.0), 1805 roundf((rect.top + rect.bottom) / 2.0)); 1806 BPoint triangle[3]; 1807 triangle[0] = center + BPoint(-2.5, -0.5); 1808 triangle[1] = center + BPoint(2.5, -0.5); 1809 triangle[2] = center + BPoint(0.0, 2.0); 1810 1811 uint32 viewFlags = view->Flags(); 1812 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); 1813 1814 rgb_color markColor; 1815 if ((flags & B_DISABLED) != 0) 1816 markColor = tint_color(base, 1.0); 1817 else 1818 markColor = tint_color(base, 1.0); 1819 1820 view->SetHighColor(markColor); 1821 view->FillTriangle(triangle[0], triangle[1], triangle[2]); 1822 1823 view->SetFlags(viewFlags); 1824 } 1825 1826 1827 void 1828 FlatControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect, 1829 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 1830 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 1831 bool popupIndicator, uint32 flags) 1832 { 1833 if (!ShouldDraw(view, rect, updateRect)) 1834 return; 1835 1836 rgb_color indicatorColor; 1837 1838 if (base.IsDark()) 1839 indicatorColor = tint_color(base, 0.95); 1840 else 1841 indicatorColor = tint_color(base, 1.05); 1842 1843 if (popupIndicator) { 1844 const float indicatorWidth = ComposeSpacing(kButtonPopUpIndicatorWidth); 1845 const float spacing = (indicatorWidth <= 11.0f) ? 1.0f : roundf(indicatorWidth / 11.0f); 1846 1847 BRect leftRect(rect); 1848 leftRect.right -= indicatorWidth - spacing; 1849 1850 BRect rightRect(rect); 1851 rightRect.left = rightRect.right - (indicatorWidth - spacing * 2); 1852 1853 _DrawMenuFieldBackgroundInside(view, leftRect, updateRect, leftTopRadius, 0.0f, 1854 leftBottomRadius, 0.0f, base, flags, B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER); 1855 1856 _DrawMenuFieldBackgroundInside(view, rightRect, updateRect, 0.0f, rightTopRadius, 0.0f, 1857 rightBottomRadius, indicatorColor, flags, 1858 B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER); 1859 1860 _DrawPopUpMarker(view, rightRect, ui_color(B_MENU_ITEM_TEXT_COLOR), flags); 1861 1862 // draw a line on the left of the popup frame 1863 rgb_color bevelShadowColor = tint_color(indicatorColor, 1.1); 1864 if (base.IsDark()) 1865 bevelShadowColor = tint_color(indicatorColor, 0.9); 1866 view->SetHighColor(bevelShadowColor); 1867 1868 BPoint leftTopCorner(floorf(rightRect.left - spacing), floorf(rightRect.top - spacing)); 1869 BPoint leftBottomCorner(floorf(rightRect.left - spacing), 1870 floorf(rightRect.bottom + spacing)); 1871 1872 for (float i = 0; i < spacing; i++) 1873 view->StrokeLine(leftTopCorner + BPoint(i, 0), leftBottomCorner + BPoint(i, 0)); 1874 1875 rect = leftRect; 1876 } else { 1877 _DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius, 1878 rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags, 1879 B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER); 1880 } 1881 } 1882 1883 1884 void 1885 FlatControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect, 1886 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 1887 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 1888 uint32 flags, uint32 borders) 1889 { 1890 if (!ShouldDraw(view, rect, updateRect)) 1891 return; 1892 1893 // save the clipping constraints of the view 1894 view->PushState(); 1895 1896 // set clipping constraints to rect 1897 view->ClipToRect(rect); 1898 1899 // frame colors 1900 rgb_color frameLightColor = _FrameLightColor(base, flags); 1901 rgb_color frameShadowColor = _FrameShadowColor(base, flags); 1902 1903 // indicator background color 1904 rgb_color indicatorBase; 1905 if ((borders & B_LEFT_BORDER) != 0) 1906 indicatorBase = base; 1907 else { 1908 if ((flags & B_DISABLED) != 0) 1909 indicatorBase = tint_color(base, 1.05); 1910 else 1911 indicatorBase = tint_color(base, 1); 1912 } 1913 1914 // bevel colors 1915 rgb_color cornerColor = tint_color(indicatorBase, 1.0); 1916 rgb_color bevelColor1 = tint_color(indicatorBase, 1.0); 1917 rgb_color bevelColor2 = tint_color(indicatorBase, 1.0); 1918 rgb_color bevelColor3 = tint_color(indicatorBase, 1.0); 1919 1920 if ((flags & B_DISABLED) != 0) { 1921 cornerColor = tint_color(indicatorBase, 1.0); 1922 bevelColor1 = tint_color(indicatorBase, 1.0); 1923 bevelColor2 = tint_color(indicatorBase, 1.0); 1924 bevelColor3 = tint_color(indicatorBase, 1.0); 1925 } else { 1926 cornerColor = tint_color(indicatorBase, 1.0); 1927 bevelColor1 = tint_color(indicatorBase, 1.0); 1928 bevelColor2 = tint_color(indicatorBase, 1.0); 1929 bevelColor3 = tint_color(indicatorBase, 1.0); 1930 } 1931 1932 // surface top gradient 1933 BGradientLinear fillGradient; 1934 _MakeButtonGradient(fillGradient, rect, indicatorBase, flags); 1935 1936 // rounded corners 1937 1938 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 1939 && leftTopRadius > 0) { 1940 // draw left top rounded corner 1941 BRect leftTopCorner(floorf(rect.left), floorf(rect.top), 1942 floorf(rect.left + leftTopRadius - 2.0), 1943 floorf(rect.top + leftTopRadius - 2.0)); 1944 BRect cornerRect(leftTopCorner); 1945 1946 view->PushState(); 1947 view->ClipToRect(cornerRect); 1948 1949 BRect ellipseRect(leftTopCorner); 1950 ellipseRect.InsetBy(-0.0, -0.0); 1951 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 1952 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 1953 1954 // draw the frame (again) 1955 view->SetHighColor(frameLightColor); 1956 view->FillEllipse(ellipseRect); 1957 1958 // draw the bevel and background 1959 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, 1960 bevelColor1, fillGradient); 1961 1962 view->PopState(); 1963 view->ClipToInverseRect(cornerRect); 1964 } 1965 1966 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 1967 && rightTopRadius > 0) { 1968 // draw right top rounded corner 1969 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), 1970 floorf(rect.top), floorf(rect.right), 1971 floorf(rect.top + rightTopRadius - 2.0)); 1972 BRect cornerRect(rightTopCorner); 1973 1974 view->PushState(); 1975 view->ClipToRect(cornerRect); 1976 1977 BRect ellipseRect(rightTopCorner); 1978 ellipseRect.InsetBy(-0.0, -0.0); 1979 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 1980 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; 1981 1982 // draw the frame (again) 1983 if (frameLightColor == frameShadowColor) { 1984 view->SetHighColor(frameLightColor); 1985 view->FillEllipse(ellipseRect); 1986 } else { 1987 BGradientLinear gradient; 1988 gradient.AddColor(frameLightColor, 0); 1989 gradient.AddColor(frameShadowColor, 255); 1990 gradient.SetStart(rightTopCorner.LeftTop()); 1991 gradient.SetEnd(rightTopCorner.RightBottom()); 1992 view->FillEllipse(ellipseRect, gradient); 1993 } 1994 1995 // draw the bevel and background 1996 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect, 1997 bevelColor1, bevelColor3, fillGradient); 1998 1999 view->PopState(); 2000 view->ClipToInverseRect(cornerRect); 2001 } 2002 2003 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2004 && leftBottomRadius > 0) { 2005 // draw left bottom rounded corner 2006 BRect leftBottomCorner(floorf(rect.left), 2007 floorf(rect.bottom - leftBottomRadius + 2.0), 2008 floorf(rect.left + leftBottomRadius - 2.0), 2009 floorf(rect.bottom)); 2010 BRect cornerRect(leftBottomCorner); 2011 2012 view->PushState(); 2013 view->ClipToRect(cornerRect); 2014 2015 BRect ellipseRect(leftBottomCorner); 2016 ellipseRect.InsetBy(-0.0, -0.0); 2017 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; 2018 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 2019 2020 // draw the frame (again) 2021 if (frameLightColor == frameShadowColor) { 2022 view->SetHighColor(frameLightColor); 2023 view->FillEllipse(ellipseRect); 2024 } else { 2025 BGradientLinear gradient; 2026 gradient.AddColor(frameLightColor, 0); 2027 gradient.AddColor(frameShadowColor, 255); 2028 gradient.SetStart(leftBottomCorner.LeftTop()); 2029 gradient.SetEnd(leftBottomCorner.RightBottom()); 2030 view->FillEllipse(ellipseRect, gradient); 2031 } 2032 2033 // draw the bevel and background 2034 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, 2035 updateRect, bevelColor2, bevelColor3, fillGradient); 2036 2037 view->PopState(); 2038 view->ClipToInverseRect(cornerRect); 2039 } 2040 2041 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 2042 && rightBottomRadius > 0) { 2043 // draw right bottom rounded corner 2044 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), 2045 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), 2046 floorf(rect.bottom)); 2047 BRect cornerRect(rightBottomCorner); 2048 2049 view->PushState(); 2050 view->ClipToRect(cornerRect); 2051 2052 BRect ellipseRect(rightBottomCorner); 2053 ellipseRect.InsetBy(-0.0, -0.0); 2054 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; 2055 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; 2056 2057 // draw the frame (again) 2058 view->SetHighColor(frameShadowColor); 2059 view->FillEllipse(ellipseRect); 2060 2061 // draw the bevel and background 2062 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, 2063 updateRect, bevelColor3, fillGradient); 2064 2065 view->PopState(); 2066 view->ClipToInverseRect(cornerRect); 2067 } 2068 2069 // fill in the background 2070 view->FillRect(rect, fillGradient); 2071 2072 // restore the clipping constraints of the view 2073 view->PopState(); 2074 } 2075 2076 rgb_color 2077 FlatControlLook::_EdgeLightColor(const rgb_color& base, float contrast, 2078 float brightness, uint32 flags) 2079 { 2080 return base; 2081 } 2082 2083 2084 rgb_color 2085 FlatControlLook::_EdgeShadowColor(const rgb_color& base, float contrast, 2086 float brightness, uint32 flags) 2087 { 2088 return base; 2089 } 2090 2091 2092 2093 2094 rgb_color 2095 FlatControlLook::_BevelLightColor(const rgb_color& base, uint32 flags) 2096 { 2097 rgb_color bevelLightColor = tint_color(base, 1.0); 2098 return bevelLightColor; 2099 } 2100 2101 2102 rgb_color 2103 FlatControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags) 2104 { 2105 rgb_color bevelShadowColor = tint_color(base, 1.0); 2106 return bevelShadowColor; 2107 } 2108 2109 2110 void 2111 FlatControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect, 2112 const rgb_color& base, float topTint, float bottomTint, 2113 orientation orientation) const 2114 { 2115 gradient.AddColor(tint_color(base, 0.97), 0); 2116 gradient.AddColor(tint_color(base, 1.0), 255); 2117 gradient.SetStart(rect.LeftTop()); 2118 if (orientation == B_HORIZONTAL) 2119 gradient.SetEnd(rect.LeftBottom()); 2120 else 2121 gradient.SetEnd(rect.RightTop()); 2122 } 2123 2124 2125 void 2126 FlatControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect, 2127 const rgb_color& base, float topTint, float middle1Tint, 2128 float middle2Tint, float bottomTint, 2129 orientation orientation) const 2130 { 2131 gradient.AddColor(tint_color(base, topTint), 0); 2132 gradient.AddColor(tint_color(base, bottomTint), 255); 2133 gradient.SetStart(rect.LeftTop()); 2134 if (orientation == B_HORIZONTAL) 2135 gradient.SetEnd(rect.LeftBottom()); 2136 else 2137 gradient.SetEnd(rect.RightTop()); 2138 } 2139 2140 2141 void 2142 FlatControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect, 2143 const rgb_color& base, uint32 flags, orientation orientation) const 2144 { 2145 float topTint = 0.99; 2146 float middleTint1 = 0.99; 2147 float middleTint2 = 1.0; 2148 float bottomTint = 1.05; 2149 2150 if ((flags & B_ACTIVATED) != 0) { 2151 topTint = 1.11; 2152 bottomTint = 1.08; 2153 } 2154 2155 if ((flags & B_DISABLED) != 0) { 2156 topTint = (topTint + B_NO_TINT) / 2; 2157 middleTint1 = (middleTint1 + B_NO_TINT) / 2; 2158 middleTint2 = (middleTint2 + B_NO_TINT) / 2; 2159 bottomTint = (bottomTint + B_NO_TINT) / 2; 2160 } else if ((flags & B_HOVER) != 0) { 2161 topTint = 1.0; 2162 middleTint1 = 1.0; 2163 middleTint2 = 1.0; 2164 bottomTint = 1.0; 2165 } 2166 2167 if ((flags & B_ACTIVATED) != 0) { 2168 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); 2169 } else { 2170 _MakeGlossyGradient(gradient, rect, base, topTint, middleTint1, 2171 middleTint2, bottomTint, orientation); 2172 } 2173 } 2174 2175 2176 } // bprivate 2177 2178 2179 extern "C" BControlLook* (instantiate_control_look)(image_id id) 2180 { 2181 return new (std::nothrow)BPrivate::FlatControlLook(); 2182 } 2183