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