tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / ControlLook.cpp
blob9f329a4c84952eea46ba93e07caf030ce55ba18d
1 /*
2 * Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
3 * Copyright 2012-2014 Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
6 * Authors:
7 * Stephan Aßmus, superstippi@gmx.de
8 * John Scipione, jscipione@gmail.com
9 */
12 #include <ControlLook.h>
14 #include <algorithm>
16 #include <Control.h>
17 #include <GradientLinear.h>
18 #include <LayoutUtils.h>
19 #include <Region.h>
20 #include <Shape.h>
21 #include <String.h>
22 #include <View.h>
23 #include <Window.h>
25 #include "ContainerWindow.h"
28 namespace BPrivate {
31 static const float kEdgeBevelLightTint = 0.59;
32 static const float kEdgeBevelShadowTint = 1.0735;
33 static const float kHoverTintFactor = 0.85;
35 static const float kButtonPopUpIndicatorWidth = 11;
38 BControlLook::BControlLook():
39 fCachedOutline(false),
40 fCachedWorkspace(-1)
45 BControlLook::~BControlLook()
50 BAlignment
51 BControlLook::DefaultLabelAlignment() const
53 return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER);
57 float
58 BControlLook::DefaultLabelSpacing() const
60 return ceilf(be_plain_font->Size() / 2.0);
64 float
65 BControlLook::DefaultItemSpacing() const
67 return ceilf(be_plain_font->Size() * 0.85);
71 float
72 BControlLook::ComposeSpacing(float spacing)
74 if (spacing == B_USE_DEFAULT_SPACING || spacing == B_USE_ITEM_SPACING) {
75 return be_control_look->DefaultItemSpacing();
76 } else if (spacing == B_USE_HALF_ITEM_SPACING) {
77 return ceilf(be_control_look->DefaultItemSpacing() * 0.5f);
78 } else if (spacing == B_USE_WINDOW_INSETS) {
79 return be_control_look->DefaultItemSpacing();
80 } else if (spacing == B_USE_SMALL_SPACING) {
81 return ceilf(be_control_look->DefaultItemSpacing() * 0.7f);
82 } else if (spacing == B_USE_BIG_SPACING) {
83 return ceilf(be_control_look->DefaultItemSpacing() * 1.3f);
85 return spacing;
89 uint32
90 BControlLook::Flags(BControl* control) const
92 uint32 flags = 0;
94 if (!control->IsEnabled())
95 flags |= B_DISABLED;
97 if (control->IsFocus() && control->Window() != NULL
98 && control->Window()->IsActive()) {
99 flags |= B_FOCUSED;
102 switch (control->Value()) {
103 case B_CONTROL_ON:
104 flags |= B_ACTIVATED;
105 break;
106 case B_CONTROL_PARTIALLY_ON:
107 flags |= B_PARTIALLY_ACTIVATED;
108 break;
111 if (control->Parent() != NULL
112 && (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) {
113 // In this constellation, assume we want to render the control
114 // against the already existing view contents of the parent view.
115 flags |= B_BLEND_FRAME;
118 return flags;
122 // #pragma mark -
125 void
126 BControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
127 const rgb_color& base, const rgb_color& background, uint32 flags,
128 uint32 borders)
130 _DrawButtonFrame(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, base,
131 background, 1.0, 1.0, flags, borders);
135 void
136 BControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
137 float radius, const rgb_color& base, const rgb_color& background, uint32 flags,
138 uint32 borders)
140 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius,
141 base, background, 1.0, 1.0, flags, borders);
145 void
146 BControlLook::DrawButtonFrame(BView* view, BRect& rect,
147 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
148 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
149 const rgb_color& background, uint32 flags,
150 uint32 borders)
152 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius,
153 leftBottomRadius, rightBottomRadius, base, background,
154 1.0, 1.0, flags, borders);
158 void
159 BControlLook::DrawButtonBackground(BView* view, BRect& rect,
160 const BRect& updateRect, const rgb_color& base, uint32 flags,
161 uint32 borders, orientation orientation)
163 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f,
164 base, false, flags, borders, orientation);
168 void
169 BControlLook::DrawButtonBackground(BView* view, BRect& rect,
170 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
171 uint32 borders, orientation orientation)
173 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius,
174 radius, base, false, flags, borders, orientation);
178 void
179 BControlLook::DrawButtonBackground(BView* view, BRect& rect,
180 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
181 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
182 uint32 flags, uint32 borders, orientation orientation)
184 _DrawButtonBackground(view, rect, updateRect, leftTopRadius,
185 rightTopRadius, leftBottomRadius, rightBottomRadius, base, false, flags,
186 borders, orientation);
190 void
191 BControlLook::DrawMenuBarBackground(BView* view, BRect& rect,
192 const BRect& updateRect, const rgb_color& base, uint32 flags,
193 uint32 borders)
195 if (!rect.IsValid() || !rect.Intersects(updateRect))
196 return;
198 // the surface edges
200 // colors
201 float topTint;
202 float bottomTint;
204 if ((flags & B_ACTIVATED) != 0) {
205 rgb_color bevelColor1 = tint_color(base, 1.40);
206 rgb_color bevelColor2 = tint_color(base, 1.25);
208 topTint = 1.25;
209 bottomTint = 1.20;
211 _DrawFrame(view, rect,
212 bevelColor1, bevelColor1,
213 bevelColor2, bevelColor2,
214 borders & B_TOP_BORDER);
215 } else {
216 rgb_color cornerColor = tint_color(base, 0.9);
217 rgb_color bevelColorTop = tint_color(base, 0.5);
218 rgb_color bevelColorLeft = tint_color(base, 0.7);
219 rgb_color bevelColorRightBottom = tint_color(base, 1.08);
221 topTint = 0.69;
222 bottomTint = 1.03;
224 _DrawFrame(view, rect,
225 bevelColorLeft, bevelColorTop,
226 bevelColorRightBottom, bevelColorRightBottom,
227 cornerColor, cornerColor,
228 borders);
231 // draw surface top
232 _FillGradient(view, rect, base, topTint, bottomTint);
236 void
237 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
238 const BRect& updateRect, const rgb_color& base,
239 const rgb_color& background, uint32 flags, uint32 borders)
241 _DrawButtonFrame(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, base,
242 background, 0.6, 1.0, flags, borders);
246 void
247 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
248 const BRect& updateRect, float radius, const rgb_color& base,
249 const rgb_color& background, uint32 flags, uint32 borders)
251 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius,
252 base, background, 0.6, 1.0, flags, borders);
256 void
257 BControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
258 const BRect& updateRect, float leftTopRadius,
259 float rightTopRadius, float leftBottomRadius,
260 float rightBottomRadius, const rgb_color& base,
261 const rgb_color& background, uint32 flags, uint32 borders)
263 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius,
264 leftBottomRadius, rightBottomRadius, base, background, 0.6, 1.0,
265 flags, borders);
269 void
270 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
271 const BRect& updateRect, const rgb_color& base, bool popupIndicator,
272 uint32 flags)
274 _DrawMenuFieldBackgroundOutside(view, rect, updateRect,
275 0.0f, 0.0f, 0.0f, 0.0f, base, popupIndicator, flags);
279 void
280 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
281 const BRect& updateRect, const rgb_color& base, uint32 flags,
282 uint32 borders)
284 _DrawMenuFieldBackgroundInside(view, rect, updateRect,
285 0.0f, 0.0f, 0.0f, 0.0f, base, flags, borders);
289 void
290 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
291 const BRect& updateRect, float radius, const rgb_color& base,
292 bool popupIndicator, uint32 flags)
294 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius,
295 radius, radius, base, popupIndicator, flags);
299 void
300 BControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
301 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
302 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
303 bool popupIndicator, uint32 flags)
305 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius,
306 rightTopRadius, leftBottomRadius, rightBottomRadius, base,
307 popupIndicator, flags);
311 void
312 BControlLook::DrawMenuBackground(BView* view, BRect& rect,
313 const BRect& updateRect, const rgb_color& base, uint32 flags,
314 uint32 borders)
316 if (!rect.IsValid() || !rect.Intersects(updateRect))
317 return;
319 // surface top color
320 rgb_color background = tint_color(base, 0.75);
322 // inner bevel colors
323 rgb_color bevelLightColor;
324 rgb_color bevelShadowColor;
326 if ((flags & B_DISABLED) != 0) {
327 bevelLightColor = tint_color(background, 0.80);
328 bevelShadowColor = tint_color(background, 1.07);
329 } else {
330 bevelLightColor = tint_color(background, 0.6);
331 bevelShadowColor = tint_color(background, 1.12);
334 // draw inner bevel
335 _DrawFrame(view, rect,
336 bevelLightColor, bevelLightColor,
337 bevelShadowColor, bevelShadowColor,
338 borders);
340 // draw surface top
341 view->SetHighColor(background);
342 view->FillRect(rect);
346 void
347 BControlLook::DrawMenuItemBackground(BView* view, BRect& rect,
348 const BRect& updateRect, const rgb_color& base, uint32 flags,
349 uint32 borders)
351 if (!rect.IsValid() || !rect.Intersects(updateRect))
352 return;
354 // surface edges
355 float topTint;
356 float bottomTint;
357 rgb_color selectedColor = base;
359 if ((flags & B_ACTIVATED) != 0) {
360 topTint = 0.9;
361 bottomTint = 1.05;
362 } else if ((flags & B_DISABLED) != 0) {
363 topTint = 0.80;
364 bottomTint = 1.07;
365 } else {
366 topTint = 0.6;
367 bottomTint = 1.12;
370 rgb_color bevelLightColor = tint_color(selectedColor, topTint);
371 rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint);
373 // draw surface edges
374 _DrawFrame(view, rect,
375 bevelLightColor, bevelLightColor,
376 bevelShadowColor, bevelShadowColor,
377 borders);
379 // draw surface top
380 view->SetLowColor(selectedColor);
381 // _FillGradient(view, rect, selectedColor, topTint, bottomTint);
382 _FillGradient(view, rect, selectedColor, bottomTint, topTint);
386 void
387 BControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect,
388 const rgb_color& base, const rgb_color& barColor, float progressPosition)
390 if (!rect.Intersects(updateRect))
391 return;
393 _DrawOuterResessedFrame(view, rect, base, 0.6);
395 // colors
396 rgb_color dark1BorderColor = tint_color(base, 1.3);
397 rgb_color dark2BorderColor = tint_color(base, 1.2);
398 rgb_color dark1FilledBorderColor = tint_color(barColor, 1.20);
399 rgb_color dark2FilledBorderColor = tint_color(barColor, 1.45);
401 BRect filledRect(rect);
402 filledRect.right = progressPosition - 1;
404 BRect nonfilledRect(rect);
405 nonfilledRect.left = progressPosition;
407 bool filledSurface = filledRect.Width() > 0;
408 bool nonfilledSurface = nonfilledRect.Width() > 0;
410 if (filledSurface) {
411 _DrawFrame(view, filledRect,
412 dark1FilledBorderColor, dark1FilledBorderColor,
413 dark2FilledBorderColor, dark2FilledBorderColor);
415 _FillGlossyGradient(view, filledRect, barColor, 0.55, 0.68, 0.76, 0.90);
418 if (nonfilledSurface) {
419 _DrawFrame(view, nonfilledRect, dark1BorderColor, dark1BorderColor,
420 dark2BorderColor, dark2BorderColor,
421 B_TOP_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER);
423 if (nonfilledRect.left < nonfilledRect.right) {
424 // shadow from fill bar, or left border
425 rgb_color leftBorder = dark1BorderColor;
426 if (filledSurface)
427 leftBorder = tint_color(base, 0.50);
428 view->SetHighColor(leftBorder);
429 view->StrokeLine(nonfilledRect.LeftTop(),
430 nonfilledRect.LeftBottom());
431 nonfilledRect.left++;
434 _FillGradient(view, nonfilledRect, base, 0.25, 0.06);
439 void
440 BControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect,
441 const rgb_color& base, uint32 flags)
443 if (!rect.Intersects(updateRect))
444 return;
446 rgb_color dark1BorderColor;
447 rgb_color dark2BorderColor;
448 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
450 if ((flags & B_DISABLED) != 0) {
451 _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags);
453 dark1BorderColor = tint_color(base, 1.15);
454 dark2BorderColor = tint_color(base, 1.15);
455 } else if ((flags & B_CLICKED) != 0) {
456 dark1BorderColor = tint_color(base, 1.50);
457 dark2BorderColor = tint_color(base, 1.48);
459 _DrawFrame(view, rect,
460 dark1BorderColor, dark1BorderColor,
461 dark2BorderColor, dark2BorderColor);
463 dark2BorderColor = dark1BorderColor;
464 } else {
465 _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags);
467 dark1BorderColor = tint_color(base, 1.40);
468 dark2BorderColor = tint_color(base, 1.38);
471 if ((flags & B_FOCUSED) != 0) {
472 dark1BorderColor = navigationColor;
473 dark2BorderColor = navigationColor;
476 _DrawFrame(view, rect,
477 dark1BorderColor, dark1BorderColor,
478 dark2BorderColor, dark2BorderColor);
480 if ((flags & B_DISABLED) != 0)
481 _FillGradient(view, rect, base, 0.4, 0.2);
482 else
483 _FillGradient(view, rect, base, 0.15, 0.0);
485 rgb_color markColor;
486 if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) {
487 view->SetHighColor(markColor);
489 BFont font;
490 view->GetFont(&font);
491 float inset = std::max(2.0f, roundf(font.Size() / 6));
492 rect.InsetBy(inset, inset);
494 float penSize = std::max(1.0f, ceilf(rect.Width() / 3.5f));
495 if (penSize > 1.0f && fmodf(penSize, 2.0f) == 0.0f) {
496 // Tweak ends to "include" the pixel at the index,
497 // we need to do this in order to produce results like R5,
498 // where coordinates were inclusive
499 rect.right++;
500 rect.bottom++;
503 view->SetPenSize(penSize);
504 view->SetDrawingMode(B_OP_OVER);
505 view->StrokeLine(rect.LeftTop(), rect.RightBottom());
506 view->StrokeLine(rect.LeftBottom(), rect.RightTop());
511 void
512 BControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateRect,
513 const rgb_color& base, uint32 flags)
515 if (!rect.Intersects(updateRect))
516 return;
518 rgb_color borderColor;
519 rgb_color bevelLight;
520 rgb_color bevelShadow;
521 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
523 if ((flags & B_DISABLED) != 0) {
524 borderColor = tint_color(base, 1.15);
525 bevelLight = base;
526 bevelShadow = base;
527 } else if ((flags & B_CLICKED) != 0) {
528 borderColor = tint_color(base, 1.50);
529 bevelLight = borderColor;
530 bevelShadow = borderColor;
531 } else {
532 borderColor = tint_color(base, 1.45);
533 bevelLight = tint_color(base, 0.55);
534 bevelShadow = tint_color(base, 1.11);
537 if ((flags & B_FOCUSED) != 0) {
538 borderColor = navigationColor;
541 BGradientLinear bevelGradient;
542 bevelGradient.AddColor(bevelShadow, 0);
543 bevelGradient.AddColor(bevelLight, 255);
544 bevelGradient.SetStart(rect.LeftTop());
545 bevelGradient.SetEnd(rect.RightBottom());
547 view->FillEllipse(rect, bevelGradient);
548 rect.InsetBy(1, 1);
550 bevelGradient.MakeEmpty();
551 bevelGradient.AddColor(borderColor, 0);
552 bevelGradient.AddColor(tint_color(borderColor, 0.8), 255);
553 view->FillEllipse(rect, bevelGradient);
554 rect.InsetBy(1, 1);
556 float topTint;
557 float bottomTint;
558 if ((flags & B_DISABLED) != 0) {
559 topTint = 0.4;
560 bottomTint = 0.2;
561 } else {
562 topTint = 0.15;
563 bottomTint = 0.0;
566 BGradientLinear gradient;
567 _MakeGradient(gradient, rect, base, topTint, bottomTint);
568 view->FillEllipse(rect, gradient);
570 rgb_color markColor;
571 if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) {
572 view->SetHighColor(markColor);
573 BFont font;
574 view->GetFont(&font);
575 float inset = roundf(font.Size() / 4);
576 rect.InsetBy(inset, inset);
577 view->FillEllipse(rect);
582 void
583 BControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2,
584 const BRect& updateRect, const rgb_color& base, uint32 flags,
585 orientation orientation)
587 DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation);
588 DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation);
592 void
593 BControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
594 const BRect& updateRect, const rgb_color& base, uint32 flags,
595 orientation orientation)
597 if (!rect.IsValid() || !rect.Intersects(updateRect))
598 return;
600 float gradient1Tint;
601 float gradient2Tint;
602 float darkEdge1Tint;
603 float darkEdge2Tint;
604 float shadowTint;
606 if ((flags & B_DISABLED) != 0) {
607 gradient1Tint = 0.9;
608 gradient2Tint = 0.8;
609 darkEdge1Tint = B_DARKEN_2_TINT;
610 darkEdge2Tint = B_DARKEN_2_TINT;
611 shadowTint = gradient1Tint;
612 } else {
613 gradient1Tint = 1.10;
614 gradient2Tint = 1.05;
615 darkEdge1Tint = B_DARKEN_3_TINT;
616 darkEdge2Tint = B_DARKEN_2_TINT;
617 shadowTint = gradient1Tint;
620 rgb_color darkEdge1 = tint_color(base, darkEdge1Tint);
621 rgb_color darkEdge2 = tint_color(base, darkEdge2Tint);
622 rgb_color shadow = tint_color(base, shadowTint);
624 if (orientation == B_HORIZONTAL) {
625 // dark vertical line on left edge
626 if (rect.Width() > 0) {
627 view->SetHighColor(darkEdge1);
628 view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
629 rect.left++;
631 // dark vertical line on right edge
632 if (rect.Width() >= 0) {
633 view->SetHighColor(darkEdge2);
634 view->StrokeLine(rect.RightTop(), rect.RightBottom());
635 rect.right--;
637 // vertical shadow line after left edge
638 if (rect.Width() >= 0) {
639 view->SetHighColor(shadow);
640 view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
641 rect.left++;
643 // fill
644 if (rect.Width() >= 0) {
645 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
646 orientation);
648 } else {
649 // dark vertical line on top edge
650 if (rect.Height() > 0) {
651 view->SetHighColor(darkEdge1);
652 view->StrokeLine(rect.LeftTop(), rect.RightTop());
653 rect.top++;
655 // dark vertical line on bottom edge
656 if (rect.Height() >= 0) {
657 view->SetHighColor(darkEdge2);
658 view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
659 rect.bottom--;
661 // horizontal shadow line after top edge
662 if (rect.Height() >= 0) {
663 view->SetHighColor(shadow);
664 view->StrokeLine(rect.LeftTop(), rect.RightTop());
665 rect.top++;
667 // fill
668 if (rect.Height() >= 0) {
669 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
670 orientation);
676 void
677 BControlLook::DrawScrollViewFrame(BView* view, BRect& rect,
678 const BRect& updateRect, BRect verticalScrollBarFrame,
679 BRect horizontalScrollBarFrame, const rgb_color& base,
680 border_style border, uint32 flags, uint32 _borders)
682 // calculate scroll corner rect before messing with the "rect"
683 BRect scrollCornerFillRect(rect.right, rect.bottom,
684 rect.right, rect.bottom);
686 if (horizontalScrollBarFrame.IsValid())
687 scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1;
689 if (verticalScrollBarFrame.IsValid())
690 scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1;
692 if (border == B_NO_BORDER) {
693 if (scrollCornerFillRect.IsValid()) {
694 view->SetHighColor(base);
695 view->FillRect(scrollCornerFillRect);
697 return;
700 bool excludeScrollCorner = border == B_FANCY_BORDER
701 && horizontalScrollBarFrame.IsValid()
702 && verticalScrollBarFrame.IsValid();
704 uint32 borders = _borders;
705 if (excludeScrollCorner) {
706 rect.bottom = horizontalScrollBarFrame.top;
707 rect.right = verticalScrollBarFrame.left;
708 borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER);
711 rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
713 if (border == B_FANCY_BORDER)
714 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
716 if ((flags & B_FOCUSED) != 0) {
717 rgb_color focusColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
718 _DrawFrame(view, rect, focusColor, focusColor, focusColor, focusColor,
719 borders);
720 } else {
721 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
722 scrollbarFrameColor, scrollbarFrameColor, borders);
725 if (excludeScrollCorner) {
726 horizontalScrollBarFrame.InsetBy(-1, -1);
727 // do not overdraw the top edge
728 horizontalScrollBarFrame.top += 2;
729 borders = _borders;
730 borders &= ~B_TOP_BORDER;
731 _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base,
732 1.0, 1.0, flags, borders);
733 _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor,
734 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
735 borders);
737 verticalScrollBarFrame.InsetBy(-1, -1);
738 // do not overdraw the left edge
739 verticalScrollBarFrame.left += 2;
740 borders = _borders;
741 borders &= ~B_LEFT_BORDER;
742 _DrawOuterResessedFrame(view, verticalScrollBarFrame, base,
743 1.0, 1.0, flags, borders);
744 _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor,
745 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
746 borders);
748 // exclude recessed frame
749 scrollCornerFillRect.top++;
750 scrollCornerFillRect.left++;
753 if (scrollCornerFillRect.IsValid()) {
754 view->SetHighColor(base);
755 view->FillRect(scrollCornerFillRect);
760 void
761 BControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect,
762 const rgb_color& base, uint32 direction, uint32 flags, float tint)
764 BPoint tri1, tri2, tri3;
765 float hInset = rect.Width() / 3;
766 float vInset = rect.Height() / 3;
767 rect.InsetBy(hInset, vInset);
769 switch (direction) {
770 case B_LEFT_ARROW:
771 tri1.Set(rect.right, rect.top);
772 tri2.Set(rect.right - rect.Width() / 1.33,
773 (rect.top + rect.bottom + 1) / 2);
774 tri3.Set(rect.right, rect.bottom + 1);
775 break;
776 case B_RIGHT_ARROW:
777 tri1.Set(rect.left + 1, rect.bottom + 1);
778 tri2.Set(rect.left + 1 + rect.Width() / 1.33,
779 (rect.top + rect.bottom + 1) / 2);
780 tri3.Set(rect.left + 1, rect.top);
781 break;
782 case B_UP_ARROW:
783 tri1.Set(rect.left, rect.bottom);
784 tri2.Set((rect.left + rect.right + 1) / 2,
785 rect.bottom - rect.Height() / 1.33);
786 tri3.Set(rect.right + 1, rect.bottom);
787 break;
788 case B_DOWN_ARROW:
789 default:
790 tri1.Set(rect.left, rect.top + 1);
791 tri2.Set((rect.left + rect.right + 1) / 2,
792 rect.top + 1 + rect.Height() / 1.33);
793 tri3.Set(rect.right + 1, rect.top + 1);
794 break;
795 case B_LEFT_UP_ARROW:
796 tri1.Set(rect.left, rect.bottom);
797 tri2.Set(rect.left, rect.top);
798 tri3.Set(rect.right - 1, rect.top);
799 break;
800 case B_RIGHT_UP_ARROW:
801 tri1.Set(rect.left + 1, rect.top);
802 tri2.Set(rect.right, rect.top);
803 tri3.Set(rect.right, rect.bottom);
804 break;
805 case B_RIGHT_DOWN_ARROW:
806 tri1.Set(rect.right, rect.top);
807 tri2.Set(rect.right, rect.bottom);
808 tri3.Set(rect.left + 1, rect.bottom);
809 break;
810 case B_LEFT_DOWN_ARROW:
811 tri1.Set(rect.right - 1, rect.bottom);
812 tri2.Set(rect.left, rect.bottom);
813 tri3.Set(rect.left, rect.top);
814 break;
817 BShape arrowShape;
818 arrowShape.MoveTo(tri1);
819 arrowShape.LineTo(tri2);
820 arrowShape.LineTo(tri3);
822 if ((flags & B_DISABLED) != 0)
823 tint = (tint + B_NO_TINT + B_NO_TINT) / 3;
825 view->SetHighColor(tint_color(base, tint));
827 float penSize = view->PenSize();
828 drawing_mode mode = view->DrawingMode();
830 view->MovePenTo(BPoint(0, 0));
832 view->SetPenSize(ceilf(hInset / 2.0));
833 view->SetDrawingMode(B_OP_OVER);
834 view->StrokeShape(&arrowShape);
836 view->SetPenSize(penSize);
837 view->SetDrawingMode(mode);
841 rgb_color
842 BControlLook::SliderBarColor(const rgb_color& base)
844 return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT);
848 void
849 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
850 const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
851 float sliderScale, uint32 flags, orientation orientation)
853 if (!rect.IsValid() || !rect.Intersects(updateRect))
854 return;
856 // save the clipping constraints of the view
857 view->PushState();
859 // separate the bar in two sides
860 float sliderPosition;
861 BRect leftBarSide = rect;
862 BRect rightBarSide = rect;
864 if (orientation == B_HORIZONTAL) {
865 sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
866 * sliderScale);
867 leftBarSide.right = sliderPosition - 1;
868 rightBarSide.left = sliderPosition;
869 } else {
870 // NOTE: position is reverse of coords
871 sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
872 * (1.0 - sliderScale));
873 leftBarSide.top = sliderPosition;
874 rightBarSide.bottom = sliderPosition - 1;
877 // fill the background for the corners, exclude the middle bar for now
878 BRegion region(rect);
879 region.Exclude(rightBarSide);
880 view->ConstrainClippingRegion(&region);
882 view->PushState();
884 DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
885 orientation);
887 view->PopState();
889 region.Set(rect);
890 region.Exclude(leftBarSide);
891 view->ConstrainClippingRegion(&region);
893 view->PushState();
895 DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
896 orientation);
898 view->PopState();
900 // restore the clipping constraints of the view
901 view->PopState();
905 void
906 BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
907 const rgb_color& base, rgb_color fillColor, uint32 flags,
908 orientation orientation)
910 if (!rect.IsValid() || !rect.Intersects(updateRect))
911 return;
913 // separate the rect into corners
914 BRect leftCorner(rect);
915 BRect rightCorner(rect);
916 BRect barRect(rect);
918 if (orientation == B_HORIZONTAL) {
919 leftCorner.right = leftCorner.left + leftCorner.Height();
920 rightCorner.left = rightCorner.right - rightCorner.Height();
921 barRect.left += ceilf(barRect.Height() / 2);
922 barRect.right -= ceilf(barRect.Height() / 2);
923 } else {
924 leftCorner.bottom = leftCorner.top + leftCorner.Width();
925 rightCorner.top = rightCorner.bottom - rightCorner.Width();
926 barRect.top += ceilf(barRect.Width() / 2);
927 barRect.bottom -= ceilf(barRect.Width() / 2);
930 // fill the background for the corners, exclude the middle bar for now
931 BRegion region(rect);
932 region.Exclude(barRect);
933 view->ConstrainClippingRegion(&region);
935 if ((flags & B_BLEND_FRAME) == 0) {
936 view->SetHighColor(base);
937 view->FillRect(rect);
940 // figure out the tints to be used
941 float edgeLightTint;
942 float edgeShadowTint;
943 float frameLightTint;
944 float frameShadowTint;
945 float fillLightTint;
946 float fillShadowTint;
947 uint8 edgeLightAlpha;
948 uint8 edgeShadowAlpha;
949 uint8 frameLightAlpha;
950 uint8 frameShadowAlpha;
952 if ((flags & B_DISABLED) != 0) {
953 edgeLightTint = 1.0;
954 edgeShadowTint = 1.0;
955 frameLightTint = 1.20;
956 frameShadowTint = 1.25;
957 fillLightTint = 0.9;
958 fillShadowTint = 1.05;
959 edgeLightAlpha = 12;
960 edgeShadowAlpha = 12;
961 frameLightAlpha = 40;
962 frameShadowAlpha = 45;
964 fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6);
965 fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6);
966 fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6);
967 } else {
968 edgeLightTint = 0.65;
969 edgeShadowTint = 1.07;
970 frameLightTint = 1.40;
971 frameShadowTint = 1.50;
972 fillLightTint = 0.8;
973 fillShadowTint = 1.1;
974 edgeLightAlpha = 15;
975 edgeShadowAlpha = 15;
976 frameLightAlpha = 92;
977 frameShadowAlpha = 107;
980 rgb_color edgeLightColor;
981 rgb_color edgeShadowColor;
982 rgb_color frameLightColor;
983 rgb_color frameShadowColor;
984 rgb_color fillLightColor = tint_color(fillColor, fillLightTint);
985 rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint);
987 drawing_mode oldMode = view->DrawingMode();
989 if ((flags & B_BLEND_FRAME) != 0) {
990 edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha };
991 edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha };
992 frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha };
993 frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha };
995 view->SetDrawingMode(B_OP_ALPHA);
996 } else {
997 edgeLightColor = tint_color(base, edgeLightTint);
998 edgeShadowColor = tint_color(base, edgeShadowTint);
999 frameLightColor = tint_color(fillColor, frameLightTint);
1000 frameShadowColor = tint_color(fillColor, frameShadowTint);
1003 if (orientation == B_HORIZONTAL) {
1004 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
1005 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
1006 fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation);
1008 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
1009 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
1010 fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation);
1011 } else {
1012 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
1013 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
1014 fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation);
1016 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
1017 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
1018 fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation);
1021 view->ConstrainClippingRegion(NULL);
1023 view->BeginLineArray(4);
1024 if (orientation == B_HORIZONTAL) {
1025 view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor);
1026 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
1027 edgeLightColor);
1028 barRect.InsetBy(0, 1);
1029 view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor);
1030 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
1031 frameLightColor);
1032 barRect.InsetBy(0, 1);
1033 } else {
1034 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor);
1035 view->AddLine(barRect.RightTop(), barRect.RightBottom(),
1036 edgeLightColor);
1037 barRect.InsetBy(1, 0);
1038 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor);
1039 view->AddLine(barRect.RightTop(), barRect.RightBottom(),
1040 frameLightColor);
1041 barRect.InsetBy(1, 0);
1043 view->EndLineArray();
1045 view->SetDrawingMode(oldMode);
1047 _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint,
1048 orientation);
1052 void
1053 BControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
1054 const rgb_color& base, uint32 flags, orientation orientation)
1056 if (!rect.IsValid() || !rect.Intersects(updateRect))
1057 return;
1059 // figure out frame color
1060 rgb_color frameLightColor;
1061 rgb_color frameShadowColor;
1062 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1064 if ((flags & B_FOCUSED) != 0) {
1065 // focused
1066 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1067 frameShadowColor = frameLightColor;
1068 } else {
1069 // figure out the tints to be used
1070 float frameLightTint;
1071 float frameShadowTint;
1073 if ((flags & B_DISABLED) != 0) {
1074 frameLightTint = 1.30;
1075 frameShadowTint = 1.35;
1076 shadowColor.alpha = 30;
1077 } else {
1078 frameLightTint = 1.6;
1079 frameShadowTint = 1.65;
1082 frameLightColor = tint_color(base, frameLightTint);
1083 frameShadowColor = tint_color(base, frameShadowTint);
1086 BRect originalRect(rect);
1087 rect.right--;
1088 rect.bottom--;
1090 _DrawFrame(view, rect, frameLightColor, frameLightColor,
1091 frameShadowColor, frameShadowColor);
1093 flags &= ~B_ACTIVATED;
1094 DrawButtonBackground(view, rect, updateRect, base, flags);
1096 // thumb shadow
1097 view->SetDrawingMode(B_OP_ALPHA);
1098 view->SetHighColor(shadowColor);
1099 originalRect.left++;
1100 originalRect.top++;
1101 view->StrokeLine(originalRect.LeftBottom(), originalRect.RightBottom());
1102 originalRect.bottom--;
1103 view->StrokeLine(originalRect.RightTop(), originalRect.RightBottom());
1105 // thumb edge
1106 if (orientation == B_HORIZONTAL) {
1107 rect.InsetBy(0, floorf(rect.Height() / 4));
1108 rect.left = floorf((rect.left + rect.right) / 2);
1109 rect.right = rect.left + 1;
1110 shadowColor = tint_color(base, B_DARKEN_2_TINT);
1111 shadowColor.alpha = 128;
1112 view->SetHighColor(shadowColor);
1113 view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
1114 rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1115 lightColor.alpha = 128;
1116 view->SetHighColor(lightColor);
1117 view->StrokeLine(rect.RightTop(), rect.RightBottom());
1118 } else {
1119 rect.InsetBy(floorf(rect.Width() / 4), 0);
1120 rect.top = floorf((rect.top + rect.bottom) / 2);
1121 rect.bottom = rect.top + 1;
1122 shadowColor = tint_color(base, B_DARKEN_2_TINT);
1123 shadowColor.alpha = 128;
1124 view->SetHighColor(shadowColor);
1125 view->StrokeLine(rect.LeftTop(), rect.RightTop());
1126 rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1127 lightColor.alpha = 128;
1128 view->SetHighColor(lightColor);
1129 view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
1132 view->SetDrawingMode(B_OP_COPY);
1136 void
1137 BControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1138 const BRect& updateRect, const rgb_color& base, uint32 flags,
1139 orientation orientation)
1141 DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation);
1145 void
1146 BControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1147 const BRect& updateRect, const rgb_color& base, const rgb_color& fill,
1148 uint32 flags, orientation orientation)
1150 if (!rect.IsValid() || !rect.Intersects(updateRect))
1151 return;
1153 // figure out frame color
1154 rgb_color frameLightColor;
1155 rgb_color frameShadowColor;
1156 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1158 float topTint = 0.49;
1159 float middleTint1 = 0.62;
1160 float middleTint2 = 0.76;
1161 float bottomTint = 0.90;
1163 if ((flags & B_DISABLED) != 0) {
1164 topTint = (topTint + B_NO_TINT) / 2;
1165 middleTint1 = (middleTint1 + B_NO_TINT) / 2;
1166 middleTint2 = (middleTint2 + B_NO_TINT) / 2;
1167 bottomTint = (bottomTint + B_NO_TINT) / 2;
1168 } else if ((flags & B_HOVER) != 0) {
1169 topTint *= kHoverTintFactor;
1170 middleTint1 *= kHoverTintFactor;
1171 middleTint2 *= kHoverTintFactor;
1172 bottomTint *= kHoverTintFactor;
1175 if ((flags & B_FOCUSED) != 0) {
1176 // focused
1177 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1178 frameShadowColor = frameLightColor;
1179 } else {
1180 // figure out the tints to be used
1181 float frameLightTint;
1182 float frameShadowTint;
1184 if ((flags & B_DISABLED) != 0) {
1185 frameLightTint = 1.30;
1186 frameShadowTint = 1.35;
1187 shadowColor.alpha = 30;
1188 } else {
1189 frameLightTint = 1.6;
1190 frameShadowTint = 1.65;
1193 frameLightColor = tint_color(base, frameLightTint);
1194 frameShadowColor = tint_color(base, frameShadowTint);
1197 // make room for the shadow
1198 rect.right--;
1199 rect.bottom--;
1201 uint32 viewFlags = view->Flags();
1202 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
1203 view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
1205 float centerh = (rect.left + rect.right) / 2;
1206 float centerv = (rect.top + rect.bottom) / 2;
1208 BShape shape;
1209 if (orientation == B_HORIZONTAL) {
1210 shape.MoveTo(BPoint(rect.left + 0.5, rect.bottom + 0.5));
1211 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1212 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom - 1 + 0.5));
1213 shape.LineTo(BPoint(centerh + 0.5, rect.top + 0.5));
1214 shape.LineTo(BPoint(rect.left + 0.5, rect.bottom - 1 + 0.5));
1215 } else {
1216 shape.MoveTo(BPoint(rect.right + 0.5, rect.top + 0.5));
1217 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1218 shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.bottom + 0.5));
1219 shape.LineTo(BPoint(rect.left + 0.5, centerv + 0.5));
1220 shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.top + 0.5));
1222 shape.Close();
1224 view->MovePenTo(BPoint(1, 1));
1226 view->SetDrawingMode(B_OP_ALPHA);
1227 view->SetHighColor(shadowColor);
1228 view->StrokeShape(&shape);
1230 view->MovePenTo(B_ORIGIN);
1232 view->SetDrawingMode(B_OP_COPY);
1233 view->SetHighColor(frameLightColor);
1234 view->StrokeShape(&shape);
1236 rect.InsetBy(1, 1);
1237 shape.Clear();
1238 if (orientation == B_HORIZONTAL) {
1239 shape.MoveTo(BPoint(rect.left, rect.bottom + 1));
1240 shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1241 shape.LineTo(BPoint(centerh + 0.5, rect.top));
1242 } else {
1243 shape.MoveTo(BPoint(rect.right + 1, rect.top));
1244 shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1245 shape.LineTo(BPoint(rect.left, centerv + 0.5));
1247 shape.Close();
1249 BGradientLinear gradient;
1250 if ((flags & B_DISABLED) != 0) {
1251 _MakeGradient(gradient, rect, fill, topTint, bottomTint);
1252 } else {
1253 _MakeGlossyGradient(gradient, rect, fill, topTint, middleTint1,
1254 middleTint2, bottomTint);
1257 view->FillShape(&shape, gradient);
1259 view->SetFlags(viewFlags);
1263 void
1264 BControlLook::DrawSliderHashMarks(BView* view, BRect& rect,
1265 const BRect& updateRect, const rgb_color& base, int32 count,
1266 hash_mark_location location, uint32 flags, orientation orientation)
1268 if (!rect.IsValid() || !rect.Intersects(updateRect))
1269 return;
1271 rgb_color lightColor;
1272 rgb_color darkColor;
1274 if ((flags & B_DISABLED) != 0) {
1275 lightColor = tint_color(base, 0.9);
1276 darkColor = tint_color(base, 1.07);
1277 } else {
1278 lightColor = tint_color(base, 0.8);
1279 darkColor = tint_color(base, 1.14);
1282 int32 hashMarkCount = std::max(count, (int32)2);
1283 // draw at least two hashmarks at min/max if
1284 // fHashMarks != B_HASH_MARKS_NONE
1285 float factor;
1286 float startPos;
1287 if (orientation == B_HORIZONTAL) {
1288 factor = (rect.Width() - 2) / (hashMarkCount - 1);
1289 startPos = rect.left + 1;
1290 } else {
1291 factor = (rect.Height() - 2) / (hashMarkCount - 1);
1292 startPos = rect.top + 1;
1295 if (location & B_HASH_MARKS_TOP) {
1296 view->BeginLineArray(hashMarkCount * 2);
1298 if (orientation == B_HORIZONTAL) {
1299 float pos = startPos;
1300 for (int32 i = 0; i < hashMarkCount; i++) {
1301 view->AddLine(BPoint(pos, rect.top),
1302 BPoint(pos, rect.top + 4), darkColor);
1303 view->AddLine(BPoint(pos + 1, rect.top),
1304 BPoint(pos + 1, rect.top + 4), lightColor);
1306 pos += factor;
1308 } else {
1309 float pos = startPos;
1310 for (int32 i = 0; i < hashMarkCount; i++) {
1311 view->AddLine(BPoint(rect.left, pos),
1312 BPoint(rect.left + 4, pos), darkColor);
1313 view->AddLine(BPoint(rect.left, pos + 1),
1314 BPoint(rect.left + 4, pos + 1), lightColor);
1316 pos += factor;
1320 view->EndLineArray();
1323 if ((location & B_HASH_MARKS_BOTTOM) != 0) {
1324 view->BeginLineArray(hashMarkCount * 2);
1326 if (orientation == B_HORIZONTAL) {
1327 float pos = startPos;
1328 for (int32 i = 0; i < hashMarkCount; i++) {
1329 view->AddLine(BPoint(pos, rect.bottom - 4),
1330 BPoint(pos, rect.bottom), darkColor);
1331 view->AddLine(BPoint(pos + 1, rect.bottom - 4),
1332 BPoint(pos + 1, rect.bottom), lightColor);
1334 pos += factor;
1336 } else {
1337 float pos = startPos;
1338 for (int32 i = 0; i < hashMarkCount; i++) {
1339 view->AddLine(BPoint(rect.right - 4, pos),
1340 BPoint(rect.right, pos), darkColor);
1341 view->AddLine(BPoint(rect.right - 4, pos + 1),
1342 BPoint(rect.right, pos + 1), lightColor);
1344 pos += factor;
1348 view->EndLineArray();
1353 void
1354 BControlLook::DrawActiveTab(BView* view, BRect& rect, const BRect& updateRect,
1355 const rgb_color& base, uint32 flags, uint32 borders)
1357 if (!rect.IsValid() || !rect.Intersects(updateRect))
1358 return;
1360 // Snap the rectangle to pixels to avoid rounding errors.
1361 rect.left = floorf(rect.left);
1362 rect.right = floorf(rect.right);
1363 rect.top = floorf(rect.top);
1364 rect.bottom = floorf(rect.bottom);
1366 // save the clipping constraints of the view
1367 view->PushState();
1369 // set clipping constraints to updateRect
1370 BRegion clipping(updateRect);
1371 view->ConstrainClippingRegion(&clipping);
1373 rgb_color edgeShadowColor;
1374 rgb_color edgeLightColor;
1375 rgb_color frameShadowColor;
1376 rgb_color frameLightColor;
1377 rgb_color bevelShadowColor;
1378 rgb_color bevelLightColor;
1379 BGradientLinear fillGradient;
1380 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1381 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1383 if ((flags & B_DISABLED) != 0) {
1384 edgeLightColor = base;
1385 edgeShadowColor = base;
1386 frameLightColor = tint_color(base, 1.25);
1387 frameShadowColor = tint_color(base, 1.30);
1388 bevelLightColor = tint_color(base, 0.8);
1389 bevelShadowColor = tint_color(base, 1.07);
1390 fillGradient.AddColor(tint_color(base, 0.85), 0);
1391 fillGradient.AddColor(base, 255);
1392 } else {
1393 edgeLightColor = tint_color(base, 0.80);
1394 edgeShadowColor = tint_color(base, 1.03);
1395 frameLightColor = tint_color(base, 1.30);
1396 frameShadowColor = tint_color(base, 1.30);
1397 bevelLightColor = tint_color(base, 0.6);
1398 bevelShadowColor = tint_color(base, 1.07);
1399 fillGradient.AddColor(tint_color(base, 0.75), 0);
1400 fillGradient.AddColor(tint_color(base, 1.03), 255);
1403 static const float kRoundCornerRadius = 4.0f;
1405 // left top corner dimensions
1406 BRect leftTopCorner(rect);
1407 leftTopCorner.right = floorf(leftTopCorner.left + kRoundCornerRadius);
1408 leftTopCorner.bottom = floorf(rect.top + kRoundCornerRadius);
1409 clipping.Exclude(leftTopCorner);
1411 // draw the left top corner
1412 _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base,
1413 edgeShadowColor, frameLightColor, bevelLightColor,
1414 fillGradient);
1416 // right top corner dimensions
1417 BRect rightTopCorner(rect);
1418 rightTopCorner.right = floorf(rect.right);
1419 rightTopCorner.left = floorf(rightTopCorner.right - kRoundCornerRadius);
1420 rightTopCorner.bottom = floorf(rect.top + kRoundCornerRadius);
1421 clipping.Exclude(rightTopCorner);
1423 // draw the right top corner
1424 _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base,
1425 edgeShadowColor, edgeLightColor, frameLightColor,
1426 frameShadowColor, bevelLightColor, bevelShadowColor,
1427 fillGradient);
1429 // clip out the corners
1430 view->ConstrainClippingRegion(&clipping);
1432 // draw the rest of frame and fill
1433 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1434 edgeLightColor,
1435 borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1436 if ((borders & B_LEFT_BORDER) == 0)
1437 rect.left++;
1438 if ((borders & B_RIGHT_BORDER) == 0)
1439 rect.right--;
1441 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1442 frameShadowColor, B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER);
1444 _DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor,
1445 bevelShadowColor);
1447 view->FillRect(rect, fillGradient);
1449 // restore the clipping constraints of the view
1450 view->PopState();
1454 void
1455 BControlLook::DrawInactiveTab(BView* view, BRect& rect, const BRect& updateRect,
1456 const rgb_color& base, uint32 flags, uint32 borders)
1458 if (!rect.IsValid() || !rect.Intersects(updateRect))
1459 return;
1461 rgb_color edgeShadowColor;
1462 rgb_color edgeLightColor;
1463 rgb_color frameShadowColor;
1464 rgb_color frameLightColor;
1465 rgb_color bevelShadowColor;
1466 rgb_color bevelLightColor;
1467 BGradientLinear fillGradient;
1468 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1469 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1471 if ((flags & B_DISABLED) != 0) {
1472 edgeLightColor = base;
1473 edgeShadowColor = base;
1474 frameLightColor = tint_color(base, 1.25);
1475 frameShadowColor = tint_color(base, 1.30);
1476 bevelLightColor = tint_color(base, 0.8);
1477 bevelShadowColor = tint_color(base, 1.07);
1478 fillGradient.AddColor(tint_color(base, 0.85), 0);
1479 fillGradient.AddColor(base, 255);
1480 } else {
1481 edgeLightColor = tint_color(base, 0.80);
1482 edgeShadowColor = tint_color(base, 1.03);
1483 frameLightColor = tint_color(base, 1.30);
1484 frameShadowColor = tint_color(base, 1.30);
1485 bevelLightColor = tint_color(base, 1.10);
1486 bevelShadowColor = tint_color(base, 1.17);
1487 fillGradient.AddColor(tint_color(base, 1.12), 0);
1488 fillGradient.AddColor(tint_color(base, 1.08), 255);
1491 // active tabs stand out at the top, but this is an inactive tab
1492 view->SetHighColor(base);
1493 view->FillRect(BRect(rect.left, rect.top, rect.right, rect.top + 4));
1494 rect.top += 4;
1496 // frame and fill
1497 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1498 edgeLightColor,
1499 borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1501 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1502 frameShadowColor,
1503 borders & (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER));
1505 if (rect.IsValid()) {
1506 _DrawFrame(view, rect, bevelShadowColor, bevelShadowColor,
1507 bevelLightColor, bevelLightColor, B_LEFT_BORDER & ~borders);
1508 } else {
1509 if ((B_LEFT_BORDER & ~borders) != 0)
1510 rect.left++;
1513 view->FillRect(rect, fillGradient);
1517 void
1518 BControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect,
1519 const rgb_color& base, orientation orientation, uint32 flags,
1520 uint32 borders)
1522 if (!rect.IsValid() || !rect.Intersects(updateRect))
1523 return;
1525 rgb_color background;
1526 if ((flags & (B_CLICKED | B_ACTIVATED)) != 0)
1527 background = tint_color(base, B_DARKEN_1_TINT);
1528 else
1529 background = base;
1531 rgb_color light = tint_color(background, 0.6);
1532 rgb_color shadow = tint_color(background, 1.21);
1534 // frame
1535 if (borders != 0 && rect.Width() > 3 && rect.Height() > 3)
1536 DrawRaisedBorder(view, rect, updateRect, background, flags, borders);
1538 // dots and rest of background
1539 if (orientation == B_HORIZONTAL) {
1540 if (rect.Width() > 2) {
1541 // background on left/right
1542 BRegion region(rect);
1543 rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5);
1544 rect.right = rect.left + 1;
1545 region.Exclude(rect);
1546 view->SetHighColor(background);
1547 view->FillRegion(&region);
1550 BPoint dot = rect.LeftTop();
1551 BPoint stop = rect.LeftBottom();
1552 int32 num = 1;
1553 while (dot.y <= stop.y) {
1554 rgb_color col1;
1555 rgb_color col2;
1556 switch (num) {
1557 case 1:
1558 col1 = background;
1559 col2 = background;
1560 break;
1561 case 2:
1562 col1 = shadow;
1563 col2 = background;
1564 break;
1565 case 3:
1566 default:
1567 col1 = background;
1568 col2 = light;
1569 num = 0;
1570 break;
1572 view->SetHighColor(col1);
1573 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1574 view->SetHighColor(col2);
1575 dot.x++;
1576 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1577 dot.x -= 1.0;
1578 // next pixel
1579 num++;
1580 dot.y++;
1582 } else {
1583 if (rect.Height() > 2) {
1584 // background on left/right
1585 BRegion region(rect);
1586 rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5);
1587 rect.bottom = rect.top + 1;
1588 region.Exclude(rect);
1589 view->SetHighColor(background);
1590 view->FillRegion(&region);
1593 BPoint dot = rect.LeftTop();
1594 BPoint stop = rect.RightTop();
1595 int32 num = 1;
1596 while (dot.x <= stop.x) {
1597 rgb_color col1;
1598 rgb_color col2;
1599 switch (num) {
1600 case 1:
1601 col1 = background;
1602 col2 = background;
1603 break;
1604 case 2:
1605 col1 = shadow;
1606 col2 = background;
1607 break;
1608 case 3:
1609 default:
1610 col1 = background;
1611 col2 = light;
1612 num = 0;
1613 break;
1615 view->SetHighColor(col1);
1616 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1617 view->SetHighColor(col2);
1618 dot.y++;
1619 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1620 dot.y -= 1.0;
1621 // next pixel
1622 num++;
1623 dot.x++;
1629 // #pragma mark -
1632 void
1633 BControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect,
1634 const rgb_color& base, border_style border, uint32 flags, uint32 borders)
1636 if (border == B_NO_BORDER)
1637 return;
1639 rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
1640 if ((flags & B_FOCUSED) != 0)
1641 scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1643 if (border == B_FANCY_BORDER)
1644 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
1646 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
1647 scrollbarFrameColor, scrollbarFrameColor, borders);
1651 void
1652 BControlLook::DrawRaisedBorder(BView* view, BRect& rect,
1653 const BRect& updateRect, const rgb_color& base, uint32 flags,
1654 uint32 borders)
1656 rgb_color lightColor;
1657 rgb_color shadowColor;
1659 if ((flags & B_DISABLED) != 0) {
1660 lightColor = base;
1661 shadowColor = base;
1662 } else {
1663 lightColor = tint_color(base, 0.85);
1664 shadowColor = tint_color(base, 1.07);
1667 _DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor,
1668 borders);
1672 void
1673 BControlLook::DrawTextControlBorder(BView* view, BRect& rect,
1674 const BRect& updateRect, const rgb_color& base, uint32 flags,
1675 uint32 borders)
1677 if (!rect.Intersects(updateRect))
1678 return;
1680 rgb_color dark1BorderColor;
1681 rgb_color dark2BorderColor;
1682 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1683 rgb_color invalidColor = ui_color(B_FAILURE_COLOR);
1685 if ((flags & B_DISABLED) != 0) {
1686 _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders);
1688 if ((flags & B_BLEND_FRAME) != 0)
1689 dark1BorderColor = (rgb_color){ 0, 0, 0, 40 };
1690 else
1691 dark1BorderColor = tint_color(base, 1.15);
1692 dark2BorderColor = dark1BorderColor;
1693 } else if ((flags & B_CLICKED) != 0) {
1694 dark1BorderColor = tint_color(base, 1.50);
1695 dark2BorderColor = tint_color(base, 1.49);
1697 // BCheckBox uses this to indicate the clicked state...
1698 _DrawFrame(view, rect,
1699 dark1BorderColor, dark1BorderColor,
1700 dark2BorderColor, dark2BorderColor);
1702 dark2BorderColor = dark1BorderColor;
1703 } else {
1704 _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders);
1706 if ((flags & B_BLEND_FRAME) != 0) {
1707 dark1BorderColor = (rgb_color){ 0, 0, 0, 102 };
1708 dark2BorderColor = (rgb_color){ 0, 0, 0, 97 };
1709 } else {
1710 dark1BorderColor = tint_color(base, 1.40);
1711 dark2BorderColor = tint_color(base, 1.38);
1715 if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) {
1716 dark1BorderColor = navigationColor;
1717 dark2BorderColor = navigationColor;
1720 if ((flags & B_DISABLED) == 0 && (flags & B_INVALID) != 0) {
1721 dark1BorderColor = invalidColor;
1722 dark2BorderColor = invalidColor;
1725 if ((flags & B_BLEND_FRAME) != 0) {
1726 drawing_mode oldMode = view->DrawingMode();
1727 view->SetDrawingMode(B_OP_ALPHA);
1729 _DrawFrame(view, rect,
1730 dark1BorderColor, dark1BorderColor,
1731 dark2BorderColor, dark2BorderColor, borders);
1733 view->SetDrawingMode(oldMode);
1734 } else {
1735 _DrawFrame(view, rect,
1736 dark1BorderColor, dark1BorderColor,
1737 dark2BorderColor, dark2BorderColor, borders);
1742 void
1743 BControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect,
1744 const rgb_color& base, uint32 borders)
1746 rgb_color frameColor = tint_color(base, 1.30);
1747 rgb_color bevelLight = tint_color(base, 0.8);
1748 rgb_color bevelShadow = tint_color(base, 1.03);
1750 _DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight,
1751 borders);
1753 _DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor,
1754 borders);
1756 _DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow,
1757 borders);
1761 void
1762 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1763 const BRect& updateRect, const rgb_color& base, uint32 flags)
1765 DrawLabel(view, label, NULL, rect, updateRect, base, flags,
1766 DefaultLabelAlignment());
1770 void
1771 BControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1772 const BRect& updateRect, const rgb_color& base, uint32 flags,
1773 const BAlignment& alignment)
1775 DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment);
1779 void
1780 BControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base,
1781 uint32 flags, const BPoint& where)
1783 // setup the text color
1784 // TODO: Should either use the ui_color(B_CONTROL_TEXT_COLOR) here,
1785 // or elliminate that constant alltogether (stippi: +1).
1787 BWindow* window = view->Window();
1788 bool isDesktop = window
1789 && window->Feel() == kPrivateDesktopWindowFeel
1790 && window->Look() == kPrivateDesktopWindowLook
1791 && view->Parent()
1792 && view->Parent()->Parent() == NULL
1793 && (flags & B_IGNORE_OUTLINE) == 0;
1795 rgb_color low;
1796 rgb_color color;
1797 rgb_color glowColor;
1799 if (isDesktop)
1800 low = view->Parent()->ViewColor();
1801 else
1802 low = base;
1804 if (low.red + low.green + low.blue > 128 * 3) {
1805 color = tint_color(low, B_DARKEN_MAX_TINT);
1806 glowColor = kWhite;
1807 } else {
1808 color = tint_color(low, B_LIGHTEN_MAX_TINT);
1809 glowColor = kBlack;
1812 if ((flags & B_DISABLED) != 0) {
1813 color.red = (uint8)(((int32)low.red + color.red + 1) / 2);
1814 color.green = (uint8)(((int32)low.green + color.green + 1) / 2);
1815 color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2);
1818 drawing_mode oldMode = view->DrawingMode();
1820 if (isDesktop) {
1821 // drawing occurs on the desktop
1822 if (fCachedWorkspace != current_workspace()) {
1823 int8 indice = 0;
1824 int32 mask;
1825 bool tmpOutline;
1826 while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces",
1827 indice, &mask) == B_OK
1828 && fBackgroundInfo.FindBool("be:bgndimginfoerasetext",
1829 indice, &tmpOutline) == B_OK) {
1831 if (((1 << current_workspace()) & mask) != 0) {
1832 fCachedOutline = tmpOutline;
1833 fCachedWorkspace = current_workspace();
1834 break;
1836 indice++;
1840 if (fCachedOutline) {
1841 BFont font;
1842 view->GetFont(&font);
1844 view->SetDrawingMode(B_OP_ALPHA);
1845 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
1846 // Draw glow or outline
1847 if (glowColor == kWhite) {
1848 font.SetFalseBoldWidth(2.0);
1849 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1851 glowColor.alpha = 30;
1852 view->SetHighColor(glowColor);
1853 view->DrawString(label, where);
1855 font.SetFalseBoldWidth(1.0);
1856 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1858 glowColor.alpha = 65;
1859 view->SetHighColor(glowColor);
1860 view->DrawString(label, where);
1862 font.SetFalseBoldWidth(0.0);
1863 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1864 } else if (glowColor == kBlack) {
1865 font.SetFalseBoldWidth(1.0);
1866 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1868 glowColor.alpha = 30;
1869 view->SetHighColor(glowColor);
1870 view->DrawString(label, where);
1872 font.SetFalseBoldWidth(0.0);
1873 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1875 glowColor.alpha = 200;
1876 view->SetHighColor(glowColor);
1877 view->DrawString(label, BPoint(where.x + 1, where.y + 1));
1882 view->SetHighColor(color);
1883 view->SetDrawingMode(B_OP_OVER);
1884 view->DrawString(label, where);
1885 view->SetDrawingMode(oldMode);
1889 void
1890 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
1891 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags)
1893 DrawLabel(view, label, icon, rect, updateRect, base, flags,
1894 DefaultLabelAlignment());
1898 void
1899 BControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
1900 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags,
1901 const BAlignment& alignment)
1903 if (!rect.Intersects(updateRect))
1904 return;
1906 if (label == NULL && icon == NULL)
1907 return;
1909 if (label == NULL) {
1910 // icon only
1911 BRect alignedRect = BLayoutUtils::AlignInFrame(rect,
1912 icon->Bounds().Size(), alignment);
1913 drawing_mode oldMode = view->DrawingMode();
1914 view->SetDrawingMode(B_OP_OVER);
1915 view->DrawBitmap(icon, alignedRect.LeftTop());
1916 view->SetDrawingMode(oldMode);
1917 return;
1920 // label, possibly with icon
1921 float availableWidth = rect.Width() + 1;
1922 float width = 0;
1923 float textOffset = 0;
1924 float height = 0;
1926 if (icon != NULL) {
1927 width = icon->Bounds().Width() + DefaultLabelSpacing() + 1;
1928 height = icon->Bounds().Height() + 1;
1929 textOffset = width;
1930 availableWidth -= textOffset;
1933 // truncate the label if necessary and get the width and height
1934 BString truncatedLabel(label);
1936 BFont font;
1937 view->GetFont(&font);
1939 font.TruncateString(&truncatedLabel, B_TRUNCATE_END, availableWidth);
1940 width += ceilf(font.StringWidth(truncatedLabel.String()));
1942 font_height fontHeight;
1943 font.GetHeight(&fontHeight);
1944 float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
1945 height = std::max(height, textHeight);
1947 // handle alignment
1948 BRect alignedRect(BLayoutUtils::AlignOnRect(rect,
1949 BSize(width - 1, height - 1), alignment));
1951 if (icon != NULL) {
1952 BPoint location(alignedRect.LeftTop());
1953 if (icon->Bounds().Height() + 1 < height)
1954 location.y += ceilf((height - icon->Bounds().Height() - 1) / 2);
1956 drawing_mode oldMode = view->DrawingMode();
1957 view->SetDrawingMode(B_OP_OVER);
1958 view->DrawBitmap(icon, location);
1959 view->SetDrawingMode(oldMode);
1962 BPoint location(alignedRect.left + textOffset,
1963 alignedRect.top + ceilf(fontHeight.ascent));
1964 if (textHeight < height)
1965 location.y += ceilf((height - textHeight) / 2);
1967 DrawLabel(view, truncatedLabel.String(), base, flags, location);
1971 void
1972 BControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left,
1973 float& _top, float& _right, float& _bottom)
1975 // All frames have the same inset on each side.
1976 float inset = 0;
1978 switch (frameType) {
1979 case B_BUTTON_FRAME:
1980 inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2;
1981 break;
1982 case B_GROUP_FRAME:
1983 case B_MENU_FIELD_FRAME:
1984 inset = 3;
1985 break;
1986 case B_SCROLL_VIEW_FRAME:
1987 case B_TEXT_CONTROL_FRAME:
1988 inset = 2;
1989 break;
1992 _left = inset;
1993 _top = inset;
1994 _right = inset;
1995 _bottom = inset;
1999 void
2000 BControlLook::GetBackgroundInsets(background_type backgroundType,
2001 uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
2003 // Most backgrounds have the same inset on each side.
2004 float inset = 0;
2006 switch (backgroundType) {
2007 case B_BUTTON_BACKGROUND:
2008 case B_MENU_BACKGROUND:
2009 case B_MENU_BAR_BACKGROUND:
2010 case B_MENU_FIELD_BACKGROUND:
2011 case B_MENU_ITEM_BACKGROUND:
2012 inset = 1;
2013 break;
2014 case B_BUTTON_WITH_POP_UP_BACKGROUND:
2015 _left = 1;
2016 _top = 1;
2017 _right = 1 + kButtonPopUpIndicatorWidth;
2018 _bottom = 1;
2019 return;
2020 case B_HORIZONTAL_SCROLL_BAR_BACKGROUND:
2021 _left = 2;
2022 _top = 0;
2023 _right = 1;
2024 _bottom = 0;
2025 return;
2026 case B_VERTICAL_SCROLL_BAR_BACKGROUND:
2027 _left = 0;
2028 _top = 2;
2029 _right = 0;
2030 _bottom = 1;
2031 return;
2034 _left = inset;
2035 _top = inset;
2036 _right = inset;
2037 _bottom = inset;
2041 void
2042 BControlLook::GetInsets(frame_type frameType, background_type backgroundType,
2043 uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
2045 GetFrameInsets(frameType, flags, _left, _top, _right, _bottom);
2047 float left, top, right, bottom;
2048 GetBackgroundInsets(backgroundType, flags, left, top, right, bottom);
2050 _left += left;
2051 _top += top;
2052 _right += right;
2053 _bottom += bottom;
2057 void
2058 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2059 const BRect& updateRect, const rgb_color& base, uint32 flags,
2060 uint32 borders, orientation orientation)
2062 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f,
2063 base, true, flags, borders, orientation);
2067 void
2068 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2069 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
2070 uint32 borders, orientation orientation)
2072 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius,
2073 radius, base, true, flags, borders, orientation);
2077 void
2078 BControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2079 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2080 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2081 uint32 flags, uint32 borders, orientation orientation)
2083 _DrawButtonBackground(view, rect, updateRect, leftTopRadius,
2084 rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags,
2085 borders, orientation);
2089 void
2090 BControlLook::SetBackgroundInfo(const BMessage& backgroundInfo)
2092 fBackgroundInfo = backgroundInfo;
2093 fCachedWorkspace = -1;
2097 // #pragma mark -
2100 void
2101 BControlLook::_DrawButtonFrame(BView* view, BRect& rect,
2102 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2103 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2104 const rgb_color& background, float contrast, float brightness,
2105 uint32 flags, uint32 borders)
2107 if (!rect.IsValid() || !rect.Intersects(updateRect))
2108 return;
2110 // save the clipping constraints of the view
2111 view->PushState();
2113 // set clipping constraints to updateRect
2114 BRegion clipping(updateRect);
2115 view->ConstrainClippingRegion(&clipping);
2117 // If the button is flat and neither activated nor otherwise highlighted
2118 // (mouse hovering or focussed), draw it flat.
2119 if ((flags & B_FLAT) != 0
2120 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0
2121 && ((flags & (B_HOVER | B_FOCUSED)) == 0
2122 || (flags & B_DISABLED) != 0)) {
2123 _DrawFrame(view, rect, background, background, background,
2124 background, borders);
2125 _DrawFrame(view, rect, background, background, background,
2126 background, borders);
2127 view->PopState();
2128 return;
2131 // outer edge colors
2132 rgb_color edgeLightColor;
2133 rgb_color edgeShadowColor;
2135 // default button frame color
2136 // TODO: B_BLEND_FRAME
2137 float defaultIndicatorTint = 1.2;
2138 if ((flags & B_DISABLED) != 0)
2139 defaultIndicatorTint = (B_NO_TINT + defaultIndicatorTint) / 2;
2141 rgb_color defaultIndicatorColor = tint_color(base, defaultIndicatorTint);
2142 rgb_color cornerBgColor;
2144 drawing_mode oldMode = view->DrawingMode();
2146 if ((flags & B_DEFAULT_BUTTON) != 0) {
2147 cornerBgColor = defaultIndicatorColor;
2148 edgeLightColor = _EdgeLightColor(defaultIndicatorColor,
2149 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2150 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
2151 edgeShadowColor = _EdgeShadowColor(defaultIndicatorColor,
2152 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2153 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
2155 // draw default button indicator
2156 view->SetHighColor(background);
2157 view->FillRect(rect);
2158 view->SetHighColor(base);
2159 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2160 rect.InsetBy(1, 1);
2162 view->SetHighColor(defaultIndicatorColor);
2163 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2164 rect.InsetBy(1, 1);
2166 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2167 rect.InsetBy(1, 1);
2168 } else {
2169 cornerBgColor = background;
2170 if ((flags & B_BLEND_FRAME) != 0) {
2171 // set the background color to transparent for the case
2172 // that we are on the desktop
2173 cornerBgColor.alpha = 0;
2174 view->SetDrawingMode(B_OP_ALPHA);
2177 edgeLightColor = _EdgeLightColor(background,
2178 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2179 brightness * 1.0, flags);
2180 edgeShadowColor = _EdgeShadowColor(background,
2181 contrast * (flags & B_DISABLED) != 0 ? 0.0 : 1.0,
2182 brightness * 1.0, flags);
2185 // frame colors
2186 rgb_color frameLightColor = _FrameLightColor(base, flags);
2187 rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2189 // rounded corners
2191 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2192 && leftTopRadius > 0) {
2193 // draw left top rounded corner
2194 BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2195 floorf(rect.left + leftTopRadius),
2196 floorf(rect.top + leftTopRadius));
2197 clipping.Exclude(leftTopCorner);
2198 _DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect,
2199 cornerBgColor, edgeShadowColor, frameLightColor);
2202 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2203 && rightTopRadius > 0) {
2204 // draw right top rounded corner
2205 BRect rightTopCorner(floorf(rect.right - rightTopRadius),
2206 floorf(rect.top), floorf(rect.right),
2207 floorf(rect.top + rightTopRadius));
2208 clipping.Exclude(rightTopCorner);
2209 _DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect,
2210 cornerBgColor, edgeShadowColor, edgeLightColor,
2211 frameLightColor, frameShadowColor);
2214 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2215 && leftBottomRadius > 0) {
2216 // draw left bottom rounded corner
2217 BRect leftBottomCorner(floorf(rect.left),
2218 floorf(rect.bottom - leftBottomRadius),
2219 floorf(rect.left + leftBottomRadius), floorf(rect.bottom));
2220 clipping.Exclude(leftBottomCorner);
2221 _DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect,
2222 cornerBgColor, edgeShadowColor, edgeLightColor,
2223 frameLightColor, frameShadowColor);
2226 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2227 && rightBottomRadius > 0) {
2228 // draw right bottom rounded corner
2229 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius),
2230 floorf(rect.bottom - rightBottomRadius), floorf(rect.right),
2231 floorf(rect.bottom));
2232 clipping.Exclude(rightBottomCorner);
2233 _DrawRoundCornerFrameRightBottom(view, rightBottomCorner,
2234 updateRect, cornerBgColor, edgeLightColor, frameShadowColor);
2237 // clip out the corners
2238 view->ConstrainClippingRegion(&clipping);
2240 // draw outer edge
2241 if ((flags & B_DEFAULT_BUTTON) != 0) {
2242 _DrawOuterResessedFrame(view, rect, defaultIndicatorColor,
2243 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2244 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9),
2245 flags, borders);
2246 } else {
2247 _DrawOuterResessedFrame(view, rect, background,
2248 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2249 brightness * 1.0, flags, borders);
2252 view->SetDrawingMode(oldMode);
2254 // draw frame
2255 if ((flags & B_BLEND_FRAME) != 0) {
2256 drawing_mode oldDrawingMode = view->DrawingMode();
2257 view->SetDrawingMode(B_OP_ALPHA);
2259 _DrawFrame(view, rect, frameLightColor, frameLightColor,
2260 frameShadowColor, frameShadowColor, borders);
2262 view->SetDrawingMode(oldDrawingMode);
2263 } else {
2264 _DrawFrame(view, rect, frameLightColor, frameLightColor,
2265 frameShadowColor, frameShadowColor, borders);
2268 // restore the clipping constraints of the view
2269 view->PopState();
2273 void
2274 BControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect,
2275 const rgb_color& base, float contrast, float brightness, uint32 flags,
2276 uint32 borders)
2278 rgb_color edgeLightColor = _EdgeLightColor(base, contrast,
2279 brightness, flags);
2280 rgb_color edgeShadowColor = _EdgeShadowColor(base, contrast,
2281 brightness, flags);
2283 if ((flags & B_BLEND_FRAME) != 0) {
2284 // assumes the background has already been painted
2285 drawing_mode oldDrawingMode = view->DrawingMode();
2286 view->SetDrawingMode(B_OP_ALPHA);
2288 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2289 edgeLightColor, edgeLightColor, borders);
2291 view->SetDrawingMode(oldDrawingMode);
2292 } else {
2293 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2294 edgeLightColor, edgeLightColor, borders);
2299 void
2300 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2301 const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2302 uint32 borders)
2304 view->BeginLineArray(4);
2306 if (borders & B_LEFT_BORDER) {
2307 view->AddLine(
2308 BPoint(rect.left, rect.bottom),
2309 BPoint(rect.left, rect.top), left);
2310 rect.left++;
2312 if (borders & B_TOP_BORDER) {
2313 view->AddLine(
2314 BPoint(rect.left, rect.top),
2315 BPoint(rect.right, rect.top), top);
2316 rect.top++;
2318 if (borders & B_RIGHT_BORDER) {
2319 view->AddLine(
2320 BPoint(rect.right, rect.top),
2321 BPoint(rect.right, rect.bottom), right);
2322 rect.right--;
2324 if (borders & B_BOTTOM_BORDER) {
2325 view->AddLine(
2326 BPoint(rect.left, rect.bottom),
2327 BPoint(rect.right, rect.bottom), bottom);
2328 rect.bottom--;
2331 view->EndLineArray();
2335 void
2336 BControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2337 const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2338 const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders)
2340 view->BeginLineArray(6);
2342 if (borders & B_TOP_BORDER) {
2343 if (borders & B_RIGHT_BORDER) {
2344 view->AddLine(
2345 BPoint(rect.left, rect.top),
2346 BPoint(rect.right - 1, rect.top), top);
2347 view->AddLine(
2348 BPoint(rect.right, rect.top),
2349 BPoint(rect.right, rect.top), rightTop);
2350 } else {
2351 view->AddLine(
2352 BPoint(rect.left, rect.top),
2353 BPoint(rect.right, rect.top), top);
2355 rect.top++;
2358 if (borders & B_LEFT_BORDER) {
2359 view->AddLine(
2360 BPoint(rect.left, rect.top),
2361 BPoint(rect.left, rect.bottom - 1), left);
2362 view->AddLine(
2363 BPoint(rect.left, rect.bottom),
2364 BPoint(rect.left, rect.bottom), leftBottom);
2365 rect.left++;
2368 if (borders & B_BOTTOM_BORDER) {
2369 view->AddLine(
2370 BPoint(rect.left, rect.bottom),
2371 BPoint(rect.right, rect.bottom), bottom);
2372 rect.bottom--;
2375 if (borders & B_RIGHT_BORDER) {
2376 view->AddLine(
2377 BPoint(rect.right, rect.bottom),
2378 BPoint(rect.right, rect.top), right);
2379 rect.right--;
2382 view->EndLineArray();
2386 void
2387 BControlLook::_DrawButtonBackground(BView* view, BRect& rect,
2388 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2389 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2390 bool popupIndicator, uint32 flags, uint32 borders, orientation orientation)
2392 if (!rect.IsValid() || !rect.Intersects(updateRect))
2393 return;
2395 // save the clipping constraints of the view
2396 view->PushState();
2398 // set clipping constraints to updateRect
2399 BRegion clipping(updateRect);
2400 view->ConstrainClippingRegion(&clipping);
2402 // If the button is flat and neither activated nor otherwise highlighted
2403 // (mouse hovering or focussed), draw it flat.
2404 if ((flags & B_FLAT) != 0
2405 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0
2406 && ((flags & (B_HOVER | B_FOCUSED)) == 0
2407 || (flags & B_DISABLED) != 0)) {
2408 _DrawFlatButtonBackground(view, rect, updateRect, base, popupIndicator,
2409 flags, borders, orientation);
2410 } else {
2411 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping,
2412 leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius,
2413 base, popupIndicator, flags, borders, orientation);
2416 // restore the clipping constraints of the view
2417 view->PopState();
2421 void
2422 BControlLook::_DrawFlatButtonBackground(BView* view, BRect& rect,
2423 const BRect& updateRect, const rgb_color& base, bool popupIndicator,
2424 uint32 flags, uint32 borders, orientation orientation)
2426 _DrawFrame(view, rect, base, base, base, base, borders);
2427 // Not an actual frame, but the method insets our rect as needed.
2429 view->SetHighColor(base);
2430 view->FillRect(rect);
2432 if (popupIndicator) {
2433 BRect indicatorRect(rect);
2434 rect.right -= kButtonPopUpIndicatorWidth;
2435 indicatorRect.left = rect.right + 3;
2436 // 2 pixels for the separator
2438 view->SetHighColor(base);
2439 view->FillRect(indicatorRect);
2441 _DrawPopUpMarker(view, indicatorRect, base, flags);
2446 void
2447 BControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect,
2448 const BRect& updateRect, BRegion& clipping, float leftTopRadius,
2449 float rightTopRadius, float leftBottomRadius, float rightBottomRadius,
2450 const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders,
2451 orientation orientation)
2453 // inner bevel colors
2454 rgb_color bevelLightColor = _BevelLightColor(base, flags);
2455 rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2457 // button background color
2458 rgb_color buttonBgColor;
2459 if ((flags & B_DISABLED) != 0)
2460 buttonBgColor = tint_color(base, 0.7);
2461 else
2462 buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT);
2464 // surface top gradient
2465 BGradientLinear fillGradient;
2466 _MakeButtonGradient(fillGradient, rect, base, flags, orientation);
2468 // rounded corners
2470 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2471 && leftTopRadius > 0) {
2472 // draw left top rounded corner
2473 BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2474 floorf(rect.left + leftTopRadius - 2.0),
2475 floorf(rect.top + leftTopRadius - 2.0));
2476 clipping.Exclude(leftTopCorner);
2477 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2478 bevelLightColor, fillGradient);
2481 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2482 && rightTopRadius > 0) {
2483 // draw right top rounded corner
2484 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2485 floorf(rect.top), floorf(rect.right),
2486 floorf(rect.top + rightTopRadius - 2.0));
2487 clipping.Exclude(rightTopCorner);
2488 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner,
2489 updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2492 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2493 && leftBottomRadius > 0) {
2494 // draw left bottom rounded corner
2495 BRect leftBottomCorner(floorf(rect.left),
2496 floorf(rect.bottom - leftBottomRadius + 2.0),
2497 floorf(rect.left + leftBottomRadius - 2.0),
2498 floorf(rect.bottom));
2499 clipping.Exclude(leftBottomCorner);
2500 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2501 updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2504 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2505 && rightBottomRadius > 0) {
2506 // draw right bottom rounded corner
2507 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2508 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2509 floorf(rect.bottom));
2510 clipping.Exclude(rightBottomCorner);
2511 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2512 updateRect, bevelShadowColor, fillGradient);
2515 // clip out the corners
2516 view->ConstrainClippingRegion(&clipping);
2518 // draw inner bevel
2520 if ((flags & B_ACTIVATED) != 0) {
2521 view->BeginLineArray(4);
2523 // shadow along left/top borders
2524 if (borders & B_LEFT_BORDER) {
2525 view->AddLine(BPoint(rect.left, rect.top),
2526 BPoint(rect.left, rect.bottom), bevelLightColor);
2527 rect.left++;
2529 if (borders & B_TOP_BORDER) {
2530 view->AddLine(BPoint(rect.left, rect.top),
2531 BPoint(rect.right, rect.top), bevelLightColor);
2532 rect.top++;
2535 // softer shadow along left/top borders
2536 if (borders & B_LEFT_BORDER) {
2537 view->AddLine(BPoint(rect.left, rect.top),
2538 BPoint(rect.left, rect.bottom), bevelShadowColor);
2539 rect.left++;
2541 if (borders & B_TOP_BORDER) {
2542 view->AddLine(BPoint(rect.left, rect.top),
2543 BPoint(rect.right, rect.top), bevelShadowColor);
2544 rect.top++;
2547 view->EndLineArray();
2548 } else {
2549 _DrawFrame(view, rect,
2550 bevelLightColor, bevelLightColor,
2551 bevelShadowColor, bevelShadowColor,
2552 buttonBgColor, buttonBgColor, borders);
2555 if (popupIndicator) {
2556 BRect indicatorRect(rect);
2557 rect.right -= kButtonPopUpIndicatorWidth;
2558 indicatorRect.left = rect.right + 3;
2559 // 2 pixels for the separator
2561 // Even when depressed we want the pop-up indicator background and
2562 // separator to cover the area up to the top.
2563 if ((flags & B_ACTIVATED) != 0)
2564 indicatorRect.top--;
2566 // draw the separator
2567 rgb_color separatorBaseColor = base;
2568 if ((flags & B_ACTIVATED) != 0)
2569 separatorBaseColor = tint_color(base, B_DARKEN_1_TINT);
2571 rgb_color separatorLightColor = _EdgeLightColor(separatorBaseColor,
2572 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags);
2573 rgb_color separatorShadowColor = _EdgeShadowColor(separatorBaseColor,
2574 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags);
2576 view->BeginLineArray(2);
2578 view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top),
2579 BPoint(indicatorRect.left - 2, indicatorRect.bottom),
2580 separatorShadowColor);
2581 view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top),
2582 BPoint(indicatorRect.left - 1, indicatorRect.bottom),
2583 separatorLightColor);
2585 view->EndLineArray();
2587 // draw background and pop-up marker
2588 _DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect,
2589 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 0);
2591 if ((flags & B_ACTIVATED) != 0)
2592 indicatorRect.top++;
2594 _DrawPopUpMarker(view, indicatorRect, base, flags);
2597 // fill in the background
2598 view->FillRect(rect, fillGradient);
2602 void
2603 BControlLook::_DrawPopUpMarker(BView* view, const BRect& rect,
2604 const rgb_color& base, uint32 flags)
2606 BPoint center(roundf((rect.left + rect.right) / 2.0),
2607 roundf((rect.top + rect.bottom) / 2.0));
2608 BPoint triangle[3];
2609 triangle[0] = center + BPoint(-2.5, -0.5);
2610 triangle[1] = center + BPoint(2.5, -0.5);
2611 triangle[2] = center + BPoint(0.0, 2.0);
2613 uint32 viewFlags = view->Flags();
2614 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
2616 rgb_color markColor;
2617 if ((flags & B_DISABLED) != 0)
2618 markColor = tint_color(base, 1.35);
2619 else
2620 markColor = tint_color(base, 1.65);
2622 view->SetHighColor(markColor);
2623 view->FillTriangle(triangle[0], triangle[1], triangle[2]);
2625 view->SetFlags(viewFlags);
2629 void
2630 BControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect,
2631 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2632 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2633 bool popupIndicator, uint32 flags)
2635 if (!rect.IsValid() || !rect.Intersects(updateRect))
2636 return;
2638 if (popupIndicator) {
2639 BRect leftRect(rect);
2640 leftRect.right -= 10;
2642 BRect rightRect(rect);
2643 rightRect.left = rightRect.right - 9;
2645 _DrawMenuFieldBackgroundInside(view, leftRect, updateRect,
2646 leftTopRadius, 0.0f, leftBottomRadius, 0.0f, base, flags,
2647 B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER);
2649 _DrawMenuFieldBackgroundInside(view, rightRect, updateRect,
2650 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags,
2651 B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER);
2653 _DrawPopUpMarker(view, rightRect, base, flags);
2655 // draw a line on the left of the popup frame
2656 rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2657 view->SetHighColor(bevelShadowColor);
2658 BPoint leftTopCorner(floorf(rightRect.left - 1.0),
2659 floorf(rightRect.top - 1.0));
2660 BPoint leftBottomCorner(floorf(rightRect.left - 1.0),
2661 floorf(rightRect.bottom + 1.0));
2662 view->StrokeLine(leftTopCorner, leftBottomCorner);
2664 rect = leftRect;
2665 } else {
2666 _DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius,
2667 rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags);
2672 void
2673 BControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect,
2674 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2675 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2676 uint32 flags, uint32 borders)
2678 if (!rect.IsValid() || !rect.Intersects(updateRect))
2679 return;
2681 // save the clipping constraints of the view
2682 view->PushState();
2684 // set clipping constraints to updateRect
2685 BRegion clipping(updateRect);
2686 view->ConstrainClippingRegion(&clipping);
2688 // frame colors
2689 rgb_color frameLightColor = _FrameLightColor(base, flags);
2690 rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2692 // indicator background color
2693 rgb_color indicatorBase;
2694 if ((borders & B_LEFT_BORDER) != 0)
2695 indicatorBase = base;
2696 else {
2697 if ((flags & B_DISABLED) != 0)
2698 indicatorBase = tint_color(base, 1.05);
2699 else
2700 indicatorBase = tint_color(base, 1.12);
2703 // bevel colors
2704 rgb_color cornerColor = tint_color(indicatorBase, 0.85);
2705 rgb_color bevelColor1 = tint_color(indicatorBase, 0.3);
2706 rgb_color bevelColor2 = tint_color(indicatorBase, 0.5);
2707 rgb_color bevelColor3 = tint_color(indicatorBase, 1.03);
2709 if ((flags & B_DISABLED) != 0) {
2710 cornerColor = tint_color(indicatorBase, 0.8);
2711 bevelColor1 = tint_color(indicatorBase, 0.7);
2712 bevelColor2 = tint_color(indicatorBase, 0.8);
2713 bevelColor3 = tint_color(indicatorBase, 1.01);
2714 } else {
2715 cornerColor = tint_color(indicatorBase, 0.85);
2716 bevelColor1 = tint_color(indicatorBase, 0.3);
2717 bevelColor2 = tint_color(indicatorBase, 0.5);
2718 bevelColor3 = tint_color(indicatorBase, 1.03);
2721 // surface top gradient
2722 BGradientLinear fillGradient;
2723 _MakeButtonGradient(fillGradient, rect, indicatorBase, flags);
2725 // rounded corners
2727 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2728 && leftTopRadius > 0) {
2729 // draw left top rounded corner
2730 BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2731 floorf(rect.left + leftTopRadius - 2.0),
2732 floorf(rect.top + leftTopRadius - 2.0));
2733 clipping.Exclude(leftTopCorner);
2735 BRegion cornerClipping(leftTopCorner);
2736 view->ConstrainClippingRegion(&cornerClipping);
2738 BRect ellipseRect(leftTopCorner);
2739 ellipseRect.InsetBy(-1.0, -1.0);
2740 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2741 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2743 // draw the frame (again)
2744 view->SetHighColor(frameLightColor);
2745 view->FillEllipse(ellipseRect);
2747 // draw the bevel and background
2748 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2749 bevelColor1, fillGradient);
2752 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2753 && rightTopRadius > 0) {
2754 // draw right top rounded corner
2755 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2756 floorf(rect.top), floorf(rect.right),
2757 floorf(rect.top + rightTopRadius - 2.0));
2758 clipping.Exclude(rightTopCorner);
2760 BRegion cornerClipping(rightTopCorner);
2761 view->ConstrainClippingRegion(&cornerClipping);
2763 BRect ellipseRect(rightTopCorner);
2764 ellipseRect.InsetBy(-1.0, -1.0);
2765 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2766 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2768 // draw the frame (again)
2769 if (frameLightColor == frameShadowColor) {
2770 view->SetHighColor(frameLightColor);
2771 view->FillEllipse(ellipseRect);
2772 } else {
2773 BGradientLinear gradient;
2774 gradient.AddColor(frameLightColor, 0);
2775 gradient.AddColor(frameShadowColor, 255);
2776 gradient.SetStart(rightTopCorner.LeftTop());
2777 gradient.SetEnd(rightTopCorner.RightBottom());
2778 view->FillEllipse(ellipseRect, gradient);
2781 // draw the bevel and background
2782 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect,
2783 bevelColor1, bevelColor3, fillGradient);
2786 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2787 && leftBottomRadius > 0) {
2788 // draw left bottom rounded corner
2789 BRect leftBottomCorner(floorf(rect.left),
2790 floorf(rect.bottom - leftBottomRadius + 2.0),
2791 floorf(rect.left + leftBottomRadius - 2.0),
2792 floorf(rect.bottom));
2793 clipping.Exclude(leftBottomCorner);
2795 BRegion cornerClipping(leftBottomCorner);
2796 view->ConstrainClippingRegion(&cornerClipping);
2798 BRect ellipseRect(leftBottomCorner);
2799 ellipseRect.InsetBy(-1.0, -1.0);
2800 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2801 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2803 // draw the frame (again)
2804 if (frameLightColor == frameShadowColor) {
2805 view->SetHighColor(frameLightColor);
2806 view->FillEllipse(ellipseRect);
2807 } else {
2808 BGradientLinear gradient;
2809 gradient.AddColor(frameLightColor, 0);
2810 gradient.AddColor(frameShadowColor, 255);
2811 gradient.SetStart(leftBottomCorner.LeftTop());
2812 gradient.SetEnd(leftBottomCorner.RightBottom());
2813 view->FillEllipse(ellipseRect, gradient);
2816 // draw the bevel and background
2817 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2818 updateRect, bevelColor2, bevelColor3, fillGradient);
2821 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2822 && rightBottomRadius > 0) {
2823 // draw right bottom rounded corner
2824 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2825 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2826 floorf(rect.bottom));
2827 clipping.Exclude(rightBottomCorner);
2829 BRegion cornerClipping(rightBottomCorner);
2830 view->ConstrainClippingRegion(&cornerClipping);
2832 BRect ellipseRect(rightBottomCorner);
2833 ellipseRect.InsetBy(-1.0, -1.0);
2834 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2835 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2837 // draw the frame (again)
2838 view->SetHighColor(frameShadowColor);
2839 view->FillEllipse(ellipseRect);
2841 // draw the bevel and background
2842 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2843 updateRect, bevelColor3, fillGradient);
2846 // clip out the corners
2847 view->ConstrainClippingRegion(&clipping);
2849 // draw the bevel
2850 _DrawFrame(view, rect,
2851 bevelColor2, bevelColor1,
2852 bevelColor3, bevelColor3,
2853 cornerColor, cornerColor,
2854 borders);
2856 // fill in the background
2857 view->FillRect(rect, fillGradient);
2859 // restore the clipping constraints of the view
2860 view->PopState();
2864 void
2865 BControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& cornerRect,
2866 const BRect& updateRect, const rgb_color& background,
2867 const rgb_color& edgeColor, const rgb_color& frameColor,
2868 const rgb_color& bevelColor, const BGradientLinear& fillGradient)
2870 _DrawRoundCornerFrameLeftTop(view, cornerRect, updateRect,
2871 background, edgeColor, frameColor);
2872 _DrawRoundCornerBackgroundLeftTop(view, cornerRect, updateRect,
2873 bevelColor, fillGradient);
2877 void
2878 BControlLook::_DrawRoundCornerFrameLeftTop(BView* view, BRect& cornerRect,
2879 const BRect& updateRect, const rgb_color& background,
2880 const rgb_color& edgeColor, const rgb_color& frameColor)
2882 // constrain clipping region to corner
2883 BRegion clipping(cornerRect);
2884 view->ConstrainClippingRegion(&clipping);
2886 // background
2887 view->SetHighColor(background);
2888 view->FillRect(cornerRect);
2890 // outer edge
2891 BRect ellipseRect(cornerRect);
2892 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2893 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2895 view->SetHighColor(edgeColor);
2896 view->FillEllipse(ellipseRect);
2898 // frame
2899 ellipseRect.InsetBy(1, 1);
2900 cornerRect.left++;
2901 cornerRect.top++;
2902 view->SetHighColor(frameColor);
2903 view->FillEllipse(ellipseRect);
2905 // prepare for bevel
2906 cornerRect.left++;
2907 cornerRect.top++;
2911 void
2912 BControlLook::_DrawRoundCornerBackgroundLeftTop(BView* view, BRect& cornerRect,
2913 const BRect& updateRect, const rgb_color& bevelColor,
2914 const BGradientLinear& fillGradient)
2916 // constrain clipping region to corner
2917 BRegion clipping(cornerRect);
2918 view->ConstrainClippingRegion(&clipping);
2920 BRect ellipseRect(cornerRect);
2921 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2922 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2924 // bevel
2925 view->SetHighColor(bevelColor);
2926 view->FillEllipse(ellipseRect);
2928 // gradient
2929 ellipseRect.InsetBy(1, 1);
2930 view->FillEllipse(ellipseRect, fillGradient);
2934 void
2935 BControlLook::_DrawRoundCornerRightTop(BView* view, BRect& cornerRect,
2936 const BRect& updateRect, const rgb_color& background,
2937 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2938 const rgb_color& frameTopColor, const rgb_color& frameRightColor,
2939 const rgb_color& bevelTopColor, const rgb_color& bevelRightColor,
2940 const BGradientLinear& fillGradient)
2942 _DrawRoundCornerFrameRightTop(view, cornerRect, updateRect,
2943 background, edgeTopColor, edgeRightColor, frameTopColor,
2944 frameRightColor);
2945 _DrawRoundCornerBackgroundRightTop(view, cornerRect, updateRect,
2946 bevelTopColor, bevelRightColor, fillGradient);
2950 void
2951 BControlLook::_DrawRoundCornerFrameRightTop(BView* view, BRect& cornerRect,
2952 const BRect& updateRect, const rgb_color& background,
2953 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
2954 const rgb_color& frameTopColor, const rgb_color& frameRightColor)
2956 // constrain clipping region to corner
2957 BRegion clipping(cornerRect);
2958 view->ConstrainClippingRegion(&clipping);
2960 // background
2961 view->SetHighColor(background);
2962 view->FillRect(cornerRect);
2964 // outer edge
2965 BRect ellipseRect(cornerRect);
2966 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2967 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2969 BGradientLinear gradient;
2970 gradient.AddColor(edgeTopColor, 0);
2971 gradient.AddColor(edgeRightColor, 255);
2972 gradient.SetStart(cornerRect.LeftTop());
2973 gradient.SetEnd(cornerRect.RightBottom());
2974 view->FillEllipse(ellipseRect, gradient);
2976 // frame
2977 ellipseRect.InsetBy(1, 1);
2978 cornerRect.right--;
2979 cornerRect.top++;
2980 if (frameTopColor == frameRightColor) {
2981 view->SetHighColor(frameTopColor);
2982 view->FillEllipse(ellipseRect);
2983 } else {
2984 gradient.SetColor(0, frameTopColor);
2985 gradient.SetColor(1, frameRightColor);
2986 gradient.SetStart(cornerRect.LeftTop());
2987 gradient.SetEnd(cornerRect.RightBottom());
2988 view->FillEllipse(ellipseRect, gradient);
2991 // prepare for bevel
2992 cornerRect.right--;
2993 cornerRect.top++;
2997 void
2998 BControlLook::_DrawRoundCornerBackgroundRightTop(BView* view, BRect& cornerRect,
2999 const BRect& updateRect, const rgb_color& bevelTopColor,
3000 const rgb_color& bevelRightColor, const BGradientLinear& fillGradient)
3002 // constrain clipping region to corner
3003 BRegion clipping(cornerRect);
3004 view->ConstrainClippingRegion(&clipping);
3006 BRect ellipseRect(cornerRect);
3007 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3008 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
3010 // bevel
3011 BGradientLinear gradient;
3012 gradient.AddColor(bevelTopColor, 0);
3013 gradient.AddColor(bevelRightColor, 255);
3014 gradient.SetStart(cornerRect.LeftTop());
3015 gradient.SetEnd(cornerRect.RightBottom());
3016 view->FillEllipse(ellipseRect, gradient);
3018 // gradient
3019 ellipseRect.InsetBy(1, 1);
3020 view->FillEllipse(ellipseRect, fillGradient);
3024 void
3025 BControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& cornerRect,
3026 const BRect& updateRect, const rgb_color& background,
3027 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
3028 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor,
3029 const rgb_color& bevelLeftColor, const rgb_color& bevelBottomColor,
3030 const BGradientLinear& fillGradient)
3032 _DrawRoundCornerFrameLeftBottom(view, cornerRect, updateRect,
3033 background, edgeLeftColor, edgeBottomColor, frameLeftColor,
3034 frameBottomColor);
3035 _DrawRoundCornerBackgroundLeftBottom(view, cornerRect, updateRect,
3036 bevelLeftColor, bevelBottomColor, fillGradient);
3040 void
3041 BControlLook::_DrawRoundCornerFrameLeftBottom(BView* view, BRect& cornerRect,
3042 const BRect& updateRect, const rgb_color& background,
3043 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
3044 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor)
3046 // constrain clipping region to corner
3047 BRegion clipping(cornerRect);
3048 view->ConstrainClippingRegion(&clipping);
3050 // background
3051 view->SetHighColor(background);
3052 view->FillRect(cornerRect);
3054 // outer edge
3055 BRect ellipseRect(cornerRect);
3056 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
3057 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3059 BGradientLinear gradient;
3060 gradient.AddColor(edgeLeftColor, 0);
3061 gradient.AddColor(edgeBottomColor, 255);
3062 gradient.SetStart(cornerRect.LeftTop());
3063 gradient.SetEnd(cornerRect.RightBottom());
3064 view->FillEllipse(ellipseRect, gradient);
3066 // frame
3067 ellipseRect.InsetBy(1, 1);
3068 cornerRect.left++;
3069 cornerRect.bottom--;
3070 if (frameLeftColor == frameBottomColor) {
3071 view->SetHighColor(frameLeftColor);
3072 view->FillEllipse(ellipseRect);
3073 } else {
3074 gradient.SetColor(0, frameLeftColor);
3075 gradient.SetColor(1, frameBottomColor);
3076 gradient.SetStart(cornerRect.LeftTop());
3077 gradient.SetEnd(cornerRect.RightBottom());
3078 view->FillEllipse(ellipseRect, gradient);
3081 // prepare for bevel
3082 cornerRect.left++;
3083 cornerRect.bottom--;
3087 void
3088 BControlLook::_DrawRoundCornerBackgroundLeftBottom(BView* view, BRect& cornerRect,
3089 const BRect& updateRect, const rgb_color& bevelLeftColor,
3090 const rgb_color& bevelBottomColor, const BGradientLinear& fillGradient)
3092 // constrain clipping region to corner
3093 BRegion clipping(cornerRect);
3094 view->ConstrainClippingRegion(&clipping);
3096 BRect ellipseRect(cornerRect);
3097 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
3098 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3100 // bevel
3101 BGradientLinear gradient;
3102 gradient.AddColor(bevelLeftColor, 0);
3103 gradient.AddColor(bevelBottomColor, 255);
3104 gradient.SetStart(cornerRect.LeftTop());
3105 gradient.SetEnd(cornerRect.RightBottom());
3106 view->FillEllipse(ellipseRect, gradient);
3108 // gradient
3109 ellipseRect.InsetBy(1, 1);
3110 view->FillEllipse(ellipseRect, fillGradient);
3114 void
3115 BControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& cornerRect,
3116 const BRect& updateRect, const rgb_color& background,
3117 const rgb_color& edgeColor, const rgb_color& frameColor,
3118 const rgb_color& bevelColor, const BGradientLinear& fillGradient)
3120 _DrawRoundCornerFrameRightBottom(view, cornerRect, updateRect,
3121 background, edgeColor, frameColor);
3122 _DrawRoundCornerBackgroundRightBottom(view, cornerRect, updateRect,
3123 bevelColor, fillGradient);
3127 void
3128 BControlLook::_DrawRoundCornerFrameRightBottom(BView* view, BRect& cornerRect,
3129 const BRect& updateRect, const rgb_color& background,
3130 const rgb_color& edgeColor, const rgb_color& frameColor)
3132 // constrain clipping region to corner
3133 BRegion clipping(cornerRect);
3134 view->ConstrainClippingRegion(&clipping);
3136 // background
3137 view->SetHighColor(background);
3138 view->FillRect(cornerRect);
3140 // outer edge
3141 BRect ellipseRect(cornerRect);
3142 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3143 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3145 view->SetHighColor(edgeColor);
3146 view->FillEllipse(ellipseRect);
3148 // frame
3149 ellipseRect.InsetBy(1, 1);
3150 cornerRect.right--;
3151 cornerRect.bottom++;
3152 view->SetHighColor(frameColor);
3153 view->FillEllipse(ellipseRect);
3155 // prepare for bevel
3156 cornerRect.left++;
3157 cornerRect.bottom--;
3161 void
3162 BControlLook::_DrawRoundCornerBackgroundRightBottom(BView* view,
3163 BRect& cornerRect, const BRect& updateRect, const rgb_color& bevelColor,
3164 const BGradientLinear& fillGradient)
3166 // constrain clipping region to corner
3167 BRegion clipping(cornerRect);
3168 view->ConstrainClippingRegion(&clipping);
3170 BRect ellipseRect(cornerRect);
3171 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3172 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3174 // bevel
3175 view->SetHighColor(bevelColor);
3176 view->FillEllipse(ellipseRect);
3178 // gradient
3179 ellipseRect.InsetBy(1, 1);
3180 view->FillEllipse(ellipseRect, fillGradient);
3184 void
3185 BControlLook::_DrawRoundBarCorner(BView* view, BRect& rect,
3186 const BRect& updateRect,
3187 const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor,
3188 const rgb_color& frameLightColor, const rgb_color& frameShadowColor,
3189 const rgb_color& fillLightColor, const rgb_color& fillShadowColor,
3190 float leftInset, float topInset, float rightInset, float bottomInset,
3191 orientation orientation)
3193 if (!rect.IsValid() || !rect.Intersects(updateRect))
3194 return;
3196 BGradientLinear gradient;
3197 gradient.AddColor(edgeShadowColor, 0);
3198 gradient.AddColor(edgeLightColor, 255);
3199 gradient.SetStart(rect.LeftTop());
3200 if (orientation == B_HORIZONTAL)
3201 gradient.SetEnd(rect.LeftBottom());
3202 else
3203 gradient.SetEnd(rect.RightTop());
3205 view->FillEllipse(rect, gradient);
3207 rect.left += leftInset;
3208 rect.top += topInset;
3209 rect.right += rightInset;
3210 rect.bottom += bottomInset;
3212 gradient.MakeEmpty();
3213 gradient.AddColor(frameShadowColor, 0);
3214 gradient.AddColor(frameLightColor, 255);
3215 gradient.SetStart(rect.LeftTop());
3216 if (orientation == B_HORIZONTAL)
3217 gradient.SetEnd(rect.LeftBottom());
3218 else
3219 gradient.SetEnd(rect.RightTop());
3221 view->FillEllipse(rect, gradient);
3223 rect.left += leftInset;
3224 rect.top += topInset;
3225 rect.right += rightInset;
3226 rect.bottom += bottomInset;
3228 gradient.MakeEmpty();
3229 gradient.AddColor(fillShadowColor, 0);
3230 gradient.AddColor(fillLightColor, 255);
3231 gradient.SetStart(rect.LeftTop());
3232 if (orientation == B_HORIZONTAL)
3233 gradient.SetEnd(rect.LeftBottom());
3234 else
3235 gradient.SetEnd(rect.RightTop());
3237 view->FillEllipse(rect, gradient);
3241 rgb_color
3242 BControlLook::_EdgeLightColor(const rgb_color& base, float contrast,
3243 float brightness, uint32 flags)
3245 rgb_color edgeLightColor;
3247 if ((flags & B_BLEND_FRAME) != 0) {
3248 uint8 alpha = uint8(20 * contrast);
3249 uint8 white = uint8(255 * brightness);
3251 edgeLightColor = (rgb_color){ white, white, white, alpha };
3252 } else {
3253 // colors
3254 float tintLight = kEdgeBevelLightTint;
3256 if (contrast == 0.0)
3257 tintLight = B_NO_TINT;
3258 else if (contrast != 1.0)
3259 tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast;
3261 edgeLightColor = tint_color(base, tintLight);
3263 if (brightness < 1.0) {
3264 edgeLightColor.red = uint8(edgeLightColor.red * brightness);
3265 edgeLightColor.green = uint8(edgeLightColor.green * brightness);
3266 edgeLightColor.blue = uint8(edgeLightColor.blue * brightness);
3270 return edgeLightColor;
3274 rgb_color
3275 BControlLook::_EdgeShadowColor(const rgb_color& base, float contrast,
3276 float brightness, uint32 flags)
3278 rgb_color edgeShadowColor;
3280 if ((flags & B_BLEND_FRAME) != 0) {
3281 uint8 alpha = uint8(20 * contrast);
3282 edgeShadowColor = (rgb_color){ 0, 0, 0, alpha };
3283 } else {
3284 float tintShadow = kEdgeBevelShadowTint;
3286 if (contrast == 0.0)
3287 tintShadow = B_NO_TINT;
3288 else if (contrast != 1.0)
3289 tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast;
3291 edgeShadowColor = tint_color(base, tintShadow);
3293 if (brightness < 1.0) {
3294 edgeShadowColor.red = uint8(edgeShadowColor.red * brightness);
3295 edgeShadowColor.green = uint8(edgeShadowColor.green * brightness);
3296 edgeShadowColor.blue = uint8(edgeShadowColor.blue * brightness);
3300 return edgeShadowColor;
3304 rgb_color
3305 BControlLook::_FrameLightColor(const rgb_color& base, uint32 flags)
3307 if ((flags & B_FOCUSED) != 0)
3308 return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3310 if ((flags & B_ACTIVATED) != 0)
3311 return _FrameShadowColor(base, flags & ~B_ACTIVATED);
3313 rgb_color frameLightColor;
3315 if ((flags & B_DISABLED) != 0) {
3316 // TODO: B_BLEND_FRAME
3317 frameLightColor = tint_color(base, 1.145);
3319 if ((flags & B_DEFAULT_BUTTON) != 0)
3320 frameLightColor = tint_color(frameLightColor, 1.14);
3321 } else {
3322 if ((flags & B_BLEND_FRAME) != 0)
3323 frameLightColor = (rgb_color){ 0, 0, 0, 75 };
3324 else
3325 frameLightColor = tint_color(base, 1.33);
3327 if ((flags & B_DEFAULT_BUTTON) != 0)
3328 frameLightColor = tint_color(frameLightColor, 1.35);
3331 return frameLightColor;
3335 rgb_color
3336 BControlLook::_FrameShadowColor(const rgb_color& base, uint32 flags)
3338 if ((flags & B_FOCUSED) != 0)
3339 return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3341 if ((flags & B_ACTIVATED) != 0)
3342 return _FrameLightColor(base, flags & ~B_ACTIVATED);
3344 rgb_color frameShadowColor;
3346 if ((flags & B_DISABLED) != 0) {
3347 // TODO: B_BLEND_FRAME
3348 frameShadowColor = tint_color(base, 1.24);
3350 if ((flags & B_DEFAULT_BUTTON) != 0) {
3351 frameShadowColor = tint_color(base, 1.145);
3352 frameShadowColor = tint_color(frameShadowColor, 1.12);
3354 } else {
3355 if ((flags & B_DEFAULT_BUTTON) != 0) {
3356 if ((flags & B_BLEND_FRAME) != 0)
3357 frameShadowColor = (rgb_color){ 0, 0, 0, 75 };
3358 else
3359 frameShadowColor = tint_color(base, 1.33);
3361 frameShadowColor = tint_color(frameShadowColor, 1.5);
3362 } else {
3363 if ((flags & B_BLEND_FRAME) != 0)
3364 frameShadowColor = (rgb_color){ 0, 0, 0, 95 };
3365 else
3366 frameShadowColor = tint_color(base, 1.47);
3370 return frameShadowColor;
3374 rgb_color
3375 BControlLook::_BevelLightColor(const rgb_color& base, uint32 flags)
3377 rgb_color bevelLightColor = tint_color(base, 0.2);
3379 if ((flags & B_DISABLED) != 0)
3380 bevelLightColor = tint_color(base, B_LIGHTEN_1_TINT);
3382 if ((flags & B_ACTIVATED) != 0)
3383 bevelLightColor = tint_color(base, B_DARKEN_1_TINT);
3385 return bevelLightColor;
3389 rgb_color
3390 BControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags)
3392 rgb_color bevelShadowColor = tint_color(base, 1.08);
3394 if ((flags & B_DISABLED) != 0)
3395 bevelShadowColor = base;
3397 if ((flags & B_ACTIVATED) != 0)
3398 bevelShadowColor = tint_color(base, B_DARKEN_1_TINT);
3400 return bevelShadowColor;
3404 void
3405 BControlLook::_FillGradient(BView* view, const BRect& rect,
3406 const rgb_color& base, float topTint, float bottomTint,
3407 orientation orientation)
3409 BGradientLinear gradient;
3410 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3411 view->FillRect(rect, gradient);
3415 void
3416 BControlLook::_FillGlossyGradient(BView* view, const BRect& rect,
3417 const rgb_color& base, float topTint, float middle1Tint,
3418 float middle2Tint, float bottomTint, orientation orientation)
3420 BGradientLinear gradient;
3421 _MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint,
3422 middle2Tint, bottomTint, orientation);
3423 view->FillRect(rect, gradient);
3427 void
3428 BControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect,
3429 const rgb_color& base, float topTint, float bottomTint,
3430 orientation orientation) const
3432 gradient.AddColor(tint_color(base, topTint), 0);
3433 gradient.AddColor(tint_color(base, bottomTint), 255);
3434 gradient.SetStart(rect.LeftTop());
3435 if (orientation == B_HORIZONTAL)
3436 gradient.SetEnd(rect.LeftBottom());
3437 else
3438 gradient.SetEnd(rect.RightTop());
3442 void
3443 BControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect,
3444 const rgb_color& base, float topTint, float middle1Tint,
3445 float middle2Tint, float bottomTint,
3446 orientation orientation) const
3448 gradient.AddColor(tint_color(base, topTint), 0);
3449 gradient.AddColor(tint_color(base, middle1Tint), 132);
3450 gradient.AddColor(tint_color(base, middle2Tint), 136);
3451 gradient.AddColor(tint_color(base, bottomTint), 255);
3452 gradient.SetStart(rect.LeftTop());
3453 if (orientation == B_HORIZONTAL)
3454 gradient.SetEnd(rect.LeftBottom());
3455 else
3456 gradient.SetEnd(rect.RightTop());
3460 void
3461 BControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect,
3462 const rgb_color& base, uint32 flags, orientation orientation) const
3464 float topTint = 0.49;
3465 float middleTint1 = 0.62;
3466 float middleTint2 = 0.76;
3467 float bottomTint = 0.90;
3469 if ((flags & B_ACTIVATED) != 0) {
3470 topTint = 1.11;
3471 bottomTint = 1.08;
3474 if ((flags & B_DISABLED) != 0) {
3475 topTint = (topTint + B_NO_TINT) / 2;
3476 middleTint1 = (middleTint1 + B_NO_TINT) / 2;
3477 middleTint2 = (middleTint2 + B_NO_TINT) / 2;
3478 bottomTint = (bottomTint + B_NO_TINT) / 2;
3479 } else if ((flags & B_HOVER) != 0) {
3480 topTint *= kHoverTintFactor;
3481 middleTint1 *= kHoverTintFactor;
3482 middleTint2 *= kHoverTintFactor;
3483 bottomTint *= kHoverTintFactor;
3486 if ((flags & B_ACTIVATED) != 0) {
3487 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3488 } else {
3489 _MakeGlossyGradient(gradient, rect, base, topTint, middleTint1,
3490 middleTint2, bottomTint, orientation);
3496 bool
3497 BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
3498 rgb_color& color, uint32 flags) const
3500 if ((flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED)) == 0) {
3501 // no mark to be drawn at all
3502 return false;
3505 color = ui_color(B_CONTROL_MARK_COLOR);
3507 float mix = 1.0;
3509 if ((flags & B_DISABLED) != 0) {
3510 // activated, but disabled
3511 mix = 0.4;
3512 } else if ((flags & B_CLICKED) != 0) {
3513 if ((flags & B_ACTIVATED) != 0) {
3514 // losing activation
3515 mix = 0.7;
3516 } else {
3517 // becoming activated (or losing partial activation)
3518 mix = 0.3;
3520 } else if ((flags & B_PARTIALLY_ACTIVATED) != 0) {
3521 // partially activated
3522 mix = 0.5;
3523 } else {
3524 // simply activated
3527 color.red = uint8(color.red * mix + base.red * (1.0 - mix));
3528 color.green = uint8(color.green * mix + base.green * (1.0 - mix));
3529 color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix));
3531 return true;
3535 // NOTE: May come from a add-on in the future. Initialized in
3536 // InterfaceDefs.cpp
3537 BControlLook* be_control_look = NULL;
3540 } // namespace BPrivate