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(): HaikuControlLook() 39 { 40 } 41 42 43 FlatControlLook::~FlatControlLook() 44 { 45 } 46 47 48 // #pragma mark - 49 50 51 void 52 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, 53 const rgb_color& base, const rgb_color& background, uint32 flags, 54 uint32 borders) 55 { 56 _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, base, 57 background, 1.0, 1.0, flags, borders); 58 } 59 60 61 void 62 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, 63 float radius, const rgb_color& base, const rgb_color& background, uint32 flags, 64 uint32 borders) 65 { 66 _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, 67 base, background, 1.0, 1.0, flags, borders); 68 } 69 70 71 void 72 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, 73 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 74 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 75 const rgb_color& background, uint32 flags, 76 uint32 borders) 77 { 78 _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 79 1.5f, 1.5f, base, background, 80 1.0, 1.0, flags, borders); 81 } 82 83 84 void 85 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, 86 const BRect& updateRect, const rgb_color& base, uint32 flags, 87 uint32 borders, orientation orientation) 88 { 89 _DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, 90 base, false, flags, borders, orientation); 91 } 92 93 94 void 95 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, 96 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, 97 uint32 borders, orientation orientation) 98 { 99 _DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, 100 base, false, flags, borders, orientation); 101 } 102 103 104 void 105 FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, 106 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 107 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 108 uint32 flags, uint32 borders, orientation orientation) 109 { 110 _DrawButtonBackground(view, rect, updateRect, 1.5f, 111 1.5f, 1.5f, 1.5f, base, false, flags, 112 borders, orientation); 113 } 114 115 116 void 117 FlatControlLook::DrawMenuBarBackground(BView* view, BRect& rect, 118 const BRect& updateRect, const rgb_color& base, uint32 flags, 119 uint32 borders) 120 { 121 if (!rect.IsValid() || !rect.Intersects(updateRect)) 122 return; 123 124 // the surface edges 125 126 // colors 127 float topTint = 1.0; 128 float bottomTint = 1.16; 129 130 rgb_color customColor = base; 131 bool isEnabled = (flags & B_ACTIVATED) != 0; 132 133 if (isEnabled) { 134 customColor = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.0); 135 rgb_color bevelColor1 = tint_color(customColor, 1.0); 136 rgb_color bevelColor2 = tint_color(customColor, 1.0); 137 138 topTint = 1.0; 139 bottomTint = 1.0; 140 141 _DrawFrame(view, rect, 142 bevelColor1, bevelColor1, 143 bevelColor2, bevelColor2, 144 borders & B_TOP_BORDER); 145 } else { 146 rgb_color cornerColor = tint_color(customColor, 1.0); 147 rgb_color bevelColorTop = tint_color(customColor, 1.0); 148 rgb_color bevelColorLeft = tint_color(customColor, 1.0); 149 rgb_color bevelColorRightBottom = tint_color(customColor, 1.0); 150 151 topTint = 1.0; 152 bottomTint = 1.0; 153 154 _DrawFrame(view, rect, 155 bevelColorLeft, bevelColorTop, 156 bevelColorRightBottom, bevelColorRightBottom, 157 cornerColor, cornerColor, 158 borders); 159 } 160 161 // draw surface top 162 _FillGradient(view, rect, customColor, topTint, bottomTint); 163 } 164 165 166 void 167 FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 168 const BRect& updateRect, const rgb_color& base, 169 const rgb_color& background, uint32 flags, uint32 borders) 170 { 171 _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, base, 172 background, 1.0, 1.0, flags, borders); 173 } 174 175 176 void 177 FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 178 const BRect& updateRect, float radius, const rgb_color& base, 179 const rgb_color& background, uint32 flags, uint32 borders) 180 { 181 _DrawButtonFrame(view, rect, updateRect, radius, radius, 1.5f, 1.5f, 182 base, background, 1.0, 1.0, flags, borders); 183 } 184 185 186 void 187 FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, 188 const BRect& updateRect, float leftTopRadius, 189 float rightTopRadius, float leftBottomRadius, 190 float rightBottomRadius, const rgb_color& base, 191 const rgb_color& background, uint32 flags, uint32 borders) 192 { 193 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius, 194 1.5f, 1.5f, base, background, 1.0, 1.0, 195 flags, borders); 196 } 197 198 199 void 200 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 201 const BRect& updateRect, const rgb_color& base, bool popupIndicator, 202 uint32 flags) 203 { 204 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, 205 1.5f, 1.5f, 1.5f, 1.5f, base, popupIndicator, flags); 206 } 207 208 209 void 210 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 211 const BRect& updateRect, const rgb_color& base, uint32 flags, 212 uint32 borders) 213 { 214 _DrawMenuFieldBackgroundInside(view, rect, updateRect, 215 1.5f, 1.5f, 1.5f, 1.5f, base, flags, borders); 216 } 217 218 219 void 220 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 221 const BRect& updateRect, float radius, const rgb_color& base, 222 bool popupIndicator, uint32 flags) 223 { 224 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius, 225 radius, radius, base, popupIndicator, flags); 226 } 227 228 229 void 230 FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, 231 const BRect& updateRect, float leftTopRadius, float rightTopRadius, 232 float leftBottomRadius, float rightBottomRadius, const rgb_color& base, 233 bool popupIndicator, uint32 flags) 234 { 235 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius, 236 rightTopRadius, leftBottomRadius, rightBottomRadius, base, 237 popupIndicator, flags); 238 } 239 240 241 void 242 HaikuControlLook::DrawMenuBackground(BView* view, BRect& rect, 243 const BRect& updateRect, const rgb_color& base, uint32 flags, 244 uint32 borders) 245 { 246 if (!rect.IsValid() || !rect.Intersects(updateRect)) 247 return; 248 249 // surface top color 250 rgb_color background = tint_color(base, 0.8); 251 252 // inner bevel colors 253 rgb_color bevelColor; 254 255 256 if ((flags & B_DISABLED) != 0) { 257 bevelColor = tint_color(background, 1.03); 258 } else { 259 bevelColor = tint_color(background, 0.5); 260 } 261 262 // draw inner bevel 263 _DrawFrame(view, rect, 264 bevelColor, bevelColor, 265 bevelColor, bevelColor, 266 borders); 267 268 // draw surface top 269 view->SetHighColor(background); 270 view->FillRect(rect); 271 } 272 273 274 void 275 FlatControlLook::DrawMenuItemBackground(BView* view, BRect& rect, 276 const BRect& updateRect, const rgb_color& base, uint32 flags, 277 uint32 borders) 278 { 279 if (!rect.IsValid() || !rect.Intersects(updateRect)) 280 return; 281 282 // surface edges 283 float topTint; 284 float bottomTint; 285 rgb_color selectedColor = base; 286 287 if ((flags & B_ACTIVATED) != 0) { 288 topTint = 0.94; 289 bottomTint = 1.1; 290 } else if ((flags & B_DISABLED) != 0) { 291 topTint = 1.0; 292 bottomTint = 1.0; 293 } else { 294 topTint = 0.95; 295 bottomTint = 1.1; 296 } 297 298 //rgb_color bevelLightColor = tint_color(selectedColor, topTint); 299 rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint); 300 301 // draw surface edges 302 _DrawFrame(view, rect, 303 bevelShadowColor, bevelShadowColor, 304 bevelShadowColor, bevelShadowColor, 305 borders); 306 307 // draw surface top 308 view->SetLowColor(selectedColor); 309 _FillGradient(view, rect, selectedColor, topTint, bottomTint); 310 } 311 312 313 void 314 HaikuControlLook::DrawScrollBarBorder(BView* view, BRect rect, 315 const BRect& updateRect, const rgb_color& base, uint32 flags, 316 orientation orientation) 317 { 318 if (!rect.IsValid() || !rect.Intersects(updateRect)) 319 return; 320 321 view->PushState(); 322 323 // set clipping constraints to updateRect 324 BRegion clipping(updateRect); 325 view->ConstrainClippingRegion(&clipping); 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 HaikuControlLook::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 (!rect.IsValid() || !rect.Intersects(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 BRegion buttonRegion(rect); 398 view->ConstrainClippingRegion(&buttonRegion); 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 BRegion clipping(updateRect); 408 view->ConstrainClippingRegion(&clipping); 409 } 410 411 412 void 413 HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, 414 BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, 415 orientation orientation) 416 { 417 DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); 418 DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); 419 } 420 421 422 void 423 HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect, 424 const BRect& updateRect, const rgb_color& base, uint32 flags, 425 orientation orientation) 426 { 427 if (!rect.IsValid() || !rect.Intersects(updateRect)) 428 return; 429 430 view->PushState(); 431 432 // set clipping constraints to updateRect 433 BRegion clipping(updateRect); 434 view->ConstrainClippingRegion(&clipping); 435 436 bool isEnabled = (flags & B_DISABLED) == 0; 437 438 // fill background, we'll draw arrows and thumb on top 439 view->SetDrawingMode(B_OP_COPY); 440 441 float gradient1Tint; 442 float gradient2Tint; 443 444 if (isEnabled) { 445 gradient1Tint = 1.08; 446 gradient2Tint = 0.99; 447 } else { 448 gradient1Tint = 1.08; 449 gradient2Tint = 0.99; 450 } 451 452 if (orientation == B_HORIZONTAL) { 453 // dark vertical line on left edge 454 // fill 455 if (rect.Width() >= 0) { 456 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, 457 orientation); 458 } 459 } else { 460 // dark vertical line on top edge 461 // fill 462 if (rect.Height() >= 0) { 463 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, 464 orientation); 465 } 466 } 467 468 view->PopState(); 469 } 470 471 472 void 473 FlatControlLook::DrawScrollBarThumb(BView* view, BRect& rect, 474 const BRect& updateRect, const rgb_color& base, uint32 flags, 475 orientation orientation, uint32 knobStyle) 476 { 477 if (!rect.IsValid() || !rect.Intersects(updateRect)) 478 return; 479 480 view->PushState(); 481 482 // set clipping constraints to updateRect 483 BRegion clipping(updateRect); 484 view->ConstrainClippingRegion(&clipping); 485 486 // flags 487 bool isEnabled = (flags & B_DISABLED) == 0; 488 489 // colors 490 rgb_color thumbColor = ui_color(B_SCROLL_BAR_THUMB_COLOR); 491 rgb_color base_panel = ui_color(B_PANEL_BACKGROUND_COLOR); 492 493 rgb_color light, dark, dark1, dark2; 494 light = tint_color(base_panel, B_DARKEN_1_TINT); 495 dark = tint_color(base_panel, B_DARKEN_1_TINT); 496 dark1 = tint_color(base_panel, B_DARKEN_1_TINT); 497 dark2 = tint_color(base_panel, B_DARKEN_1_TINT); 498 499 // draw thumb over background 500 view->SetDrawingMode(B_OP_OVER); 501 view->SetHighColor(dark1); 502 503 // draw scroll thumb 504 if (isEnabled) { 505 // fill the clickable surface of the thumb 506 // set clipping constraints to updateRect 507 BRegion clipping(updateRect); 508 view->ConstrainClippingRegion(&clipping); 509 DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation); 510 rect.InsetBy(3, 3); 511 view->SetHighColor(base_panel); 512 view->FillRect(rect); 513 514 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, 4.0f, 4.0f, 4.0f, 4.0f, thumbColor, false, flags, B_ALL_BORDERS, orientation); 515 516 } else { 517 DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation); 518 } 519 520 knobStyle = B_KNOB_LINES; //Hard set of the knobstyle 521 522 // draw knob style 523 if (knobStyle != B_KNOB_NONE && isEnabled) { 524 rgb_color knobLight = isEnabled 525 ? tint_color(thumbColor, 0.85) 526 : tint_color(base_panel, 1.05); 527 rgb_color knobDark = isEnabled 528 ? tint_color(thumbColor, 1.35) 529 : tint_color(base_panel, 1.05); 530 531 if (knobStyle == B_KNOB_DOTS) { 532 // draw dots on the scroll bar thumb 533 float hcenter = rect.left + rect.Width() / 2; 534 float vmiddle = rect.top + rect.Height() / 2; 535 BRect knob(hcenter, vmiddle, hcenter, vmiddle); 536 537 if (orientation == B_HORIZONTAL) { 538 view->SetHighColor(knobDark); 539 view->FillRect(knob); 540 view->SetHighColor(knobLight); 541 view->FillRect(knob.OffsetByCopy(1, 1)); 542 543 float spacer = rect.Height(); 544 545 if (rect.left + 3 < hcenter - spacer) { 546 view->SetHighColor(knobDark); 547 view->FillRect(knob.OffsetByCopy(-spacer, 0)); 548 view->SetHighColor(knobLight); 549 view->FillRect(knob.OffsetByCopy(-spacer + 1, 1)); 550 } 551 552 if (rect.right - 3 > hcenter + spacer) { 553 view->SetHighColor(knobDark); 554 view->FillRect(knob.OffsetByCopy(spacer, 0)); 555 view->SetHighColor(knobLight); 556 view->FillRect(knob.OffsetByCopy(spacer + 1, 1)); 557 } 558 } else { 559 // B_VERTICAL 560 view->SetHighColor(knobDark); 561 view->FillRect(knob); 562 view->SetHighColor(knobLight); 563 view->FillRect(knob.OffsetByCopy(1, 1)); 564 565 float spacer = rect.Width(); 566 567 if (rect.top + 3 < vmiddle - spacer) { 568 view->SetHighColor(knobDark); 569 view->FillRect(knob.OffsetByCopy(0, -spacer)); 570 view->SetHighColor(knobLight); 571 view->FillRect(knob.OffsetByCopy(1, -spacer + 1)); 572 } 573 574 if (rect.bottom - 3 > vmiddle + spacer) { 575 view->SetHighColor(knobDark); 576 view->FillRect(knob.OffsetByCopy(0, spacer)); 577 view->SetHighColor(knobLight); 578 view->FillRect(knob.OffsetByCopy(1, spacer + 1)); 579 } 580 } 581 } else if (knobStyle == B_KNOB_LINES && isEnabled) { 582 // draw lines on the scroll bar thumb 583 if (orientation == B_HORIZONTAL) { 584 float middle = rect.Width() / 2; 585 586 view->BeginLineArray(6); 587 view->AddLine( 588 BPoint(rect.left + middle - 3, rect.top + 2), 589 BPoint(rect.left + middle - 3, rect.bottom - 2), 590 knobDark); 591 view->AddLine( 592 BPoint(rect.left + middle, rect.top + 2), 593 BPoint(rect.left + middle, rect.bottom - 2), 594 knobDark); 595 view->AddLine( 596 BPoint(rect.left + middle + 3, rect.top + 2), 597 BPoint(rect.left + middle + 3, rect.bottom - 2), 598 knobDark); 599 view->AddLine( 600 BPoint(rect.left + middle - 2, rect.top + 2), 601 BPoint(rect.left + middle - 2, rect.bottom - 2), 602 knobLight); 603 view->AddLine( 604 BPoint(rect.left + middle + 1, rect.top + 2), 605 BPoint(rect.left + middle + 1, rect.bottom - 2), 606 knobLight); 607 view->AddLine( 608 BPoint(rect.left + middle + 4, rect.top + 2), 609 BPoint(rect.left + middle + 4, rect.bottom - 2), 610 knobLight); 611 view->EndLineArray(); 612 } else { 613 // B_VERTICAL 614 float middle = rect.Height() / 2; 615 616 view->BeginLineArray(6); 617 view->AddLine( 618 BPoint(rect.left + 2, rect.top + middle - 3), 619 BPoint(rect.right - 2, rect.top + middle - 3), 620 knobDark); 621 view->AddLine( 622 BPoint(rect.left + 2, rect.top + middle), 623 BPoint(rect.right - 2, rect.top + middle), 624 knobDark); 625 view->AddLine( 626 BPoint(rect.left + 2, rect.top + middle + 3), 627 BPoint(rect.right - 2, rect.top + middle + 3), 628 knobDark); 629 view->AddLine( 630 BPoint(rect.left + 2, rect.top + middle - 2), 631 BPoint(rect.right - 2, rect.top + middle - 2), 632 knobLight); 633 view->AddLine( 634 BPoint(rect.left + 2, rect.top + middle + 1), 635 BPoint(rect.right - 2, rect.top + middle + 1), 636 knobLight); 637 view->AddLine( 638 BPoint(rect.left + 2, rect.top + middle + 4), 639 BPoint(rect.right - 2, rect.top + middle + 4), 640 knobLight); 641 view->EndLineArray(); 642 } 643 } 644 } 645 646 view->PopState(); 647 } 648 649 650 void 651 HaikuControlLook::DrawScrollViewFrame(BView* view, BRect& rect, 652 const BRect& updateRect, BRect verticalScrollBarFrame, 653 BRect horizontalScrollBarFrame, const rgb_color& base, 654 border_style borderStyle, uint32 flags, uint32 _borders) 655 { 656 // calculate scroll corner rect before messing with the "rect" 657 BRect scrollCornerFillRect(rect.right, rect.bottom, 658 rect.right, rect.bottom); 659 660 if (horizontalScrollBarFrame.IsValid()) 661 scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1; 662 663 if (verticalScrollBarFrame.IsValid()) 664 scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1; 665 666 if (borderStyle == B_NO_BORDER) { 667 if (scrollCornerFillRect.IsValid()) { 668 view->SetHighColor(base); 669 view->FillRect(scrollCornerFillRect); 670 } 671 return; 672 } 673 674 bool excludeScrollCorner = borderStyle == B_FANCY_BORDER 675 && horizontalScrollBarFrame.IsValid() 676 && verticalScrollBarFrame.IsValid(); 677 678 uint32 borders = _borders; 679 if (excludeScrollCorner) { 680 rect.bottom = horizontalScrollBarFrame.top; 681 rect.right = verticalScrollBarFrame.left; 682 borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER); 683 } 684 685 rgb_color scrollbarFrameColor = tint_color(base, 1.2); 686 687 if (borderStyle == B_FANCY_BORDER) 688 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); 689 690 if ((flags & B_FOCUSED) != 0) { 691 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 692 scrollbarFrameColor, scrollbarFrameColor, borders); 693 } else { 694 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, 695 scrollbarFrameColor, scrollbarFrameColor, borders); 696 } 697 698 if (excludeScrollCorner) { 699 horizontalScrollBarFrame.InsetBy(-1, -1); 700 701 // do not overdraw the top edge 702 horizontalScrollBarFrame.top += 2; 703 borders = _borders; 704 borders &= ~B_TOP_BORDER; 705 _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base, 706 1.0, 1.0, flags, borders); 707 _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor, 708 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, 709 borders); 710 711 verticalScrollBarFrame.InsetBy(-1, -1); 712 713 // do not overdraw the left edge 714 verticalScrollBarFrame.left += 2; 715 borders = _borders; 716 borders &= ~B_LEFT_BORDER; 717 _DrawOuterResessedFrame(view, verticalScrollBarFrame, base, 718 1.0, 1.0, flags, borders); 719 _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor, 720 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, 721 borders); 722 723 // exclude recessed frame 724 scrollCornerFillRect.top++; 725 scrollCornerFillRect.left++; 726 } 727 728 if (scrollCornerFillRect.IsValid()) { 729 view->SetHighColor(base); 730 view->FillRect(scrollCornerFillRect); 731 } 732 } 733 734 735 rgb_color 736 HaikuControlLook::SliderBarColor(const rgb_color& base) 737 { 738 rgb_color customColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.05); 739 // if the color BACKGROUND used is too dark, then make it lighter using the 740 // same as B_CONTROL_TEXT_COLOR 741 if (base.red + base.green + base.blue <= 128 * 3) { 742 customColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 0.95); 743 } 744 745 return customColor; 746 } 747 748 749 void 750 HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 751 const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor, 752 float sliderScale, uint32 flags, orientation orientation) 753 { 754 if (!rect.IsValid() || !rect.Intersects(updateRect)) 755 return; 756 757 // save the clipping constraints of the view 758 view->PushState(); 759 760 // separate the bar in two sides 761 float sliderPosition; 762 BRect leftBarSide = rect; 763 BRect rightBarSide = rect; 764 765 if (orientation == B_HORIZONTAL) { 766 sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2) 767 * sliderScale); 768 leftBarSide.right = sliderPosition - 1; 769 rightBarSide.left = sliderPosition; 770 } else { 771 // NOTE: position is reverse of coords 772 sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2) 773 * (1.0 - sliderScale)); 774 leftBarSide.top = sliderPosition; 775 rightBarSide.bottom = sliderPosition - 1; 776 } 777 778 // fill the background for the corners, exclude the middle bar for now 779 BRegion region(rect); 780 region.Exclude(rightBarSide); 781 view->ConstrainClippingRegion(®ion); 782 783 view->PushState(); 784 785 DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags, 786 orientation); 787 788 view->PopState(); 789 790 region.Set(rect); 791 region.Exclude(leftBarSide); 792 view->ConstrainClippingRegion(®ion); 793 794 view->PushState(); 795 796 DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags, 797 orientation); 798 799 view->PopState(); 800 801 // restore the clipping constraints of the view 802 view->PopState(); 803 } 804 805 806 void 807 HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, 808 const rgb_color& base, rgb_color fillColor, uint32 flags, 809 orientation orientation) 810 { 811 if (!rect.IsValid() || !rect.Intersects(updateRect)) 812 return; 813 814 // separate the rect into corners 815 BRect leftCorner(rect); 816 BRect rightCorner(rect); 817 BRect barRect(rect); 818 819 if (orientation == B_HORIZONTAL) { 820 leftCorner.right = leftCorner.left + leftCorner.Height(); 821 rightCorner.left = rightCorner.right - rightCorner.Height(); 822 barRect.left += ceilf(barRect.Height() / 2); 823 barRect.right -= ceilf(barRect.Height() / 2); 824 } else { 825 leftCorner.bottom = leftCorner.top + leftCorner.Width(); 826 rightCorner.top = rightCorner.bottom - rightCorner.Width(); 827 barRect.top += ceilf(barRect.Width() / 2); 828 barRect.bottom -= ceilf(barRect.Width() / 2); 829 } 830 831 // fill the background for the corners, exclude the middle bar for now 832 BRegion region(rect); 833 region.Exclude(barRect); 834 view->ConstrainClippingRegion(®ion); 835 836 if ((flags & B_BLEND_FRAME) == 0) { 837 view->SetHighColor(base); 838 view->FillRect(rect); 839 } 840 841 // figure out the tints to be used 842 float edgeLightTint; 843 float edgeShadowTint; 844 float frameLightTint; 845 float frameShadowTint; 846 float fillLightTint; 847 float fillShadowTint; 848 uint8 edgeLightAlpha; 849 uint8 edgeShadowAlpha; 850 uint8 frameLightAlpha; 851 uint8 frameShadowAlpha; 852 853 if ((flags & B_DISABLED) != 0) { 854 edgeLightTint = 1.0; 855 edgeShadowTint = 1.0; 856 frameLightTint = 1.05; 857 frameShadowTint = 1.05; 858 fillLightTint = 0.8; 859 fillShadowTint = 0.8; 860 edgeLightAlpha = 12; 861 edgeShadowAlpha = 12; 862 frameLightAlpha = 40; 863 frameShadowAlpha = 45; 864 865 fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6); 866 fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6); 867 fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6); 868 } else { 869 edgeLightTint = 1.0; 870 edgeShadowTint = 1.0; 871 frameLightTint = 1.20; 872 frameShadowTint = 1.20; 873 fillLightTint = 0.9; 874 fillShadowTint = 0.9; 875 edgeLightAlpha = 15; 876 edgeShadowAlpha = 15; 877 frameLightAlpha = 102; 878 frameShadowAlpha = 117; 879 } 880 881 rgb_color edgeLightColor; 882 rgb_color edgeShadowColor; 883 rgb_color frameLightColor; 884 rgb_color frameShadowColor; 885 rgb_color fillLightColor = tint_color(fillColor, fillLightTint); 886 rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint); 887 888 drawing_mode oldMode = view->DrawingMode(); 889 890 if ((flags & B_BLEND_FRAME) != 0) { 891 edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha }; 892 edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha }; 893 frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha }; 894 frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha }; 895 896 view->SetDrawingMode(B_OP_ALPHA); 897 } else { 898 edgeLightColor = tint_color(base, edgeLightTint); 899 edgeShadowColor = tint_color(base, edgeShadowTint); 900 frameLightColor = tint_color(fillColor, frameLightTint); 901 frameShadowColor = tint_color(fillColor, frameShadowTint); 902 } 903 904 if (orientation == B_HORIZONTAL) { 905 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, 906 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 907 fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation); 908 909 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, 910 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 911 fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation); 912 } else { 913 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, 914 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 915 fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation); 916 917 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, 918 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, 919 fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation); 920 } 921 922 view->ConstrainClippingRegion(NULL); 923 924 view->BeginLineArray(4); 925 if (orientation == B_HORIZONTAL) { 926 view->AddLine(barRect.LeftTop(), barRect.RightTop(), 927 edgeShadowColor); 928 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), 929 edgeLightColor); 930 barRect.InsetBy(0, 1); 931 view->AddLine(barRect.LeftTop(), barRect.RightTop(), 932 frameShadowColor); 933 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), 934 frameLightColor); 935 barRect.InsetBy(0, 1); 936 } else { 937 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), 938 edgeShadowColor); 939 view->AddLine(barRect.RightTop(), barRect.RightBottom(), 940 edgeLightColor); 941 barRect.InsetBy(1, 0); 942 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), 943 frameShadowColor); 944 view->AddLine(barRect.RightTop(), barRect.RightBottom(), 945 frameLightColor); 946 barRect.InsetBy(1, 0); 947 } 948 view->EndLineArray(); 949 950 view->SetDrawingMode(oldMode); 951 952 _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint, 953 orientation); 954 } 955 956 957 void 958 HaikuControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect, 959 const rgb_color& base, uint32 flags, orientation orientation) 960 { 961 if (!rect.IsValid() || !rect.Intersects(updateRect)) 962 return; 963 964 rgb_color thumbColor = tint_color(ui_color(B_SCROLL_BAR_THUMB_COLOR), 1.0); 965 966 // figure out frame color 967 rgb_color frameLightColor; 968 rgb_color frameShadowColor; 969 rgb_color shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.5); 970 971 //if the color BACKGROUND used is too dark, then make it lighter using the same as B_CONTROL_TEXT_COLOR 972 if (base.red + base.green + base.blue <= 128 * 3) { 973 shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.55); 974 } 975 976 if ((flags & B_FOCUSED) != 0) { 977 // focused 978 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 979 frameShadowColor = frameLightColor; 980 } else { 981 // figure out the tints to be used 982 float frameLightTint; 983 float frameShadowTint; 984 985 if ((flags & B_DISABLED) != 0) { 986 frameLightTint = 1.30; 987 frameShadowTint = 1.35; 988 shadowColor.alpha = 30; 989 } else { 990 frameLightTint = 1.6; 991 frameShadowTint = 1.65; 992 } 993 994 frameLightColor = tint_color(base, frameLightTint); 995 frameShadowColor = tint_color(base, frameShadowTint); 996 } 997 998 BRect originalRect(rect); 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 HaikuControlLook::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 HaikuControlLook::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 HaikuControlLook::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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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 HaikuControlLook::_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