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