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