HaikuDepot: notify work status from main window
[haiku.git] / src / kits / interface / HaikuControlLook.cpp
blobcdbb1e1e30036054d3efdbebb0ab5869e82ed61f
1 /*
2 * Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
3 * Copyright 2012-2017 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 <HaikuControlLook.h>
14 #include <algorithm>
16 #include <Bitmap.h>
17 #include <Control.h>
18 #include <GradientLinear.h>
19 #include <LayoutUtils.h>
20 #include <Region.h>
21 #include <Shape.h>
22 #include <String.h>
23 #include <View.h>
24 #include <Window.h>
25 #include <WindowPrivate.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 HaikuControlLook::HaikuControlLook()
40 fCachedOutline(false)
45 HaikuControlLook::~HaikuControlLook()
50 BAlignment
51 HaikuControlLook::DefaultLabelAlignment() const
53 return BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER);
57 float
58 HaikuControlLook::DefaultLabelSpacing() const
60 return ceilf(be_plain_font->Size() / 2.0);
64 float
65 HaikuControlLook::DefaultItemSpacing() const
67 return ceilf(be_plain_font->Size() * 0.85);
71 uint32
72 HaikuControlLook::Flags(BControl* control) const
74 uint32 flags = B_IS_CONTROL;
76 if (!control->IsEnabled())
77 flags |= B_DISABLED;
79 if (control->IsFocus() && control->Window() != NULL
80 && control->Window()->IsActive()) {
81 flags |= B_FOCUSED;
84 switch (control->Value()) {
85 case B_CONTROL_ON:
86 flags |= B_ACTIVATED;
87 break;
88 case B_CONTROL_PARTIALLY_ON:
89 flags |= B_PARTIALLY_ACTIVATED;
90 break;
93 if (control->Parent() != NULL
94 && (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) {
95 // In this constellation, assume we want to render the control
96 // against the already existing view contents of the parent view.
97 flags |= B_BLEND_FRAME;
100 return flags;
104 // #pragma mark -
107 void
108 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
109 const rgb_color& base, const rgb_color& background, uint32 flags,
110 uint32 borders)
112 _DrawButtonFrame(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, base,
113 background, 1.0, 1.0, flags, borders);
117 void
118 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
119 float radius, const rgb_color& base, const rgb_color& background, uint32 flags,
120 uint32 borders)
122 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius,
123 base, background, 1.0, 1.0, flags, borders);
127 void
128 HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect,
129 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
130 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
131 const rgb_color& background, uint32 flags,
132 uint32 borders)
134 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius,
135 leftBottomRadius, rightBottomRadius, base, background,
136 1.0, 1.0, flags, borders);
140 void
141 HaikuControlLook::DrawButtonBackground(BView* view, BRect& rect,
142 const BRect& updateRect, const rgb_color& base, uint32 flags,
143 uint32 borders, orientation orientation)
145 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f,
146 base, false, flags, borders, orientation);
150 void
151 HaikuControlLook::DrawButtonBackground(BView* view, BRect& rect,
152 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
153 uint32 borders, orientation orientation)
155 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius,
156 radius, base, false, flags, borders, orientation);
160 void
161 HaikuControlLook::DrawButtonBackground(BView* view, BRect& rect,
162 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
163 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
164 uint32 flags, uint32 borders, orientation orientation)
166 _DrawButtonBackground(view, rect, updateRect, leftTopRadius,
167 rightTopRadius, leftBottomRadius, rightBottomRadius, base, false, flags,
168 borders, orientation);
172 void
173 HaikuControlLook::DrawMenuBarBackground(BView* view, BRect& rect,
174 const BRect& updateRect, const rgb_color& base, uint32 flags,
175 uint32 borders)
177 if (!rect.IsValid() || !rect.Intersects(updateRect))
178 return;
180 // the surface edges
182 // colors
183 float topTint;
184 float bottomTint;
186 if ((flags & B_ACTIVATED) != 0) {
187 rgb_color bevelColor1 = tint_color(base, 1.40);
188 rgb_color bevelColor2 = tint_color(base, 1.25);
190 topTint = 1.25;
191 bottomTint = 1.20;
193 _DrawFrame(view, rect,
194 bevelColor1, bevelColor1,
195 bevelColor2, bevelColor2,
196 borders & B_TOP_BORDER);
197 } else {
198 rgb_color cornerColor = tint_color(base, 0.9);
199 rgb_color bevelColorTop = tint_color(base, 0.5);
200 rgb_color bevelColorLeft = tint_color(base, 0.7);
201 rgb_color bevelColorRightBottom = tint_color(base, 1.08);
203 topTint = 0.69;
204 bottomTint = 1.03;
206 _DrawFrame(view, rect,
207 bevelColorLeft, bevelColorTop,
208 bevelColorRightBottom, bevelColorRightBottom,
209 cornerColor, cornerColor,
210 borders);
213 // draw surface top
214 _FillGradient(view, rect, base, topTint, bottomTint);
218 void
219 HaikuControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
220 const BRect& updateRect, const rgb_color& base,
221 const rgb_color& background, uint32 flags, uint32 borders)
223 _DrawButtonFrame(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f, base,
224 background, 0.6, 1.0, flags, borders);
228 void
229 HaikuControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
230 const BRect& updateRect, float radius, const rgb_color& base,
231 const rgb_color& background, uint32 flags, uint32 borders)
233 _DrawButtonFrame(view, rect, updateRect, radius, radius, radius, radius,
234 base, background, 0.6, 1.0, flags, borders);
238 void
239 HaikuControlLook::DrawMenuFieldFrame(BView* view, BRect& rect,
240 const BRect& updateRect, float leftTopRadius,
241 float rightTopRadius, float leftBottomRadius,
242 float rightBottomRadius, const rgb_color& base,
243 const rgb_color& background, uint32 flags, uint32 borders)
245 _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius,
246 leftBottomRadius, rightBottomRadius, base, background, 0.6, 1.0,
247 flags, borders);
251 void
252 HaikuControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
253 const BRect& updateRect, const rgb_color& base, bool popupIndicator,
254 uint32 flags)
256 _DrawMenuFieldBackgroundOutside(view, rect, updateRect,
257 0.0f, 0.0f, 0.0f, 0.0f, base, popupIndicator, flags);
261 void
262 HaikuControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
263 const BRect& updateRect, const rgb_color& base, uint32 flags,
264 uint32 borders)
266 _DrawMenuFieldBackgroundInside(view, rect, updateRect,
267 0.0f, 0.0f, 0.0f, 0.0f, base, flags, borders);
271 void
272 HaikuControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
273 const BRect& updateRect, float radius, const rgb_color& base,
274 bool popupIndicator, uint32 flags)
276 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius,
277 radius, radius, base, popupIndicator, flags);
281 void
282 HaikuControlLook::DrawMenuFieldBackground(BView* view, BRect& rect,
283 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
284 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
285 bool popupIndicator, uint32 flags)
287 _DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius,
288 rightTopRadius, leftBottomRadius, rightBottomRadius, base,
289 popupIndicator, flags);
293 void
294 HaikuControlLook::DrawMenuBackground(BView* view, BRect& rect,
295 const BRect& updateRect, const rgb_color& base, uint32 flags,
296 uint32 borders)
298 if (!rect.IsValid() || !rect.Intersects(updateRect))
299 return;
301 // surface top color
302 rgb_color background = tint_color(base, 0.75);
304 // inner bevel colors
305 rgb_color bevelLightColor;
306 rgb_color bevelShadowColor;
308 if ((flags & B_DISABLED) != 0) {
309 bevelLightColor = tint_color(background, 0.80);
310 bevelShadowColor = tint_color(background, 1.07);
311 } else {
312 bevelLightColor = tint_color(background, 0.6);
313 bevelShadowColor = tint_color(background, 1.12);
316 // draw inner bevel
317 _DrawFrame(view, rect,
318 bevelLightColor, bevelLightColor,
319 bevelShadowColor, bevelShadowColor,
320 borders);
322 // draw surface top
323 view->SetHighColor(background);
324 view->FillRect(rect);
328 void
329 HaikuControlLook::DrawMenuItemBackground(BView* view, BRect& rect,
330 const BRect& updateRect, const rgb_color& base, uint32 flags,
331 uint32 borders)
333 if (!rect.IsValid() || !rect.Intersects(updateRect))
334 return;
336 // surface edges
337 float topTint;
338 float bottomTint;
339 rgb_color selectedColor = base;
341 if ((flags & B_ACTIVATED) != 0) {
342 topTint = 0.9;
343 bottomTint = 1.05;
344 } else if ((flags & B_DISABLED) != 0) {
345 topTint = 0.80;
346 bottomTint = 1.07;
347 } else {
348 topTint = 0.6;
349 bottomTint = 1.12;
352 rgb_color bevelLightColor = tint_color(selectedColor, topTint);
353 rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint);
355 // draw surface edges
356 _DrawFrame(view, rect,
357 bevelLightColor, bevelLightColor,
358 bevelShadowColor, bevelShadowColor,
359 borders);
361 // draw surface top
362 view->SetLowColor(selectedColor);
363 // _FillGradient(view, rect, selectedColor, topTint, bottomTint);
364 _FillGradient(view, rect, selectedColor, bottomTint, topTint);
368 void
369 HaikuControlLook::DrawStatusBar(BView* view, BRect& rect, const BRect& updateRect,
370 const rgb_color& base, const rgb_color& barColor, float progressPosition)
372 if (!rect.Intersects(updateRect))
373 return;
375 _DrawOuterResessedFrame(view, rect, base, 0.6);
377 // colors
378 rgb_color dark1BorderColor = tint_color(base, 1.3);
379 rgb_color dark2BorderColor = tint_color(base, 1.2);
380 rgb_color dark1FilledBorderColor = tint_color(barColor, 1.20);
381 rgb_color dark2FilledBorderColor = tint_color(barColor, 1.45);
383 BRect filledRect(rect);
384 filledRect.right = progressPosition - 1;
386 BRect nonfilledRect(rect);
387 nonfilledRect.left = progressPosition;
389 bool filledSurface = filledRect.Width() > 0;
390 bool nonfilledSurface = nonfilledRect.Width() > 0;
392 if (filledSurface) {
393 _DrawFrame(view, filledRect,
394 dark1FilledBorderColor, dark1FilledBorderColor,
395 dark2FilledBorderColor, dark2FilledBorderColor);
397 _FillGlossyGradient(view, filledRect, barColor, 0.55, 0.68, 0.76, 0.90);
400 if (nonfilledSurface) {
401 _DrawFrame(view, nonfilledRect, dark1BorderColor, dark1BorderColor,
402 dark2BorderColor, dark2BorderColor,
403 B_TOP_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER);
405 if (nonfilledRect.left < nonfilledRect.right) {
406 // shadow from fill bar, or left border
407 rgb_color leftBorder = dark1BorderColor;
408 if (filledSurface)
409 leftBorder = tint_color(base, 0.50);
410 view->SetHighColor(leftBorder);
411 view->StrokeLine(nonfilledRect.LeftTop(),
412 nonfilledRect.LeftBottom());
413 nonfilledRect.left++;
416 _FillGradient(view, nonfilledRect, base, 0.25, 0.06);
421 void
422 HaikuControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect,
423 const rgb_color& base, uint32 flags)
425 if (!rect.Intersects(updateRect))
426 return;
428 rgb_color dark1BorderColor;
429 rgb_color dark2BorderColor;
430 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
432 if ((flags & B_DISABLED) != 0) {
433 _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags);
435 dark1BorderColor = tint_color(base, 1.15);
436 dark2BorderColor = tint_color(base, 1.15);
437 } else if ((flags & B_CLICKED) != 0) {
438 dark1BorderColor = tint_color(base, 1.50);
439 dark2BorderColor = tint_color(base, 1.48);
441 _DrawFrame(view, rect,
442 dark1BorderColor, dark1BorderColor,
443 dark2BorderColor, dark2BorderColor);
445 dark2BorderColor = dark1BorderColor;
446 } else {
447 _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags);
449 dark1BorderColor = tint_color(base, 1.40);
450 dark2BorderColor = tint_color(base, 1.38);
453 if ((flags & B_FOCUSED) != 0) {
454 dark1BorderColor = navigationColor;
455 dark2BorderColor = navigationColor;
458 _DrawFrame(view, rect,
459 dark1BorderColor, dark1BorderColor,
460 dark2BorderColor, dark2BorderColor);
462 if ((flags & B_DISABLED) != 0)
463 _FillGradient(view, rect, base, 0.4, 0.2);
464 else
465 _FillGradient(view, rect, base, 0.15, 0.0);
467 rgb_color markColor;
468 if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) {
469 view->SetHighColor(markColor);
471 BFont font;
472 view->GetFont(&font);
473 float inset = std::max(2.0f, roundf(font.Size() / 6));
474 rect.InsetBy(inset, inset);
476 float penSize = std::max(1.0f, ceilf(rect.Width() / 3.5f));
477 if (penSize > 1.0f && fmodf(penSize, 2.0f) == 0.0f) {
478 // Tweak ends to "include" the pixel at the index,
479 // we need to do this in order to produce results like R5,
480 // where coordinates were inclusive
481 rect.right++;
482 rect.bottom++;
485 view->SetPenSize(penSize);
486 view->SetDrawingMode(B_OP_OVER);
487 view->StrokeLine(rect.LeftTop(), rect.RightBottom());
488 view->StrokeLine(rect.LeftBottom(), rect.RightTop());
493 void
494 HaikuControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateRect,
495 const rgb_color& base, uint32 flags)
497 if (!rect.Intersects(updateRect))
498 return;
500 rgb_color borderColor;
501 rgb_color bevelLight;
502 rgb_color bevelShadow;
503 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
505 if ((flags & B_DISABLED) != 0) {
506 borderColor = tint_color(base, 1.15);
507 bevelLight = base;
508 bevelShadow = base;
509 } else if ((flags & B_CLICKED) != 0) {
510 borderColor = tint_color(base, 1.50);
511 bevelLight = borderColor;
512 bevelShadow = borderColor;
513 } else {
514 borderColor = tint_color(base, 1.45);
515 bevelLight = tint_color(base, 0.55);
516 bevelShadow = tint_color(base, 1.11);
519 if ((flags & B_FOCUSED) != 0) {
520 borderColor = navigationColor;
523 BGradientLinear bevelGradient;
524 bevelGradient.AddColor(bevelShadow, 0);
525 bevelGradient.AddColor(bevelLight, 255);
526 bevelGradient.SetStart(rect.LeftTop());
527 bevelGradient.SetEnd(rect.RightBottom());
529 view->FillEllipse(rect, bevelGradient);
530 rect.InsetBy(1, 1);
532 bevelGradient.MakeEmpty();
533 bevelGradient.AddColor(borderColor, 0);
534 bevelGradient.AddColor(tint_color(borderColor, 0.8), 255);
535 view->FillEllipse(rect, bevelGradient);
536 rect.InsetBy(1, 1);
538 float topTint;
539 float bottomTint;
540 if ((flags & B_DISABLED) != 0) {
541 topTint = 0.4;
542 bottomTint = 0.2;
543 } else {
544 topTint = 0.15;
545 bottomTint = 0.0;
548 BGradientLinear gradient;
549 _MakeGradient(gradient, rect, base, topTint, bottomTint);
550 view->FillEllipse(rect, gradient);
552 rgb_color markColor;
553 if (_RadioButtonAndCheckBoxMarkColor(base, markColor, flags)) {
554 view->SetHighColor(markColor);
555 BFont font;
556 view->GetFont(&font);
557 float inset = roundf(font.Size() / 4);
558 rect.InsetBy(inset, inset);
559 view->FillEllipse(rect);
564 void
565 HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2,
566 const BRect& updateRect, const rgb_color& base, uint32 flags,
567 orientation orientation)
569 DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation);
570 DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation);
574 void
575 HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
576 const BRect& updateRect, const rgb_color& base, uint32 flags,
577 orientation orientation)
579 if (!rect.IsValid() || !rect.Intersects(updateRect))
580 return;
582 float gradient1Tint;
583 float gradient2Tint;
584 float darkEdge1Tint;
585 float darkEdge2Tint;
586 float shadowTint;
588 if ((flags & B_DISABLED) != 0) {
589 gradient1Tint = 0.9;
590 gradient2Tint = 0.8;
591 darkEdge1Tint = B_DARKEN_2_TINT;
592 darkEdge2Tint = B_DARKEN_2_TINT;
593 shadowTint = gradient1Tint;
594 } else {
595 gradient1Tint = 1.10;
596 gradient2Tint = 1.05;
597 darkEdge1Tint = B_DARKEN_3_TINT;
598 darkEdge2Tint = B_DARKEN_2_TINT;
599 shadowTint = gradient1Tint;
602 rgb_color darkEdge1 = tint_color(base, darkEdge1Tint);
603 rgb_color darkEdge2 = tint_color(base, darkEdge2Tint);
604 rgb_color shadow = tint_color(base, shadowTint);
606 if (orientation == B_HORIZONTAL) {
607 // dark vertical line on left edge
608 if (rect.Width() > 0) {
609 view->SetHighColor(darkEdge1);
610 view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
611 rect.left++;
613 // dark vertical line on right edge
614 if (rect.Width() >= 0) {
615 view->SetHighColor(darkEdge2);
616 view->StrokeLine(rect.RightTop(), rect.RightBottom());
617 rect.right--;
619 // vertical shadow line after left edge
620 if (rect.Width() >= 0) {
621 view->SetHighColor(shadow);
622 view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
623 rect.left++;
625 // fill
626 if (rect.Width() >= 0) {
627 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
628 orientation);
630 } else {
631 // dark vertical line on top edge
632 if (rect.Height() > 0) {
633 view->SetHighColor(darkEdge1);
634 view->StrokeLine(rect.LeftTop(), rect.RightTop());
635 rect.top++;
637 // dark vertical line on bottom edge
638 if (rect.Height() >= 0) {
639 view->SetHighColor(darkEdge2);
640 view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
641 rect.bottom--;
643 // horizontal shadow line after top edge
644 if (rect.Height() >= 0) {
645 view->SetHighColor(shadow);
646 view->StrokeLine(rect.LeftTop(), rect.RightTop());
647 rect.top++;
649 // fill
650 if (rect.Height() >= 0) {
651 _FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
652 orientation);
658 void
659 HaikuControlLook::DrawScrollViewFrame(BView* view, BRect& rect,
660 const BRect& updateRect, BRect verticalScrollBarFrame,
661 BRect horizontalScrollBarFrame, const rgb_color& base,
662 border_style borderStyle, uint32 flags, uint32 _borders)
664 // calculate scroll corner rect before messing with the "rect"
665 BRect scrollCornerFillRect(rect.right, rect.bottom,
666 rect.right, rect.bottom);
668 if (horizontalScrollBarFrame.IsValid())
669 scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1;
671 if (verticalScrollBarFrame.IsValid())
672 scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1;
674 if (borderStyle == B_NO_BORDER) {
675 if (scrollCornerFillRect.IsValid()) {
676 view->SetHighColor(base);
677 view->FillRect(scrollCornerFillRect);
679 return;
682 bool excludeScrollCorner = borderStyle == B_FANCY_BORDER
683 && horizontalScrollBarFrame.IsValid()
684 && verticalScrollBarFrame.IsValid();
686 uint32 borders = _borders;
687 if (excludeScrollCorner) {
688 rect.bottom = horizontalScrollBarFrame.top;
689 rect.right = verticalScrollBarFrame.left;
690 borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER);
693 rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
695 if (borderStyle == B_FANCY_BORDER)
696 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
698 if ((flags & B_FOCUSED) != 0) {
699 rgb_color focusColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
700 _DrawFrame(view, rect, focusColor, focusColor, focusColor, focusColor,
701 borders);
702 } else {
703 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
704 scrollbarFrameColor, scrollbarFrameColor, borders);
707 if (excludeScrollCorner) {
708 horizontalScrollBarFrame.InsetBy(-1, -1);
709 // do not overdraw the top edge
710 horizontalScrollBarFrame.top += 2;
711 borders = _borders;
712 borders &= ~B_TOP_BORDER;
713 _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base,
714 1.0, 1.0, flags, borders);
715 _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor,
716 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
717 borders);
719 verticalScrollBarFrame.InsetBy(-1, -1);
720 // do not overdraw the left edge
721 verticalScrollBarFrame.left += 2;
722 borders = _borders;
723 borders &= ~B_LEFT_BORDER;
724 _DrawOuterResessedFrame(view, verticalScrollBarFrame, base,
725 1.0, 1.0, flags, borders);
726 _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor,
727 scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor,
728 borders);
730 // exclude recessed frame
731 scrollCornerFillRect.top++;
732 scrollCornerFillRect.left++;
735 if (scrollCornerFillRect.IsValid()) {
736 view->SetHighColor(base);
737 view->FillRect(scrollCornerFillRect);
742 void
743 HaikuControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect,
744 const rgb_color& base, uint32 direction, uint32 flags, float tint)
746 BPoint tri1, tri2, tri3;
747 float hInset = rect.Width() / 3;
748 float vInset = rect.Height() / 3;
749 rect.InsetBy(hInset, vInset);
751 switch (direction) {
752 case B_LEFT_ARROW:
753 tri1.Set(rect.right, rect.top);
754 tri2.Set(rect.right - rect.Width() / 1.33,
755 (rect.top + rect.bottom + 1) / 2);
756 tri3.Set(rect.right, rect.bottom + 1);
757 break;
758 case B_RIGHT_ARROW:
759 tri1.Set(rect.left + 1, rect.bottom + 1);
760 tri2.Set(rect.left + 1 + rect.Width() / 1.33,
761 (rect.top + rect.bottom + 1) / 2);
762 tri3.Set(rect.left + 1, rect.top);
763 break;
764 case B_UP_ARROW:
765 tri1.Set(rect.left, rect.bottom);
766 tri2.Set((rect.left + rect.right + 1) / 2,
767 rect.bottom - rect.Height() / 1.33);
768 tri3.Set(rect.right + 1, rect.bottom);
769 break;
770 case B_DOWN_ARROW:
771 default:
772 tri1.Set(rect.left, rect.top + 1);
773 tri2.Set((rect.left + rect.right + 1) / 2,
774 rect.top + 1 + rect.Height() / 1.33);
775 tri3.Set(rect.right + 1, rect.top + 1);
776 break;
777 case B_LEFT_UP_ARROW:
778 tri1.Set(rect.left, rect.bottom);
779 tri2.Set(rect.left, rect.top);
780 tri3.Set(rect.right - 1, rect.top);
781 break;
782 case B_RIGHT_UP_ARROW:
783 tri1.Set(rect.left + 1, rect.top);
784 tri2.Set(rect.right, rect.top);
785 tri3.Set(rect.right, rect.bottom);
786 break;
787 case B_RIGHT_DOWN_ARROW:
788 tri1.Set(rect.right, rect.top);
789 tri2.Set(rect.right, rect.bottom);
790 tri3.Set(rect.left + 1, rect.bottom);
791 break;
792 case B_LEFT_DOWN_ARROW:
793 tri1.Set(rect.right - 1, rect.bottom);
794 tri2.Set(rect.left, rect.bottom);
795 tri3.Set(rect.left, rect.top);
796 break;
799 BShape arrowShape;
800 arrowShape.MoveTo(tri1);
801 arrowShape.LineTo(tri2);
802 arrowShape.LineTo(tri3);
804 if ((flags & B_DISABLED) != 0)
805 tint = (tint + B_NO_TINT + B_NO_TINT) / 3;
807 view->SetHighColor(tint_color(base, tint));
809 float penSize = view->PenSize();
810 drawing_mode mode = view->DrawingMode();
812 view->MovePenTo(BPoint(0, 0));
814 view->SetPenSize(ceilf(hInset / 2.0));
815 view->SetDrawingMode(B_OP_OVER);
816 view->StrokeShape(&arrowShape);
818 view->SetPenSize(penSize);
819 view->SetDrawingMode(mode);
823 rgb_color
824 HaikuControlLook::SliderBarColor(const rgb_color& base)
826 return tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_1_TINT);
830 void
831 HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
832 const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
833 float sliderScale, uint32 flags, orientation orientation)
835 if (!rect.IsValid() || !rect.Intersects(updateRect))
836 return;
838 // save the clipping constraints of the view
839 view->PushState();
841 // separate the bar in two sides
842 float sliderPosition;
843 BRect leftBarSide = rect;
844 BRect rightBarSide = rect;
846 if (orientation == B_HORIZONTAL) {
847 sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
848 * sliderScale);
849 leftBarSide.right = sliderPosition - 1;
850 rightBarSide.left = sliderPosition;
851 } else {
852 // NOTE: position is reverse of coords
853 sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
854 * (1.0 - sliderScale));
855 leftBarSide.top = sliderPosition;
856 rightBarSide.bottom = sliderPosition - 1;
859 // fill the background for the corners, exclude the middle bar for now
860 BRegion region(rect);
861 region.Exclude(rightBarSide);
862 view->ConstrainClippingRegion(&region);
864 view->PushState();
866 DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
867 orientation);
869 view->PopState();
871 region.Set(rect);
872 region.Exclude(leftBarSide);
873 view->ConstrainClippingRegion(&region);
875 view->PushState();
877 DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
878 orientation);
880 view->PopState();
882 // restore the clipping constraints of the view
883 view->PopState();
887 void
888 HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
889 const rgb_color& base, rgb_color fillColor, uint32 flags,
890 orientation orientation)
892 if (!rect.IsValid() || !rect.Intersects(updateRect))
893 return;
895 // separate the rect into corners
896 BRect leftCorner(rect);
897 BRect rightCorner(rect);
898 BRect barRect(rect);
900 if (orientation == B_HORIZONTAL) {
901 leftCorner.right = leftCorner.left + leftCorner.Height();
902 rightCorner.left = rightCorner.right - rightCorner.Height();
903 barRect.left += ceilf(barRect.Height() / 2);
904 barRect.right -= ceilf(barRect.Height() / 2);
905 } else {
906 leftCorner.bottom = leftCorner.top + leftCorner.Width();
907 rightCorner.top = rightCorner.bottom - rightCorner.Width();
908 barRect.top += ceilf(barRect.Width() / 2);
909 barRect.bottom -= ceilf(barRect.Width() / 2);
912 // fill the background for the corners, exclude the middle bar for now
913 BRegion region(rect);
914 region.Exclude(barRect);
915 view->ConstrainClippingRegion(&region);
917 if ((flags & B_BLEND_FRAME) == 0) {
918 view->SetHighColor(base);
919 view->FillRect(rect);
922 // figure out the tints to be used
923 float edgeLightTint;
924 float edgeShadowTint;
925 float frameLightTint;
926 float frameShadowTint;
927 float fillLightTint;
928 float fillShadowTint;
929 uint8 edgeLightAlpha;
930 uint8 edgeShadowAlpha;
931 uint8 frameLightAlpha;
932 uint8 frameShadowAlpha;
934 if ((flags & B_DISABLED) != 0) {
935 edgeLightTint = 1.0;
936 edgeShadowTint = 1.0;
937 frameLightTint = 1.20;
938 frameShadowTint = 1.25;
939 fillLightTint = 0.9;
940 fillShadowTint = 1.05;
941 edgeLightAlpha = 12;
942 edgeShadowAlpha = 12;
943 frameLightAlpha = 40;
944 frameShadowAlpha = 45;
946 fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6);
947 fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6);
948 fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6);
949 } else {
950 edgeLightTint = 0.65;
951 edgeShadowTint = 1.07;
952 frameLightTint = 1.40;
953 frameShadowTint = 1.50;
954 fillLightTint = 0.8;
955 fillShadowTint = 1.1;
956 edgeLightAlpha = 15;
957 edgeShadowAlpha = 15;
958 frameLightAlpha = 92;
959 frameShadowAlpha = 107;
962 rgb_color edgeLightColor;
963 rgb_color edgeShadowColor;
964 rgb_color frameLightColor;
965 rgb_color frameShadowColor;
966 rgb_color fillLightColor = tint_color(fillColor, fillLightTint);
967 rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint);
969 drawing_mode oldMode = view->DrawingMode();
971 if ((flags & B_BLEND_FRAME) != 0) {
972 edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha };
973 edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha };
974 frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha };
975 frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha };
977 view->SetDrawingMode(B_OP_ALPHA);
978 } else {
979 edgeLightColor = tint_color(base, edgeLightTint);
980 edgeShadowColor = tint_color(base, edgeShadowTint);
981 frameLightColor = tint_color(fillColor, frameLightTint);
982 frameShadowColor = tint_color(fillColor, frameShadowTint);
985 if (orientation == B_HORIZONTAL) {
986 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
987 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
988 fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation);
990 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
991 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
992 fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation);
993 } else {
994 _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor,
995 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
996 fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation);
998 _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor,
999 edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor,
1000 fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation);
1003 view->ConstrainClippingRegion(NULL);
1005 view->BeginLineArray(4);
1006 if (orientation == B_HORIZONTAL) {
1007 view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor);
1008 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
1009 edgeLightColor);
1010 barRect.InsetBy(0, 1);
1011 view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor);
1012 view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
1013 frameLightColor);
1014 barRect.InsetBy(0, 1);
1015 } else {
1016 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor);
1017 view->AddLine(barRect.RightTop(), barRect.RightBottom(),
1018 edgeLightColor);
1019 barRect.InsetBy(1, 0);
1020 view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor);
1021 view->AddLine(barRect.RightTop(), barRect.RightBottom(),
1022 frameLightColor);
1023 barRect.InsetBy(1, 0);
1025 view->EndLineArray();
1027 view->SetDrawingMode(oldMode);
1029 _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint,
1030 orientation);
1034 void
1035 HaikuControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
1036 const rgb_color& base, uint32 flags, orientation orientation)
1038 if (!rect.IsValid() || !rect.Intersects(updateRect))
1039 return;
1041 // figure out frame color
1042 rgb_color frameLightColor;
1043 rgb_color frameShadowColor;
1044 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1046 if ((flags & B_FOCUSED) != 0) {
1047 // focused
1048 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1049 frameShadowColor = frameLightColor;
1050 } else {
1051 // figure out the tints to be used
1052 float frameLightTint;
1053 float frameShadowTint;
1055 if ((flags & B_DISABLED) != 0) {
1056 frameLightTint = 1.30;
1057 frameShadowTint = 1.35;
1058 shadowColor.alpha = 30;
1059 } else {
1060 frameLightTint = 1.6;
1061 frameShadowTint = 1.65;
1064 frameLightColor = tint_color(base, frameLightTint);
1065 frameShadowColor = tint_color(base, frameShadowTint);
1068 BRect originalRect(rect);
1069 rect.right--;
1070 rect.bottom--;
1072 _DrawFrame(view, rect, frameLightColor, frameLightColor,
1073 frameShadowColor, frameShadowColor);
1075 flags &= ~B_ACTIVATED;
1076 DrawButtonBackground(view, rect, updateRect, base, flags);
1078 // thumb shadow
1079 view->SetDrawingMode(B_OP_ALPHA);
1080 view->SetHighColor(shadowColor);
1081 originalRect.left++;
1082 originalRect.top++;
1083 view->StrokeLine(originalRect.LeftBottom(), originalRect.RightBottom());
1084 originalRect.bottom--;
1085 view->StrokeLine(originalRect.RightTop(), originalRect.RightBottom());
1087 // thumb edge
1088 if (orientation == B_HORIZONTAL) {
1089 rect.InsetBy(0, floorf(rect.Height() / 4));
1090 rect.left = floorf((rect.left + rect.right) / 2);
1091 rect.right = rect.left + 1;
1092 shadowColor = tint_color(base, B_DARKEN_2_TINT);
1093 shadowColor.alpha = 128;
1094 view->SetHighColor(shadowColor);
1095 view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
1096 rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1097 lightColor.alpha = 128;
1098 view->SetHighColor(lightColor);
1099 view->StrokeLine(rect.RightTop(), rect.RightBottom());
1100 } else {
1101 rect.InsetBy(floorf(rect.Width() / 4), 0);
1102 rect.top = floorf((rect.top + rect.bottom) / 2);
1103 rect.bottom = rect.top + 1;
1104 shadowColor = tint_color(base, B_DARKEN_2_TINT);
1105 shadowColor.alpha = 128;
1106 view->SetHighColor(shadowColor);
1107 view->StrokeLine(rect.LeftTop(), rect.RightTop());
1108 rgb_color lightColor = tint_color(base, B_LIGHTEN_2_TINT);
1109 lightColor.alpha = 128;
1110 view->SetHighColor(lightColor);
1111 view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
1114 view->SetDrawingMode(B_OP_COPY);
1118 void
1119 HaikuControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1120 const BRect& updateRect, const rgb_color& base, uint32 flags,
1121 orientation orientation)
1123 DrawSliderTriangle(view, rect, updateRect, base, base, flags, orientation);
1127 void
1128 HaikuControlLook::DrawSliderTriangle(BView* view, BRect& rect,
1129 const BRect& updateRect, const rgb_color& base, const rgb_color& fill,
1130 uint32 flags, orientation orientation)
1132 if (!rect.IsValid() || !rect.Intersects(updateRect))
1133 return;
1135 // figure out frame color
1136 rgb_color frameLightColor;
1137 rgb_color frameShadowColor;
1138 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
1140 float topTint = 0.49;
1141 float middleTint1 = 0.62;
1142 float middleTint2 = 0.76;
1143 float bottomTint = 0.90;
1145 if ((flags & B_DISABLED) != 0) {
1146 topTint = (topTint + B_NO_TINT) / 2;
1147 middleTint1 = (middleTint1 + B_NO_TINT) / 2;
1148 middleTint2 = (middleTint2 + B_NO_TINT) / 2;
1149 bottomTint = (bottomTint + B_NO_TINT) / 2;
1150 } else if ((flags & B_HOVER) != 0) {
1151 topTint *= kHoverTintFactor;
1152 middleTint1 *= kHoverTintFactor;
1153 middleTint2 *= kHoverTintFactor;
1154 bottomTint *= kHoverTintFactor;
1157 if ((flags & B_FOCUSED) != 0) {
1158 // focused
1159 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1160 frameShadowColor = frameLightColor;
1161 } else {
1162 // figure out the tints to be used
1163 float frameLightTint;
1164 float frameShadowTint;
1166 if ((flags & B_DISABLED) != 0) {
1167 frameLightTint = 1.30;
1168 frameShadowTint = 1.35;
1169 shadowColor.alpha = 30;
1170 } else {
1171 frameLightTint = 1.6;
1172 frameShadowTint = 1.65;
1175 frameLightColor = tint_color(base, frameLightTint);
1176 frameShadowColor = tint_color(base, frameShadowTint);
1179 // make room for the shadow
1180 rect.right--;
1181 rect.bottom--;
1183 uint32 viewFlags = view->Flags();
1184 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
1185 view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
1187 float centerh = (rect.left + rect.right) / 2;
1188 float centerv = (rect.top + rect.bottom) / 2;
1190 BShape shape;
1191 if (orientation == B_HORIZONTAL) {
1192 shape.MoveTo(BPoint(rect.left + 0.5, rect.bottom + 0.5));
1193 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1194 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom - 1 + 0.5));
1195 shape.LineTo(BPoint(centerh + 0.5, rect.top + 0.5));
1196 shape.LineTo(BPoint(rect.left + 0.5, rect.bottom - 1 + 0.5));
1197 } else {
1198 shape.MoveTo(BPoint(rect.right + 0.5, rect.top + 0.5));
1199 shape.LineTo(BPoint(rect.right + 0.5, rect.bottom + 0.5));
1200 shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.bottom + 0.5));
1201 shape.LineTo(BPoint(rect.left + 0.5, centerv + 0.5));
1202 shape.LineTo(BPoint(rect.right - 1 + 0.5, rect.top + 0.5));
1204 shape.Close();
1206 view->MovePenTo(BPoint(1, 1));
1208 view->SetDrawingMode(B_OP_ALPHA);
1209 view->SetHighColor(shadowColor);
1210 view->StrokeShape(&shape);
1212 view->MovePenTo(B_ORIGIN);
1214 view->SetDrawingMode(B_OP_COPY);
1215 view->SetHighColor(frameLightColor);
1216 view->StrokeShape(&shape);
1218 rect.InsetBy(1, 1);
1219 shape.Clear();
1220 if (orientation == B_HORIZONTAL) {
1221 shape.MoveTo(BPoint(rect.left, rect.bottom + 1));
1222 shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1223 shape.LineTo(BPoint(centerh + 0.5, rect.top));
1224 } else {
1225 shape.MoveTo(BPoint(rect.right + 1, rect.top));
1226 shape.LineTo(BPoint(rect.right + 1, rect.bottom + 1));
1227 shape.LineTo(BPoint(rect.left, centerv + 0.5));
1229 shape.Close();
1231 BGradientLinear gradient;
1232 if ((flags & B_DISABLED) != 0) {
1233 _MakeGradient(gradient, rect, fill, topTint, bottomTint);
1234 } else {
1235 _MakeGlossyGradient(gradient, rect, fill, topTint, middleTint1,
1236 middleTint2, bottomTint);
1239 view->FillShape(&shape, gradient);
1241 view->SetFlags(viewFlags);
1245 void
1246 HaikuControlLook::DrawSliderHashMarks(BView* view, BRect& rect,
1247 const BRect& updateRect, const rgb_color& base, int32 count,
1248 hash_mark_location location, uint32 flags, orientation orientation)
1250 if (!rect.IsValid() || !rect.Intersects(updateRect))
1251 return;
1253 rgb_color lightColor;
1254 rgb_color darkColor;
1256 if ((flags & B_DISABLED) != 0) {
1257 lightColor = tint_color(base, 0.9);
1258 darkColor = tint_color(base, 1.07);
1259 } else {
1260 lightColor = tint_color(base, 0.8);
1261 darkColor = tint_color(base, 1.14);
1264 int32 hashMarkCount = std::max(count, (int32)2);
1265 // draw at least two hashmarks at min/max if
1266 // fHashMarks != B_HASH_MARKS_NONE
1267 float factor;
1268 float startPos;
1269 if (orientation == B_HORIZONTAL) {
1270 factor = (rect.Width() - 2) / (hashMarkCount - 1);
1271 startPos = rect.left + 1;
1272 } else {
1273 factor = (rect.Height() - 2) / (hashMarkCount - 1);
1274 startPos = rect.top + 1;
1277 if (location & B_HASH_MARKS_TOP) {
1278 view->BeginLineArray(hashMarkCount * 2);
1280 if (orientation == B_HORIZONTAL) {
1281 float pos = startPos;
1282 for (int32 i = 0; i < hashMarkCount; i++) {
1283 view->AddLine(BPoint(pos, rect.top),
1284 BPoint(pos, rect.top + 4), darkColor);
1285 view->AddLine(BPoint(pos + 1, rect.top),
1286 BPoint(pos + 1, rect.top + 4), lightColor);
1288 pos += factor;
1290 } else {
1291 float pos = startPos;
1292 for (int32 i = 0; i < hashMarkCount; i++) {
1293 view->AddLine(BPoint(rect.left, pos),
1294 BPoint(rect.left + 4, pos), darkColor);
1295 view->AddLine(BPoint(rect.left, pos + 1),
1296 BPoint(rect.left + 4, pos + 1), lightColor);
1298 pos += factor;
1302 view->EndLineArray();
1305 if ((location & B_HASH_MARKS_BOTTOM) != 0) {
1306 view->BeginLineArray(hashMarkCount * 2);
1308 if (orientation == B_HORIZONTAL) {
1309 float pos = startPos;
1310 for (int32 i = 0; i < hashMarkCount; i++) {
1311 view->AddLine(BPoint(pos, rect.bottom - 4),
1312 BPoint(pos, rect.bottom), darkColor);
1313 view->AddLine(BPoint(pos + 1, rect.bottom - 4),
1314 BPoint(pos + 1, rect.bottom), lightColor);
1316 pos += factor;
1318 } else {
1319 float pos = startPos;
1320 for (int32 i = 0; i < hashMarkCount; i++) {
1321 view->AddLine(BPoint(rect.right - 4, pos),
1322 BPoint(rect.right, pos), darkColor);
1323 view->AddLine(BPoint(rect.right - 4, pos + 1),
1324 BPoint(rect.right, pos + 1), lightColor);
1326 pos += factor;
1330 view->EndLineArray();
1335 void
1336 HaikuControlLook::DrawActiveTab(BView* view, BRect& rect, const BRect& updateRect,
1337 const rgb_color& base, uint32 flags, uint32 borders, uint32 side)
1339 if (!rect.IsValid() || !rect.Intersects(updateRect))
1340 return;
1342 // Snap the rectangle to pixels to avoid rounding errors.
1343 rect.left = floorf(rect.left);
1344 rect.right = floorf(rect.right);
1345 rect.top = floorf(rect.top);
1346 rect.bottom = floorf(rect.bottom);
1348 // save the clipping constraints of the view
1349 view->PushState();
1351 // set clipping constraints to updateRect
1352 BRegion clipping(updateRect);
1353 view->ConstrainClippingRegion(&clipping);
1355 rgb_color edgeShadowColor;
1356 rgb_color edgeLightColor;
1357 rgb_color frameShadowColor;
1358 rgb_color frameLightColor;
1359 rgb_color bevelShadowColor;
1360 rgb_color bevelLightColor;
1361 BGradientLinear fillGradient;
1362 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1363 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1365 if ((flags & B_DISABLED) != 0) {
1366 edgeLightColor = base;
1367 edgeShadowColor = base;
1368 frameLightColor = tint_color(base, 1.25);
1369 frameShadowColor = tint_color(base, 1.30);
1370 bevelLightColor = tint_color(base, 0.8);
1371 bevelShadowColor = tint_color(base, 1.07);
1372 fillGradient.AddColor(tint_color(base, 0.85), 0);
1373 fillGradient.AddColor(base, 255);
1374 } else {
1375 edgeLightColor = tint_color(base, 0.80);
1376 edgeShadowColor = tint_color(base, 1.03);
1377 frameLightColor = tint_color(base, 1.30);
1378 frameShadowColor = tint_color(base, 1.30);
1379 bevelLightColor = tint_color(base, 0.6);
1380 bevelShadowColor = tint_color(base, 1.07);
1381 fillGradient.AddColor(tint_color(base, 0.75), 0);
1382 fillGradient.AddColor(tint_color(base, 1.03), 255);
1385 static const float kRoundCornerRadius = 4.0f;
1387 // left top corner dimensions
1388 BRect leftTopCorner(rect);
1389 leftTopCorner.right = floorf(leftTopCorner.left + kRoundCornerRadius);
1390 leftTopCorner.bottom = floorf(rect.top + kRoundCornerRadius);
1392 // right top corner dimensions
1393 BRect rightTopCorner(rect);
1394 rightTopCorner.left = floorf(rightTopCorner.right - kRoundCornerRadius);
1395 rightTopCorner.bottom = floorf(rect.top + kRoundCornerRadius);
1397 // left bottom corner dimensions
1398 BRect leftBottomCorner(rect);
1399 leftBottomCorner.right = floorf(leftBottomCorner.left + kRoundCornerRadius);
1400 leftBottomCorner.top = floorf(rect.bottom - kRoundCornerRadius);
1402 // right bottom corner dimensions
1403 BRect rightBottomCorner(rect);
1404 rightBottomCorner.left = floorf(rightBottomCorner.right
1405 - kRoundCornerRadius);
1406 rightBottomCorner.top = floorf(rect.bottom - kRoundCornerRadius);
1408 switch (side) {
1409 case B_TOP_BORDER:
1410 clipping.Exclude(leftTopCorner);
1411 clipping.Exclude(rightTopCorner);
1413 // draw the left top corner
1414 _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base,
1415 edgeShadowColor, frameLightColor, bevelLightColor,
1416 fillGradient);
1417 // draw the right top corner
1418 _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base,
1419 edgeShadowColor, edgeLightColor, frameLightColor,
1420 frameShadowColor, bevelLightColor, bevelShadowColor,
1421 fillGradient);
1422 break;
1423 case B_BOTTOM_BORDER:
1424 clipping.Exclude(leftBottomCorner);
1425 clipping.Exclude(rightBottomCorner);
1427 // draw the left bottom corner
1428 _DrawRoundCornerLeftBottom(view, leftBottomCorner, updateRect, base,
1429 edgeShadowColor, edgeLightColor, frameLightColor,
1430 frameShadowColor, bevelLightColor, bevelShadowColor,
1431 fillGradient);
1432 // draw the right bottom corner
1433 _DrawRoundCornerRightBottom(view, rightBottomCorner, updateRect,
1434 base, edgeLightColor, frameShadowColor, bevelShadowColor,
1435 fillGradient);
1436 break;
1437 case B_LEFT_BORDER:
1438 clipping.Exclude(leftTopCorner);
1439 clipping.Exclude(leftBottomCorner);
1441 // draw the left top corner
1442 _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base,
1443 edgeShadowColor, frameLightColor, bevelLightColor,
1444 fillGradient);
1445 // draw the left bottom corner
1446 _DrawRoundCornerLeftBottom(view, leftBottomCorner, updateRect, base,
1447 edgeShadowColor, edgeLightColor, frameLightColor,
1448 frameShadowColor, bevelLightColor, bevelShadowColor,
1449 fillGradient);
1450 break;
1451 case B_RIGHT_BORDER:
1452 clipping.Exclude(rightTopCorner);
1453 clipping.Exclude(rightBottomCorner);
1455 // draw the right top corner
1456 _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base,
1457 edgeShadowColor, edgeLightColor, frameLightColor,
1458 frameShadowColor, bevelLightColor, bevelShadowColor,
1459 fillGradient);
1460 // draw the right bottom corner
1461 _DrawRoundCornerRightBottom(view, rightBottomCorner, updateRect,
1462 base, edgeLightColor, frameShadowColor, bevelShadowColor,
1463 fillGradient);
1464 break;
1467 // clip out the corners
1468 view->ConstrainClippingRegion(&clipping);
1470 uint32 bordersToDraw = 0;
1471 switch (side) {
1472 case B_TOP_BORDER:
1473 bordersToDraw = (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER);
1474 break;
1475 case B_BOTTOM_BORDER:
1476 bordersToDraw = (B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER);
1477 break;
1478 case B_LEFT_BORDER:
1479 bordersToDraw = (B_LEFT_BORDER | B_BOTTOM_BORDER | B_TOP_BORDER);
1480 break;
1481 case B_RIGHT_BORDER:
1482 bordersToDraw = (B_RIGHT_BORDER | B_BOTTOM_BORDER | B_TOP_BORDER);
1483 break;
1486 // draw the rest of frame and fill
1487 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1488 edgeLightColor, borders);
1489 if (side == B_TOP_BORDER || side == B_BOTTOM_BORDER) {
1490 if ((borders & B_LEFT_BORDER) == 0)
1491 rect.left++;
1492 if ((borders & B_RIGHT_BORDER) == 0)
1493 rect.right--;
1494 } else if (side == B_LEFT_BORDER || side == B_RIGHT_BORDER) {
1495 if ((borders & B_TOP_BORDER) == 0)
1496 rect.top++;
1497 if ((borders & B_BOTTOM_BORDER) == 0)
1498 rect.bottom--;
1501 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1502 frameShadowColor, bordersToDraw);
1504 _DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor,
1505 bevelShadowColor);
1507 view->FillRect(rect, fillGradient);
1509 // restore the clipping constraints of the view
1510 view->PopState();
1514 void
1515 HaikuControlLook::DrawInactiveTab(BView* view, BRect& rect, const BRect& updateRect,
1516 const rgb_color& base, uint32 flags, uint32 borders, uint32 side)
1518 if (!rect.IsValid() || !rect.Intersects(updateRect))
1519 return;
1521 rgb_color edgeShadowColor;
1522 rgb_color edgeLightColor;
1523 rgb_color frameShadowColor;
1524 rgb_color frameLightColor;
1525 rgb_color bevelShadowColor;
1526 rgb_color bevelLightColor;
1527 BGradientLinear fillGradient;
1528 fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3));
1529 fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3));
1531 if ((flags & B_DISABLED) != 0) {
1532 edgeLightColor = base;
1533 edgeShadowColor = base;
1534 frameLightColor = tint_color(base, 1.25);
1535 frameShadowColor = tint_color(base, 1.30);
1536 bevelLightColor = tint_color(base, 0.8);
1537 bevelShadowColor = tint_color(base, 1.07);
1538 fillGradient.AddColor(tint_color(base, 0.85), 0);
1539 fillGradient.AddColor(base, 255);
1540 } else {
1541 edgeLightColor = tint_color(base, 0.80);
1542 edgeShadowColor = tint_color(base, 1.03);
1543 frameLightColor = tint_color(base, 1.30);
1544 frameShadowColor = tint_color(base, 1.30);
1545 bevelLightColor = tint_color(base, 1.10);
1546 bevelShadowColor = tint_color(base, 1.17);
1547 fillGradient.AddColor(tint_color(base, 1.12), 0);
1548 fillGradient.AddColor(tint_color(base, 1.08), 255);
1551 BRect background = rect;
1552 switch (side) {
1553 case B_TOP_BORDER:
1554 rect.top += 4;
1555 background.bottom = rect.top;
1556 break;
1557 case B_BOTTOM_BORDER:
1558 rect.bottom -= 4;
1559 background.top = rect.bottom;
1560 break;
1561 case B_LEFT_BORDER:
1562 rect.left += 4;
1563 background.right = rect.left;
1564 break;
1565 case B_RIGHT_BORDER:
1566 rect.right -= 4;
1567 background.left = rect.right;
1568 break;
1571 // active tabs stand out at the top, but this is an inactive tab
1572 view->SetHighColor(base);
1573 view->FillRect(background);
1575 // frame and fill
1576 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor,
1577 edgeLightColor, borders);
1579 _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor,
1580 frameShadowColor, borders);
1582 if (rect.IsValid()) {
1583 if (side == B_TOP_BORDER || side == B_BOTTOM_BORDER) {
1584 _DrawFrame(view, rect, bevelShadowColor, bevelShadowColor,
1585 bevelLightColor, bevelLightColor, B_LEFT_BORDER & ~borders);
1586 } else if (side == B_LEFT_BORDER || side == B_RIGHT_BORDER) {
1587 _DrawFrame(view, rect, bevelShadowColor, bevelShadowColor,
1588 bevelLightColor, bevelLightColor, B_TOP_BORDER & ~borders);
1590 } else {
1591 if (side == B_TOP_BORDER || side == B_BOTTOM_BORDER) {
1592 if ((B_LEFT_BORDER & ~borders) != 0)
1593 rect.left++;
1594 } else if (side == B_LEFT_BORDER || side == B_RIGHT_BORDER) {
1595 if ((B_TOP_BORDER & ~borders) != 0)
1596 rect.top++;
1600 view->FillRect(rect, fillGradient);
1604 void
1605 HaikuControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect,
1606 const rgb_color& base, orientation orientation, uint32 flags,
1607 uint32 borders)
1609 if (!rect.IsValid() || !rect.Intersects(updateRect))
1610 return;
1612 rgb_color background;
1613 if ((flags & (B_CLICKED | B_ACTIVATED)) != 0)
1614 background = tint_color(base, B_DARKEN_1_TINT);
1615 else
1616 background = base;
1618 rgb_color light = tint_color(background, 0.6);
1619 rgb_color shadow = tint_color(background, 1.21);
1621 // frame
1622 if (borders != 0 && rect.Width() > 3 && rect.Height() > 3)
1623 DrawRaisedBorder(view, rect, updateRect, background, flags, borders);
1625 // dots and rest of background
1626 if (orientation == B_HORIZONTAL) {
1627 if (rect.Width() > 2) {
1628 // background on left/right
1629 BRegion region(rect);
1630 rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5);
1631 rect.right = rect.left + 1;
1632 region.Exclude(rect);
1633 view->SetHighColor(background);
1634 view->FillRegion(&region);
1637 BPoint dot = rect.LeftTop();
1638 BPoint stop = rect.LeftBottom();
1639 int32 num = 1;
1640 while (dot.y <= stop.y) {
1641 rgb_color col1;
1642 rgb_color col2;
1643 switch (num) {
1644 case 1:
1645 col1 = background;
1646 col2 = background;
1647 break;
1648 case 2:
1649 col1 = shadow;
1650 col2 = background;
1651 break;
1652 case 3:
1653 default:
1654 col1 = background;
1655 col2 = light;
1656 num = 0;
1657 break;
1659 view->SetHighColor(col1);
1660 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1661 view->SetHighColor(col2);
1662 dot.x++;
1663 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1664 dot.x -= 1.0;
1665 // next pixel
1666 num++;
1667 dot.y++;
1669 } else {
1670 if (rect.Height() > 2) {
1671 // background on left/right
1672 BRegion region(rect);
1673 rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5);
1674 rect.bottom = rect.top + 1;
1675 region.Exclude(rect);
1676 view->SetHighColor(background);
1677 view->FillRegion(&region);
1680 BPoint dot = rect.LeftTop();
1681 BPoint stop = rect.RightTop();
1682 int32 num = 1;
1683 while (dot.x <= stop.x) {
1684 rgb_color col1;
1685 rgb_color col2;
1686 switch (num) {
1687 case 1:
1688 col1 = background;
1689 col2 = background;
1690 break;
1691 case 2:
1692 col1 = shadow;
1693 col2 = background;
1694 break;
1695 case 3:
1696 default:
1697 col1 = background;
1698 col2 = light;
1699 num = 0;
1700 break;
1702 view->SetHighColor(col1);
1703 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1704 view->SetHighColor(col2);
1705 dot.y++;
1706 view->StrokeLine(dot, dot, B_SOLID_HIGH);
1707 dot.y -= 1.0;
1708 // next pixel
1709 num++;
1710 dot.x++;
1716 // #pragma mark -
1719 void
1720 HaikuControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect,
1721 const rgb_color& base, border_style borderStyle, uint32 flags,
1722 uint32 borders)
1724 if (borderStyle == B_NO_BORDER)
1725 return;
1727 rgb_color scrollbarFrameColor = tint_color(base, B_DARKEN_2_TINT);
1728 if ((flags & B_FOCUSED) != 0)
1729 scrollbarFrameColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1731 if (borderStyle == B_FANCY_BORDER)
1732 _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders);
1734 _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor,
1735 scrollbarFrameColor, scrollbarFrameColor, borders);
1739 void
1740 HaikuControlLook::DrawRaisedBorder(BView* view, BRect& rect,
1741 const BRect& updateRect, const rgb_color& base, uint32 flags,
1742 uint32 borders)
1744 rgb_color lightColor;
1745 rgb_color shadowColor;
1747 if ((flags & B_DISABLED) != 0) {
1748 lightColor = base;
1749 shadowColor = base;
1750 } else {
1751 lightColor = tint_color(base, 0.85);
1752 shadowColor = tint_color(base, 1.07);
1755 _DrawFrame(view, rect, lightColor, lightColor, shadowColor, shadowColor,
1756 borders);
1760 void
1761 HaikuControlLook::DrawTextControlBorder(BView* view, BRect& rect,
1762 const BRect& updateRect, const rgb_color& base, uint32 flags,
1763 uint32 borders)
1765 if (!rect.Intersects(updateRect))
1766 return;
1768 rgb_color dark1BorderColor;
1769 rgb_color dark2BorderColor;
1770 rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
1771 rgb_color invalidColor = ui_color(B_FAILURE_COLOR);
1773 if ((flags & B_DISABLED) != 0) {
1774 _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders);
1776 if ((flags & B_BLEND_FRAME) != 0)
1777 dark1BorderColor = (rgb_color){ 0, 0, 0, 40 };
1778 else
1779 dark1BorderColor = tint_color(base, 1.15);
1780 dark2BorderColor = dark1BorderColor;
1781 } else if ((flags & B_CLICKED) != 0) {
1782 dark1BorderColor = tint_color(base, 1.50);
1783 dark2BorderColor = tint_color(base, 1.49);
1785 // BCheckBox uses this to indicate the clicked state...
1786 _DrawFrame(view, rect,
1787 dark1BorderColor, dark1BorderColor,
1788 dark2BorderColor, dark2BorderColor);
1790 dark2BorderColor = dark1BorderColor;
1791 } else {
1792 _DrawOuterResessedFrame(view, rect, base, 0.6, 1.0, flags, borders);
1794 if ((flags & B_BLEND_FRAME) != 0) {
1795 dark1BorderColor = (rgb_color){ 0, 0, 0, 102 };
1796 dark2BorderColor = (rgb_color){ 0, 0, 0, 97 };
1797 } else {
1798 dark1BorderColor = tint_color(base, 1.40);
1799 dark2BorderColor = tint_color(base, 1.38);
1803 if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) {
1804 dark1BorderColor = navigationColor;
1805 dark2BorderColor = navigationColor;
1808 if ((flags & B_DISABLED) == 0 && (flags & B_INVALID) != 0) {
1809 dark1BorderColor = invalidColor;
1810 dark2BorderColor = invalidColor;
1813 if ((flags & B_BLEND_FRAME) != 0) {
1814 drawing_mode oldMode = view->DrawingMode();
1815 view->SetDrawingMode(B_OP_ALPHA);
1817 _DrawFrame(view, rect,
1818 dark1BorderColor, dark1BorderColor,
1819 dark2BorderColor, dark2BorderColor, borders);
1821 view->SetDrawingMode(oldMode);
1822 } else {
1823 _DrawFrame(view, rect,
1824 dark1BorderColor, dark1BorderColor,
1825 dark2BorderColor, dark2BorderColor, borders);
1830 void
1831 HaikuControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect,
1832 const rgb_color& base, uint32 borders)
1834 rgb_color frameColor = tint_color(base, 1.30);
1835 rgb_color bevelLight = tint_color(base, 0.8);
1836 rgb_color bevelShadow = tint_color(base, 1.03);
1838 _DrawFrame(view, rect, bevelShadow, bevelShadow, bevelLight, bevelLight,
1839 borders);
1841 _DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor,
1842 borders);
1844 _DrawFrame(view, rect, bevelLight, bevelLight, bevelShadow, bevelShadow,
1845 borders);
1849 void
1850 HaikuControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1851 const BRect& updateRect, const rgb_color& base, uint32 flags,
1852 const rgb_color* textColor)
1854 DrawLabel(view, label, NULL, rect, updateRect, base, flags,
1855 DefaultLabelAlignment(), textColor);
1859 void
1860 HaikuControlLook::DrawLabel(BView* view, const char* label, BRect rect,
1861 const BRect& updateRect, const rgb_color& base, uint32 flags,
1862 const BAlignment& alignment, const rgb_color* textColor)
1864 DrawLabel(view, label, NULL, rect, updateRect, base, flags, alignment,
1865 textColor);
1869 void
1870 HaikuControlLook::DrawLabel(BView* view, const char* label, const rgb_color& base,
1871 uint32 flags, const BPoint& where, const rgb_color* textColor)
1873 // setup the text color
1875 BWindow* window = view->Window();
1876 bool isDesktop = window
1877 && window->Feel() == kDesktopWindowFeel
1878 && window->Look() == kDesktopWindowLook
1879 && view->Parent()
1880 && view->Parent()->Parent() == NULL
1881 && (flags & B_IGNORE_OUTLINE) == 0;
1883 rgb_color low;
1884 rgb_color color;
1885 rgb_color glowColor;
1887 if (textColor != NULL)
1888 glowColor = *textColor;
1889 else if ((flags & B_IS_CONTROL) != 0)
1890 glowColor = ui_color(B_CONTROL_TEXT_COLOR);
1891 else
1892 glowColor = ui_color(B_PANEL_TEXT_COLOR);
1894 color = glowColor;
1896 if (isDesktop)
1897 low = view->Parent()->ViewColor();
1898 else
1899 low = base;
1901 if ((flags & B_DISABLED) != 0) {
1902 color.red = (uint8)(((int32)low.red + color.red + 1) / 2);
1903 color.green = (uint8)(((int32)low.green + color.green + 1) / 2);
1904 color.blue = (uint8)(((int32)low.blue + color.blue + 1) / 2);
1907 drawing_mode oldMode = view->DrawingMode();
1909 if (isDesktop) {
1910 // enforce proper use of desktop label colors
1911 if (low.Brightness() < 100) {
1912 if (textColor == NULL)
1913 color = make_color(255, 255, 255);
1915 glowColor = make_color(0, 0, 0);
1916 } else {
1917 if (textColor == NULL)
1918 color = make_color(0, 0, 0);
1920 glowColor = make_color(255, 255, 255);
1923 // drawing occurs on the desktop
1924 if (fCachedWorkspace != current_workspace()) {
1925 int8 indice = 0;
1926 int32 mask;
1927 bool tmpOutline;
1928 while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces",
1929 indice, &mask) == B_OK
1930 && fBackgroundInfo.FindBool("be:bgndimginfoerasetext",
1931 indice, &tmpOutline) == B_OK) {
1933 if (((1 << current_workspace()) & mask) != 0) {
1934 fCachedOutline = tmpOutline;
1935 fCachedWorkspace = current_workspace();
1936 break;
1938 indice++;
1942 if (fCachedOutline) {
1943 BFont font;
1944 view->GetFont(&font);
1946 view->SetDrawingMode(B_OP_ALPHA);
1947 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
1948 // Draw glow or outline
1949 if (glowColor.Brightness() > 128) {
1950 font.SetFalseBoldWidth(2.0);
1951 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1953 glowColor.alpha = 30;
1954 view->SetHighColor(glowColor);
1955 view->DrawString(label, where);
1957 font.SetFalseBoldWidth(1.0);
1958 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1960 glowColor.alpha = 65;
1961 view->SetHighColor(glowColor);
1962 view->DrawString(label, where);
1964 font.SetFalseBoldWidth(0.0);
1965 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1966 } else {
1967 font.SetFalseBoldWidth(1.0);
1968 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1970 glowColor.alpha = 30;
1971 view->SetHighColor(glowColor);
1972 view->DrawString(label, where);
1974 font.SetFalseBoldWidth(0.0);
1975 view->SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1977 glowColor.alpha = 200;
1978 view->SetHighColor(glowColor);
1979 view->DrawString(label, BPoint(where.x + 1, where.y + 1));
1984 view->SetHighColor(color);
1985 view->SetDrawingMode(B_OP_OVER);
1986 view->DrawString(label, where);
1987 view->SetDrawingMode(oldMode);
1991 void
1992 HaikuControlLook::DrawLabel(BView* view, const char* label, const BBitmap* icon,
1993 BRect rect, const BRect& updateRect, const rgb_color& base, uint32 flags,
1994 const BAlignment& alignment, const rgb_color* textColor)
1996 if (!rect.Intersects(updateRect))
1997 return;
1999 if (label == NULL && icon == NULL)
2000 return;
2002 if (label == NULL) {
2003 // icon only
2004 BRect alignedRect = BLayoutUtils::AlignInFrame(rect,
2005 icon->Bounds().Size(), alignment);
2006 drawing_mode oldMode = view->DrawingMode();
2007 view->SetDrawingMode(B_OP_OVER);
2008 view->DrawBitmap(icon, alignedRect.LeftTop());
2009 view->SetDrawingMode(oldMode);
2010 return;
2013 // label, possibly with icon
2014 float availableWidth = rect.Width() + 1;
2015 float width = 0;
2016 float textOffset = 0;
2017 float height = 0;
2019 if (icon != NULL) {
2020 width = icon->Bounds().Width() + DefaultLabelSpacing() + 1;
2021 height = icon->Bounds().Height() + 1;
2022 textOffset = width;
2023 availableWidth -= textOffset;
2026 // truncate the label if necessary and get the width and height
2027 BString truncatedLabel(label);
2029 BFont font;
2030 view->GetFont(&font);
2032 font.TruncateString(&truncatedLabel, B_TRUNCATE_END, availableWidth);
2033 width += ceilf(font.StringWidth(truncatedLabel.String()));
2035 font_height fontHeight;
2036 font.GetHeight(&fontHeight);
2037 float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
2038 height = std::max(height, textHeight);
2040 // handle alignment
2041 BRect alignedRect(BLayoutUtils::AlignOnRect(rect,
2042 BSize(width - 1, height - 1), alignment));
2044 if (icon != NULL) {
2045 BPoint location(alignedRect.LeftTop());
2046 if (icon->Bounds().Height() + 1 < height)
2047 location.y += ceilf((height - icon->Bounds().Height() - 1) / 2);
2049 drawing_mode oldMode = view->DrawingMode();
2050 view->SetDrawingMode(B_OP_OVER);
2051 view->DrawBitmap(icon, location);
2052 view->SetDrawingMode(oldMode);
2055 BPoint location(alignedRect.left + textOffset,
2056 alignedRect.top + ceilf(fontHeight.ascent));
2057 if (textHeight < height)
2058 location.y += ceilf((height - textHeight) / 2);
2060 DrawLabel(view, truncatedLabel.String(), base, flags, location, textColor);
2064 void
2065 HaikuControlLook::GetFrameInsets(frame_type frameType, uint32 flags, float& _left,
2066 float& _top, float& _right, float& _bottom)
2068 // All frames have the same inset on each side.
2069 float inset = 0;
2071 switch (frameType) {
2072 case B_BUTTON_FRAME:
2073 inset = (flags & B_DEFAULT_BUTTON) != 0 ? 5 : 2;
2074 break;
2075 case B_GROUP_FRAME:
2076 case B_MENU_FIELD_FRAME:
2077 inset = 3;
2078 break;
2079 case B_SCROLL_VIEW_FRAME:
2080 case B_TEXT_CONTROL_FRAME:
2081 inset = 2;
2082 break;
2085 _left = inset;
2086 _top = inset;
2087 _right = inset;
2088 _bottom = inset;
2092 void
2093 HaikuControlLook::GetBackgroundInsets(background_type backgroundType,
2094 uint32 flags, float& _left, float& _top, float& _right, float& _bottom)
2096 // Most backgrounds have the same inset on each side.
2097 float inset = 0;
2099 switch (backgroundType) {
2100 case B_BUTTON_BACKGROUND:
2101 case B_MENU_BACKGROUND:
2102 case B_MENU_BAR_BACKGROUND:
2103 case B_MENU_FIELD_BACKGROUND:
2104 case B_MENU_ITEM_BACKGROUND:
2105 inset = 1;
2106 break;
2107 case B_BUTTON_WITH_POP_UP_BACKGROUND:
2108 _left = 1;
2109 _top = 1;
2110 _right = 1 + kButtonPopUpIndicatorWidth;
2111 _bottom = 1;
2112 return;
2113 case B_HORIZONTAL_SCROLL_BAR_BACKGROUND:
2114 _left = 2;
2115 _top = 0;
2116 _right = 1;
2117 _bottom = 0;
2118 return;
2119 case B_VERTICAL_SCROLL_BAR_BACKGROUND:
2120 _left = 0;
2121 _top = 2;
2122 _right = 0;
2123 _bottom = 1;
2124 return;
2127 _left = inset;
2128 _top = inset;
2129 _right = inset;
2130 _bottom = inset;
2134 void
2135 HaikuControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2136 const BRect& updateRect, const rgb_color& base, uint32 flags,
2137 uint32 borders, orientation orientation)
2139 _DrawButtonBackground(view, rect, updateRect, 0.0f, 0.0f, 0.0f, 0.0f,
2140 base, true, flags, borders, orientation);
2144 void
2145 HaikuControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2146 const BRect& updateRect, float radius, const rgb_color& base, uint32 flags,
2147 uint32 borders, orientation orientation)
2149 _DrawButtonBackground(view, rect, updateRect, radius, radius, radius,
2150 radius, base, true, flags, borders, orientation);
2154 void
2155 HaikuControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect,
2156 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2157 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2158 uint32 flags, uint32 borders, orientation orientation)
2160 _DrawButtonBackground(view, rect, updateRect, leftTopRadius,
2161 rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags,
2162 borders, orientation);
2166 // #pragma mark -
2169 void
2170 HaikuControlLook::_DrawButtonFrame(BView* view, BRect& rect,
2171 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2172 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2173 const rgb_color& background, float contrast, float brightness,
2174 uint32 flags, uint32 borders)
2176 if (!rect.IsValid())
2177 return;
2179 // save the clipping constraints of the view
2180 view->PushState();
2182 // set clipping constraints to updateRect
2183 BRegion clipping(updateRect);
2184 view->ConstrainClippingRegion(&clipping);
2186 // If the button is flat and neither activated nor otherwise highlighted
2187 // (mouse hovering or focussed), draw it flat.
2188 if ((flags & B_FLAT) != 0
2189 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0
2190 && ((flags & (B_HOVER | B_FOCUSED)) == 0
2191 || (flags & B_DISABLED) != 0)) {
2192 _DrawFrame(view, rect, background, background, background,
2193 background, borders);
2194 _DrawFrame(view, rect, background, background, background,
2195 background, borders);
2196 view->PopState();
2197 return;
2200 // outer edge colors
2201 rgb_color edgeLightColor;
2202 rgb_color edgeShadowColor;
2204 // default button frame color
2205 rgb_color defaultIndicatorColor = ui_color(B_CONTROL_BORDER_COLOR);
2206 rgb_color cornerBgColor;
2208 if ((flags & B_DISABLED) != 0) {
2209 defaultIndicatorColor = disable_color(defaultIndicatorColor,
2210 background);
2213 drawing_mode oldMode = view->DrawingMode();
2215 if ((flags & B_DEFAULT_BUTTON) != 0) {
2216 cornerBgColor = defaultIndicatorColor;
2217 edgeLightColor = _EdgeLightColor(defaultIndicatorColor,
2218 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2219 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
2220 edgeShadowColor = _EdgeShadowColor(defaultIndicatorColor,
2221 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2222 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9), flags);
2224 // draw default button indicator
2225 // Allow a 1-pixel border of the background to come through.
2226 rect.InsetBy(1, 1);
2228 view->SetHighColor(defaultIndicatorColor);
2229 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2230 rect.InsetBy(1, 1);
2232 view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius);
2233 rect.InsetBy(1, 1);
2234 } else {
2235 cornerBgColor = background;
2236 if ((flags & B_BLEND_FRAME) != 0) {
2237 // set the background color to transparent for the case
2238 // that we are on the desktop
2239 cornerBgColor.alpha = 0;
2240 view->SetDrawingMode(B_OP_ALPHA);
2243 edgeLightColor = _EdgeLightColor(background,
2244 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2245 brightness * 1.0, flags);
2246 edgeShadowColor = _EdgeShadowColor(background,
2247 contrast * (flags & B_DISABLED) != 0 ? 0.0 : 1.0,
2248 brightness * 1.0, flags);
2251 // frame colors
2252 rgb_color frameLightColor = _FrameLightColor(base, flags);
2253 rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2255 // rounded corners
2257 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2258 && leftTopRadius > 0) {
2259 // draw left top rounded corner
2260 BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2261 floorf(rect.left + leftTopRadius),
2262 floorf(rect.top + leftTopRadius));
2263 clipping.Exclude(leftTopCorner);
2264 _DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect,
2265 cornerBgColor, edgeShadowColor, frameLightColor);
2268 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2269 && rightTopRadius > 0) {
2270 // draw right top rounded corner
2271 BRect rightTopCorner(floorf(rect.right - rightTopRadius),
2272 floorf(rect.top), floorf(rect.right),
2273 floorf(rect.top + rightTopRadius));
2274 clipping.Exclude(rightTopCorner);
2275 _DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect,
2276 cornerBgColor, edgeShadowColor, edgeLightColor,
2277 frameLightColor, frameShadowColor);
2280 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2281 && leftBottomRadius > 0) {
2282 // draw left bottom rounded corner
2283 BRect leftBottomCorner(floorf(rect.left),
2284 floorf(rect.bottom - leftBottomRadius),
2285 floorf(rect.left + leftBottomRadius), floorf(rect.bottom));
2286 clipping.Exclude(leftBottomCorner);
2287 _DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect,
2288 cornerBgColor, edgeShadowColor, edgeLightColor,
2289 frameLightColor, frameShadowColor);
2292 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2293 && rightBottomRadius > 0) {
2294 // draw right bottom rounded corner
2295 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius),
2296 floorf(rect.bottom - rightBottomRadius), floorf(rect.right),
2297 floorf(rect.bottom));
2298 clipping.Exclude(rightBottomCorner);
2299 _DrawRoundCornerFrameRightBottom(view, rightBottomCorner,
2300 updateRect, cornerBgColor, edgeLightColor, frameShadowColor);
2303 // clip out the corners
2304 view->ConstrainClippingRegion(&clipping);
2306 // draw outer edge
2307 if ((flags & B_DEFAULT_BUTTON) != 0) {
2308 _DrawOuterResessedFrame(view, rect, defaultIndicatorColor,
2309 contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8),
2310 brightness * ((flags & B_DISABLED) != 0 ? 1.0 : 0.9),
2311 flags, borders);
2312 } else {
2313 _DrawOuterResessedFrame(view, rect, background,
2314 contrast * ((flags & B_DISABLED) != 0 ? 0.0 : 1.0),
2315 brightness * 1.0, flags, borders);
2318 view->SetDrawingMode(oldMode);
2320 // draw frame
2321 if ((flags & B_BLEND_FRAME) != 0) {
2322 drawing_mode oldDrawingMode = view->DrawingMode();
2323 view->SetDrawingMode(B_OP_ALPHA);
2325 _DrawFrame(view, rect, frameLightColor, frameLightColor,
2326 frameShadowColor, frameShadowColor, borders);
2328 view->SetDrawingMode(oldDrawingMode);
2329 } else {
2330 _DrawFrame(view, rect, frameLightColor, frameLightColor,
2331 frameShadowColor, frameShadowColor, borders);
2334 // restore the clipping constraints of the view
2335 view->PopState();
2339 void
2340 HaikuControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect,
2341 const rgb_color& base, float contrast, float brightness, uint32 flags,
2342 uint32 borders)
2344 rgb_color edgeLightColor = _EdgeLightColor(base, contrast,
2345 brightness, flags);
2346 rgb_color edgeShadowColor = _EdgeShadowColor(base, contrast,
2347 brightness, flags);
2349 if ((flags & B_BLEND_FRAME) != 0) {
2350 // assumes the background has already been painted
2351 drawing_mode oldDrawingMode = view->DrawingMode();
2352 view->SetDrawingMode(B_OP_ALPHA);
2354 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2355 edgeLightColor, edgeLightColor, borders);
2357 view->SetDrawingMode(oldDrawingMode);
2358 } else {
2359 _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor,
2360 edgeLightColor, edgeLightColor, borders);
2365 void
2366 HaikuControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2367 const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2368 uint32 borders)
2370 view->BeginLineArray(4);
2372 if (borders & B_LEFT_BORDER) {
2373 view->AddLine(
2374 BPoint(rect.left, rect.bottom),
2375 BPoint(rect.left, rect.top), left);
2376 rect.left++;
2378 if (borders & B_TOP_BORDER) {
2379 view->AddLine(
2380 BPoint(rect.left, rect.top),
2381 BPoint(rect.right, rect.top), top);
2382 rect.top++;
2384 if (borders & B_RIGHT_BORDER) {
2385 view->AddLine(
2386 BPoint(rect.right, rect.top),
2387 BPoint(rect.right, rect.bottom), right);
2388 rect.right--;
2390 if (borders & B_BOTTOM_BORDER) {
2391 view->AddLine(
2392 BPoint(rect.left, rect.bottom),
2393 BPoint(rect.right, rect.bottom), bottom);
2394 rect.bottom--;
2397 view->EndLineArray();
2401 void
2402 HaikuControlLook::_DrawFrame(BView* view, BRect& rect, const rgb_color& left,
2403 const rgb_color& top, const rgb_color& right, const rgb_color& bottom,
2404 const rgb_color& rightTop, const rgb_color& leftBottom, uint32 borders)
2406 view->BeginLineArray(6);
2408 if (borders & B_TOP_BORDER) {
2409 if (borders & B_RIGHT_BORDER) {
2410 view->AddLine(
2411 BPoint(rect.left, rect.top),
2412 BPoint(rect.right - 1, rect.top), top);
2413 view->AddLine(
2414 BPoint(rect.right, rect.top),
2415 BPoint(rect.right, rect.top), rightTop);
2416 } else {
2417 view->AddLine(
2418 BPoint(rect.left, rect.top),
2419 BPoint(rect.right, rect.top), top);
2421 rect.top++;
2424 if (borders & B_LEFT_BORDER) {
2425 view->AddLine(
2426 BPoint(rect.left, rect.top),
2427 BPoint(rect.left, rect.bottom - 1), left);
2428 view->AddLine(
2429 BPoint(rect.left, rect.bottom),
2430 BPoint(rect.left, rect.bottom), leftBottom);
2431 rect.left++;
2434 if (borders & B_BOTTOM_BORDER) {
2435 view->AddLine(
2436 BPoint(rect.left, rect.bottom),
2437 BPoint(rect.right, rect.bottom), bottom);
2438 rect.bottom--;
2441 if (borders & B_RIGHT_BORDER) {
2442 view->AddLine(
2443 BPoint(rect.right, rect.bottom),
2444 BPoint(rect.right, rect.top), right);
2445 rect.right--;
2448 view->EndLineArray();
2452 void
2453 HaikuControlLook::_DrawButtonBackground(BView* view, BRect& rect,
2454 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2455 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2456 bool popupIndicator, uint32 flags, uint32 borders, orientation orientation)
2458 if (!rect.IsValid())
2459 return;
2461 // save the clipping constraints of the view
2462 view->PushState();
2464 // set clipping constraints to updateRect
2465 BRegion clipping(updateRect);
2466 view->ConstrainClippingRegion(&clipping);
2468 // If the button is flat and neither activated nor otherwise highlighted
2469 // (mouse hovering or focussed), draw it flat.
2470 if ((flags & B_FLAT) != 0
2471 && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0
2472 && ((flags & (B_HOVER | B_FOCUSED)) == 0
2473 || (flags & B_DISABLED) != 0)) {
2474 _DrawFlatButtonBackground(view, rect, updateRect, base, popupIndicator,
2475 flags, borders, orientation);
2476 } else {
2477 _DrawNonFlatButtonBackground(view, rect, updateRect, clipping,
2478 leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius,
2479 base, popupIndicator, flags, borders, orientation);
2482 // restore the clipping constraints of the view
2483 view->PopState();
2487 void
2488 HaikuControlLook::_DrawFlatButtonBackground(BView* view, BRect& rect,
2489 const BRect& updateRect, const rgb_color& base, bool popupIndicator,
2490 uint32 flags, uint32 borders, orientation orientation)
2492 _DrawFrame(view, rect, base, base, base, base, borders);
2493 // Not an actual frame, but the method insets our rect as needed.
2495 view->SetHighColor(base);
2496 view->FillRect(rect);
2498 if (popupIndicator) {
2499 BRect indicatorRect(rect);
2500 rect.right -= kButtonPopUpIndicatorWidth;
2501 indicatorRect.left = rect.right + 3;
2502 // 2 pixels for the separator
2504 view->SetHighColor(base);
2505 view->FillRect(indicatorRect);
2507 _DrawPopUpMarker(view, indicatorRect, base, flags);
2512 void
2513 HaikuControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect,
2514 const BRect& updateRect, BRegion& clipping, float leftTopRadius,
2515 float rightTopRadius, float leftBottomRadius, float rightBottomRadius,
2516 const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders,
2517 orientation orientation)
2519 // inner bevel colors
2520 rgb_color bevelLightColor = _BevelLightColor(base, flags);
2521 rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2523 // button background color
2524 rgb_color buttonBgColor;
2525 if ((flags & B_DISABLED) != 0)
2526 buttonBgColor = tint_color(base, 0.7);
2527 else
2528 buttonBgColor = tint_color(base, B_LIGHTEN_1_TINT);
2530 // surface top gradient
2531 BGradientLinear fillGradient;
2532 _MakeButtonGradient(fillGradient, rect, base, flags, orientation);
2534 // rounded corners
2536 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2537 && leftTopRadius > 0) {
2538 // draw left top rounded corner
2539 BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2540 floorf(rect.left + leftTopRadius - 2.0),
2541 floorf(rect.top + leftTopRadius - 2.0));
2542 clipping.Exclude(leftTopCorner);
2543 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2544 bevelLightColor, fillGradient);
2547 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2548 && rightTopRadius > 0) {
2549 // draw right top rounded corner
2550 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2551 floorf(rect.top), floorf(rect.right),
2552 floorf(rect.top + rightTopRadius - 2.0));
2553 clipping.Exclude(rightTopCorner);
2554 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner,
2555 updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2558 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2559 && leftBottomRadius > 0) {
2560 // draw left bottom rounded corner
2561 BRect leftBottomCorner(floorf(rect.left),
2562 floorf(rect.bottom - leftBottomRadius + 2.0),
2563 floorf(rect.left + leftBottomRadius - 2.0),
2564 floorf(rect.bottom));
2565 clipping.Exclude(leftBottomCorner);
2566 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2567 updateRect, bevelLightColor, bevelShadowColor, fillGradient);
2570 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2571 && rightBottomRadius > 0) {
2572 // draw right bottom rounded corner
2573 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2574 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2575 floorf(rect.bottom));
2576 clipping.Exclude(rightBottomCorner);
2577 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2578 updateRect, bevelShadowColor, fillGradient);
2581 // clip out the corners
2582 view->ConstrainClippingRegion(&clipping);
2584 // draw inner bevel
2586 if ((flags & B_ACTIVATED) != 0) {
2587 view->BeginLineArray(4);
2589 // shadow along left/top borders
2590 if (borders & B_LEFT_BORDER) {
2591 view->AddLine(BPoint(rect.left, rect.top),
2592 BPoint(rect.left, rect.bottom), bevelLightColor);
2593 rect.left++;
2595 if (borders & B_TOP_BORDER) {
2596 view->AddLine(BPoint(rect.left, rect.top),
2597 BPoint(rect.right, rect.top), bevelLightColor);
2598 rect.top++;
2601 // softer shadow along left/top borders
2602 if (borders & B_LEFT_BORDER) {
2603 view->AddLine(BPoint(rect.left, rect.top),
2604 BPoint(rect.left, rect.bottom), bevelShadowColor);
2605 rect.left++;
2607 if (borders & B_TOP_BORDER) {
2608 view->AddLine(BPoint(rect.left, rect.top),
2609 BPoint(rect.right, rect.top), bevelShadowColor);
2610 rect.top++;
2613 view->EndLineArray();
2614 } else {
2615 _DrawFrame(view, rect,
2616 bevelLightColor, bevelLightColor,
2617 bevelShadowColor, bevelShadowColor,
2618 buttonBgColor, buttonBgColor, borders);
2621 if (popupIndicator) {
2622 BRect indicatorRect(rect);
2623 rect.right -= kButtonPopUpIndicatorWidth;
2624 indicatorRect.left = rect.right + 3;
2625 // 2 pixels for the separator
2627 // Even when depressed we want the pop-up indicator background and
2628 // separator to cover the area up to the top.
2629 if ((flags & B_ACTIVATED) != 0)
2630 indicatorRect.top--;
2632 // draw the separator
2633 rgb_color separatorBaseColor = base;
2634 if ((flags & B_ACTIVATED) != 0)
2635 separatorBaseColor = tint_color(base, B_DARKEN_1_TINT);
2637 rgb_color separatorLightColor = _EdgeLightColor(separatorBaseColor,
2638 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags);
2639 rgb_color separatorShadowColor = _EdgeShadowColor(separatorBaseColor,
2640 (flags & B_DISABLED) != 0 ? 0.7 : 1.0, 1.0, flags);
2642 view->BeginLineArray(2);
2644 view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top),
2645 BPoint(indicatorRect.left - 2, indicatorRect.bottom),
2646 separatorShadowColor);
2647 view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top),
2648 BPoint(indicatorRect.left - 1, indicatorRect.bottom),
2649 separatorLightColor);
2651 view->EndLineArray();
2653 // draw background and pop-up marker
2654 _DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect,
2655 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags, 0);
2657 if ((flags & B_ACTIVATED) != 0)
2658 indicatorRect.top++;
2660 _DrawPopUpMarker(view, indicatorRect, base, flags);
2663 // fill in the background
2664 view->FillRect(rect, fillGradient);
2668 void
2669 HaikuControlLook::_DrawPopUpMarker(BView* view, const BRect& rect,
2670 const rgb_color& base, uint32 flags)
2672 BPoint center(roundf((rect.left + rect.right) / 2.0),
2673 roundf((rect.top + rect.bottom) / 2.0));
2674 BPoint triangle[3];
2675 triangle[0] = center + BPoint(-2.5, -0.5);
2676 triangle[1] = center + BPoint(2.5, -0.5);
2677 triangle[2] = center + BPoint(0.0, 2.0);
2679 uint32 viewFlags = view->Flags();
2680 view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE);
2682 rgb_color markColor;
2683 if ((flags & B_DISABLED) != 0)
2684 markColor = tint_color(base, 1.35);
2685 else
2686 markColor = tint_color(base, 1.65);
2688 view->SetHighColor(markColor);
2689 view->FillTriangle(triangle[0], triangle[1], triangle[2]);
2691 view->SetFlags(viewFlags);
2695 void
2696 HaikuControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect,
2697 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2698 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2699 bool popupIndicator, uint32 flags)
2701 if (!rect.IsValid() || !rect.Intersects(updateRect))
2702 return;
2704 if (popupIndicator) {
2705 BRect leftRect(rect);
2706 leftRect.right -= 10;
2708 BRect rightRect(rect);
2709 rightRect.left = rightRect.right - 9;
2711 _DrawMenuFieldBackgroundInside(view, leftRect, updateRect,
2712 leftTopRadius, 0.0f, leftBottomRadius, 0.0f, base, flags,
2713 B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER);
2715 _DrawMenuFieldBackgroundInside(view, rightRect, updateRect,
2716 0.0f, rightTopRadius, 0.0f, rightBottomRadius, base, flags,
2717 B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER);
2719 _DrawPopUpMarker(view, rightRect, base, flags);
2721 // draw a line on the left of the popup frame
2722 rgb_color bevelShadowColor = _BevelShadowColor(base, flags);
2723 view->SetHighColor(bevelShadowColor);
2724 BPoint leftTopCorner(floorf(rightRect.left - 1.0),
2725 floorf(rightRect.top - 1.0));
2726 BPoint leftBottomCorner(floorf(rightRect.left - 1.0),
2727 floorf(rightRect.bottom + 1.0));
2728 view->StrokeLine(leftTopCorner, leftBottomCorner);
2730 rect = leftRect;
2731 } else {
2732 _DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius,
2733 rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags);
2738 void
2739 HaikuControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect,
2740 const BRect& updateRect, float leftTopRadius, float rightTopRadius,
2741 float leftBottomRadius, float rightBottomRadius, const rgb_color& base,
2742 uint32 flags, uint32 borders)
2744 if (!rect.IsValid() || !rect.Intersects(updateRect))
2745 return;
2747 // save the clipping constraints of the view
2748 view->PushState();
2750 // set clipping constraints to updateRect
2751 BRegion clipping(updateRect);
2752 view->ConstrainClippingRegion(&clipping);
2754 // frame colors
2755 rgb_color frameLightColor = _FrameLightColor(base, flags);
2756 rgb_color frameShadowColor = _FrameShadowColor(base, flags);
2758 // indicator background color
2759 rgb_color indicatorBase;
2760 if ((borders & B_LEFT_BORDER) != 0)
2761 indicatorBase = base;
2762 else {
2763 if ((flags & B_DISABLED) != 0)
2764 indicatorBase = tint_color(base, 1.05);
2765 else
2766 indicatorBase = tint_color(base, 1.12);
2769 // bevel colors
2770 rgb_color cornerColor = tint_color(indicatorBase, 0.85);
2771 rgb_color bevelColor1 = tint_color(indicatorBase, 0.3);
2772 rgb_color bevelColor2 = tint_color(indicatorBase, 0.5);
2773 rgb_color bevelColor3 = tint_color(indicatorBase, 1.03);
2775 if ((flags & B_DISABLED) != 0) {
2776 cornerColor = tint_color(indicatorBase, 0.8);
2777 bevelColor1 = tint_color(indicatorBase, 0.7);
2778 bevelColor2 = tint_color(indicatorBase, 0.8);
2779 bevelColor3 = tint_color(indicatorBase, 1.01);
2780 } else {
2781 cornerColor = tint_color(indicatorBase, 0.85);
2782 bevelColor1 = tint_color(indicatorBase, 0.3);
2783 bevelColor2 = tint_color(indicatorBase, 0.5);
2784 bevelColor3 = tint_color(indicatorBase, 1.03);
2787 // surface top gradient
2788 BGradientLinear fillGradient;
2789 _MakeButtonGradient(fillGradient, rect, indicatorBase, flags);
2791 // rounded corners
2793 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0
2794 && leftTopRadius > 0) {
2795 // draw left top rounded corner
2796 BRect leftTopCorner(floorf(rect.left), floorf(rect.top),
2797 floorf(rect.left + leftTopRadius - 2.0),
2798 floorf(rect.top + leftTopRadius - 2.0));
2799 clipping.Exclude(leftTopCorner);
2801 BRegion cornerClipping(leftTopCorner);
2802 view->ConstrainClippingRegion(&cornerClipping);
2804 BRect ellipseRect(leftTopCorner);
2805 ellipseRect.InsetBy(-1.0, -1.0);
2806 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2807 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2809 // draw the frame (again)
2810 view->SetHighColor(frameLightColor);
2811 view->FillEllipse(ellipseRect);
2813 // draw the bevel and background
2814 _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect,
2815 bevelColor1, fillGradient);
2818 if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0
2819 && rightTopRadius > 0) {
2820 // draw right top rounded corner
2821 BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0),
2822 floorf(rect.top), floorf(rect.right),
2823 floorf(rect.top + rightTopRadius - 2.0));
2824 clipping.Exclude(rightTopCorner);
2826 BRegion cornerClipping(rightTopCorner);
2827 view->ConstrainClippingRegion(&cornerClipping);
2829 BRect ellipseRect(rightTopCorner);
2830 ellipseRect.InsetBy(-1.0, -1.0);
2831 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2832 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2834 // draw the frame (again)
2835 if (frameLightColor == frameShadowColor) {
2836 view->SetHighColor(frameLightColor);
2837 view->FillEllipse(ellipseRect);
2838 } else {
2839 BGradientLinear gradient;
2840 gradient.AddColor(frameLightColor, 0);
2841 gradient.AddColor(frameShadowColor, 255);
2842 gradient.SetStart(rightTopCorner.LeftTop());
2843 gradient.SetEnd(rightTopCorner.RightBottom());
2844 view->FillEllipse(ellipseRect, gradient);
2847 // draw the bevel and background
2848 _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect,
2849 bevelColor1, bevelColor3, fillGradient);
2852 if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2853 && leftBottomRadius > 0) {
2854 // draw left bottom rounded corner
2855 BRect leftBottomCorner(floorf(rect.left),
2856 floorf(rect.bottom - leftBottomRadius + 2.0),
2857 floorf(rect.left + leftBottomRadius - 2.0),
2858 floorf(rect.bottom));
2859 clipping.Exclude(leftBottomCorner);
2861 BRegion cornerClipping(leftBottomCorner);
2862 view->ConstrainClippingRegion(&cornerClipping);
2864 BRect ellipseRect(leftBottomCorner);
2865 ellipseRect.InsetBy(-1.0, -1.0);
2866 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2867 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2869 // draw the frame (again)
2870 if (frameLightColor == frameShadowColor) {
2871 view->SetHighColor(frameLightColor);
2872 view->FillEllipse(ellipseRect);
2873 } else {
2874 BGradientLinear gradient;
2875 gradient.AddColor(frameLightColor, 0);
2876 gradient.AddColor(frameShadowColor, 255);
2877 gradient.SetStart(leftBottomCorner.LeftTop());
2878 gradient.SetEnd(leftBottomCorner.RightBottom());
2879 view->FillEllipse(ellipseRect, gradient);
2882 // draw the bevel and background
2883 _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner,
2884 updateRect, bevelColor2, bevelColor3, fillGradient);
2887 if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0
2888 && rightBottomRadius > 0) {
2889 // draw right bottom rounded corner
2890 BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0),
2891 floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right),
2892 floorf(rect.bottom));
2893 clipping.Exclude(rightBottomCorner);
2895 BRegion cornerClipping(rightBottomCorner);
2896 view->ConstrainClippingRegion(&cornerClipping);
2898 BRect ellipseRect(rightBottomCorner);
2899 ellipseRect.InsetBy(-1.0, -1.0);
2900 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
2901 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
2903 // draw the frame (again)
2904 view->SetHighColor(frameShadowColor);
2905 view->FillEllipse(ellipseRect);
2907 // draw the bevel and background
2908 _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner,
2909 updateRect, bevelColor3, fillGradient);
2912 // clip out the corners
2913 view->ConstrainClippingRegion(&clipping);
2915 // draw the bevel
2916 _DrawFrame(view, rect,
2917 bevelColor2, bevelColor1,
2918 bevelColor3, bevelColor3,
2919 cornerColor, cornerColor,
2920 borders);
2922 // fill in the background
2923 view->FillRect(rect, fillGradient);
2925 // restore the clipping constraints of the view
2926 view->PopState();
2930 void
2931 HaikuControlLook::_DrawRoundCornerLeftTop(BView* view, BRect& cornerRect,
2932 const BRect& updateRect, const rgb_color& background,
2933 const rgb_color& edgeColor, const rgb_color& frameColor,
2934 const rgb_color& bevelColor, const BGradientLinear& fillGradient)
2936 _DrawRoundCornerFrameLeftTop(view, cornerRect, updateRect,
2937 background, edgeColor, frameColor);
2938 _DrawRoundCornerBackgroundLeftTop(view, cornerRect, updateRect,
2939 bevelColor, fillGradient);
2943 void
2944 HaikuControlLook::_DrawRoundCornerFrameLeftTop(BView* view, BRect& cornerRect,
2945 const BRect& updateRect, const rgb_color& background,
2946 const rgb_color& edgeColor, const rgb_color& frameColor)
2948 // constrain clipping region to corner
2949 BRegion clipping(cornerRect);
2950 view->ConstrainClippingRegion(&clipping);
2952 // background
2953 view->SetHighColor(background);
2954 view->FillRect(cornerRect);
2956 // outer edge
2957 BRect ellipseRect(cornerRect);
2958 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2959 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2961 view->SetHighColor(edgeColor);
2962 view->FillEllipse(ellipseRect);
2964 // frame
2965 ellipseRect.InsetBy(1, 1);
2966 cornerRect.left++;
2967 cornerRect.top++;
2968 view->SetHighColor(frameColor);
2969 view->FillEllipse(ellipseRect);
2971 // prepare for bevel
2972 cornerRect.left++;
2973 cornerRect.top++;
2977 void
2978 HaikuControlLook::_DrawRoundCornerBackgroundLeftTop(BView* view, BRect& cornerRect,
2979 const BRect& updateRect, const rgb_color& bevelColor,
2980 const BGradientLinear& fillGradient)
2982 // constrain clipping region to corner
2983 BRegion clipping(cornerRect);
2984 view->ConstrainClippingRegion(&clipping);
2986 BRect ellipseRect(cornerRect);
2987 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
2988 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
2990 // bevel
2991 view->SetHighColor(bevelColor);
2992 view->FillEllipse(ellipseRect);
2994 // gradient
2995 ellipseRect.InsetBy(1, 1);
2996 view->FillEllipse(ellipseRect, fillGradient);
3000 void
3001 HaikuControlLook::_DrawRoundCornerRightTop(BView* view, BRect& cornerRect,
3002 const BRect& updateRect, const rgb_color& background,
3003 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
3004 const rgb_color& frameTopColor, const rgb_color& frameRightColor,
3005 const rgb_color& bevelTopColor, const rgb_color& bevelRightColor,
3006 const BGradientLinear& fillGradient)
3008 _DrawRoundCornerFrameRightTop(view, cornerRect, updateRect,
3009 background, edgeTopColor, edgeRightColor, frameTopColor,
3010 frameRightColor);
3011 _DrawRoundCornerBackgroundRightTop(view, cornerRect, updateRect,
3012 bevelTopColor, bevelRightColor, fillGradient);
3016 void
3017 HaikuControlLook::_DrawRoundCornerFrameRightTop(BView* view, BRect& cornerRect,
3018 const BRect& updateRect, const rgb_color& background,
3019 const rgb_color& edgeTopColor, const rgb_color& edgeRightColor,
3020 const rgb_color& frameTopColor, const rgb_color& frameRightColor)
3022 // constrain clipping region to corner
3023 BRegion clipping(cornerRect);
3024 view->ConstrainClippingRegion(&clipping);
3026 // background
3027 view->SetHighColor(background);
3028 view->FillRect(cornerRect);
3030 // outer edge
3031 BRect ellipseRect(cornerRect);
3032 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3033 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
3035 BGradientLinear gradient;
3036 gradient.AddColor(edgeTopColor, 0);
3037 gradient.AddColor(edgeRightColor, 255);
3038 gradient.SetStart(cornerRect.LeftTop());
3039 gradient.SetEnd(cornerRect.RightBottom());
3040 view->FillEllipse(ellipseRect, gradient);
3042 // frame
3043 ellipseRect.InsetBy(1, 1);
3044 cornerRect.right--;
3045 cornerRect.top++;
3046 if (frameTopColor == frameRightColor) {
3047 view->SetHighColor(frameTopColor);
3048 view->FillEllipse(ellipseRect);
3049 } else {
3050 gradient.SetColor(0, frameTopColor);
3051 gradient.SetColor(1, frameRightColor);
3052 gradient.SetStart(cornerRect.LeftTop());
3053 gradient.SetEnd(cornerRect.RightBottom());
3054 view->FillEllipse(ellipseRect, gradient);
3057 // prepare for bevel
3058 cornerRect.right--;
3059 cornerRect.top++;
3063 void
3064 HaikuControlLook::_DrawRoundCornerBackgroundRightTop(BView* view, BRect& cornerRect,
3065 const BRect& updateRect, const rgb_color& bevelTopColor,
3066 const rgb_color& bevelRightColor, const BGradientLinear& fillGradient)
3068 // constrain clipping region to corner
3069 BRegion clipping(cornerRect);
3070 view->ConstrainClippingRegion(&clipping);
3072 BRect ellipseRect(cornerRect);
3073 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3074 ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2;
3076 // bevel
3077 BGradientLinear gradient;
3078 gradient.AddColor(bevelTopColor, 0);
3079 gradient.AddColor(bevelRightColor, 255);
3080 gradient.SetStart(cornerRect.LeftTop());
3081 gradient.SetEnd(cornerRect.RightBottom());
3082 view->FillEllipse(ellipseRect, gradient);
3084 // gradient
3085 ellipseRect.InsetBy(1, 1);
3086 view->FillEllipse(ellipseRect, fillGradient);
3090 void
3091 HaikuControlLook::_DrawRoundCornerLeftBottom(BView* view, BRect& cornerRect,
3092 const BRect& updateRect, const rgb_color& background,
3093 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
3094 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor,
3095 const rgb_color& bevelLeftColor, const rgb_color& bevelBottomColor,
3096 const BGradientLinear& fillGradient)
3098 _DrawRoundCornerFrameLeftBottom(view, cornerRect, updateRect,
3099 background, edgeLeftColor, edgeBottomColor, frameLeftColor,
3100 frameBottomColor);
3101 _DrawRoundCornerBackgroundLeftBottom(view, cornerRect, updateRect,
3102 bevelLeftColor, bevelBottomColor, fillGradient);
3106 void
3107 HaikuControlLook::_DrawRoundCornerFrameLeftBottom(BView* view, BRect& cornerRect,
3108 const BRect& updateRect, const rgb_color& background,
3109 const rgb_color& edgeLeftColor, const rgb_color& edgeBottomColor,
3110 const rgb_color& frameLeftColor, const rgb_color& frameBottomColor)
3112 // constrain clipping region to corner
3113 BRegion clipping(cornerRect);
3114 view->ConstrainClippingRegion(&clipping);
3116 // background
3117 view->SetHighColor(background);
3118 view->FillRect(cornerRect);
3120 // outer edge
3121 BRect ellipseRect(cornerRect);
3122 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
3123 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3125 BGradientLinear gradient;
3126 gradient.AddColor(edgeLeftColor, 0);
3127 gradient.AddColor(edgeBottomColor, 255);
3128 gradient.SetStart(cornerRect.LeftTop());
3129 gradient.SetEnd(cornerRect.RightBottom());
3130 view->FillEllipse(ellipseRect, gradient);
3132 // frame
3133 ellipseRect.InsetBy(1, 1);
3134 cornerRect.left++;
3135 cornerRect.bottom--;
3136 if (frameLeftColor == frameBottomColor) {
3137 view->SetHighColor(frameLeftColor);
3138 view->FillEllipse(ellipseRect);
3139 } else {
3140 gradient.SetColor(0, frameLeftColor);
3141 gradient.SetColor(1, frameBottomColor);
3142 gradient.SetStart(cornerRect.LeftTop());
3143 gradient.SetEnd(cornerRect.RightBottom());
3144 view->FillEllipse(ellipseRect, gradient);
3147 // prepare for bevel
3148 cornerRect.left++;
3149 cornerRect.bottom--;
3153 void
3154 HaikuControlLook::_DrawRoundCornerBackgroundLeftBottom(BView* view, BRect& cornerRect,
3155 const BRect& updateRect, const rgb_color& bevelLeftColor,
3156 const rgb_color& bevelBottomColor, const BGradientLinear& fillGradient)
3158 // constrain clipping region to corner
3159 BRegion clipping(cornerRect);
3160 view->ConstrainClippingRegion(&clipping);
3162 BRect ellipseRect(cornerRect);
3163 ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2;
3164 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3166 // bevel
3167 BGradientLinear gradient;
3168 gradient.AddColor(bevelLeftColor, 0);
3169 gradient.AddColor(bevelBottomColor, 255);
3170 gradient.SetStart(cornerRect.LeftTop());
3171 gradient.SetEnd(cornerRect.RightBottom());
3172 view->FillEllipse(ellipseRect, gradient);
3174 // gradient
3175 ellipseRect.InsetBy(1, 1);
3176 view->FillEllipse(ellipseRect, fillGradient);
3180 void
3181 HaikuControlLook::_DrawRoundCornerRightBottom(BView* view, BRect& cornerRect,
3182 const BRect& updateRect, const rgb_color& background,
3183 const rgb_color& edgeColor, const rgb_color& frameColor,
3184 const rgb_color& bevelColor, const BGradientLinear& fillGradient)
3186 _DrawRoundCornerFrameRightBottom(view, cornerRect, updateRect,
3187 background, edgeColor, frameColor);
3188 _DrawRoundCornerBackgroundRightBottom(view, cornerRect, updateRect,
3189 bevelColor, fillGradient);
3193 void
3194 HaikuControlLook::_DrawRoundCornerFrameRightBottom(BView* view, BRect& cornerRect,
3195 const BRect& updateRect, const rgb_color& background,
3196 const rgb_color& edgeColor, const rgb_color& frameColor)
3198 // constrain clipping region to corner
3199 BRegion clipping(cornerRect);
3200 view->ConstrainClippingRegion(&clipping);
3202 // background
3203 view->SetHighColor(background);
3204 view->FillRect(cornerRect);
3206 // outer edge
3207 BRect ellipseRect(cornerRect);
3208 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3209 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3211 view->SetHighColor(edgeColor);
3212 view->FillEllipse(ellipseRect);
3214 // frame
3215 ellipseRect.InsetBy(1, 1);
3216 cornerRect.right--;
3217 cornerRect.bottom--;
3218 view->SetHighColor(frameColor);
3219 view->FillEllipse(ellipseRect);
3221 // prepare for bevel
3222 cornerRect.right--;
3223 cornerRect.bottom--;
3227 void
3228 HaikuControlLook::_DrawRoundCornerBackgroundRightBottom(BView* view,
3229 BRect& cornerRect, const BRect& updateRect, const rgb_color& bevelColor,
3230 const BGradientLinear& fillGradient)
3232 // constrain clipping region to corner
3233 BRegion clipping(cornerRect);
3234 view->ConstrainClippingRegion(&clipping);
3236 BRect ellipseRect(cornerRect);
3237 ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2;
3238 ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2;
3240 // bevel
3241 view->SetHighColor(bevelColor);
3242 view->FillEllipse(ellipseRect);
3244 // gradient
3245 ellipseRect.InsetBy(1, 1);
3246 view->FillEllipse(ellipseRect, fillGradient);
3250 void
3251 HaikuControlLook::_DrawRoundBarCorner(BView* view, BRect& rect,
3252 const BRect& updateRect,
3253 const rgb_color& edgeLightColor, const rgb_color& edgeShadowColor,
3254 const rgb_color& frameLightColor, const rgb_color& frameShadowColor,
3255 const rgb_color& fillLightColor, const rgb_color& fillShadowColor,
3256 float leftInset, float topInset, float rightInset, float bottomInset,
3257 orientation orientation)
3259 if (!rect.IsValid() || !rect.Intersects(updateRect))
3260 return;
3262 BGradientLinear gradient;
3263 gradient.AddColor(edgeShadowColor, 0);
3264 gradient.AddColor(edgeLightColor, 255);
3265 gradient.SetStart(rect.LeftTop());
3266 if (orientation == B_HORIZONTAL)
3267 gradient.SetEnd(rect.LeftBottom());
3268 else
3269 gradient.SetEnd(rect.RightTop());
3271 view->FillEllipse(rect, gradient);
3273 rect.left += leftInset;
3274 rect.top += topInset;
3275 rect.right += rightInset;
3276 rect.bottom += bottomInset;
3278 gradient.MakeEmpty();
3279 gradient.AddColor(frameShadowColor, 0);
3280 gradient.AddColor(frameLightColor, 255);
3281 gradient.SetStart(rect.LeftTop());
3282 if (orientation == B_HORIZONTAL)
3283 gradient.SetEnd(rect.LeftBottom());
3284 else
3285 gradient.SetEnd(rect.RightTop());
3287 view->FillEllipse(rect, gradient);
3289 rect.left += leftInset;
3290 rect.top += topInset;
3291 rect.right += rightInset;
3292 rect.bottom += bottomInset;
3294 gradient.MakeEmpty();
3295 gradient.AddColor(fillShadowColor, 0);
3296 gradient.AddColor(fillLightColor, 255);
3297 gradient.SetStart(rect.LeftTop());
3298 if (orientation == B_HORIZONTAL)
3299 gradient.SetEnd(rect.LeftBottom());
3300 else
3301 gradient.SetEnd(rect.RightTop());
3303 view->FillEllipse(rect, gradient);
3307 rgb_color
3308 HaikuControlLook::_EdgeLightColor(const rgb_color& base, float contrast,
3309 float brightness, uint32 flags)
3311 rgb_color edgeLightColor;
3313 if ((flags & B_BLEND_FRAME) != 0) {
3314 uint8 alpha = uint8(20 * contrast);
3315 uint8 white = uint8(255 * brightness);
3317 edgeLightColor = (rgb_color){ white, white, white, alpha };
3318 } else {
3319 // colors
3320 float tintLight = kEdgeBevelLightTint;
3322 if (contrast == 0.0)
3323 tintLight = B_NO_TINT;
3324 else if (contrast != 1.0)
3325 tintLight = B_NO_TINT + (tintLight - B_NO_TINT) * contrast;
3327 edgeLightColor = tint_color(base, tintLight);
3329 if (brightness < 1.0) {
3330 edgeLightColor.red = uint8(edgeLightColor.red * brightness);
3331 edgeLightColor.green = uint8(edgeLightColor.green * brightness);
3332 edgeLightColor.blue = uint8(edgeLightColor.blue * brightness);
3336 return edgeLightColor;
3340 rgb_color
3341 HaikuControlLook::_EdgeShadowColor(const rgb_color& base, float contrast,
3342 float brightness, uint32 flags)
3344 rgb_color edgeShadowColor;
3346 if ((flags & B_BLEND_FRAME) != 0) {
3347 uint8 alpha = uint8(20 * contrast);
3348 edgeShadowColor = (rgb_color){ 0, 0, 0, alpha };
3349 } else {
3350 float tintShadow = kEdgeBevelShadowTint;
3352 if (contrast == 0.0)
3353 tintShadow = B_NO_TINT;
3354 else if (contrast != 1.0)
3355 tintShadow = B_NO_TINT + (tintShadow - B_NO_TINT) * contrast;
3357 edgeShadowColor = tint_color(base, tintShadow);
3359 if (brightness < 1.0) {
3360 edgeShadowColor.red = uint8(edgeShadowColor.red * brightness);
3361 edgeShadowColor.green = uint8(edgeShadowColor.green * brightness);
3362 edgeShadowColor.blue = uint8(edgeShadowColor.blue * brightness);
3366 return edgeShadowColor;
3370 rgb_color
3371 HaikuControlLook::_FrameLightColor(const rgb_color& base, uint32 flags)
3373 if ((flags & B_FOCUSED) != 0)
3374 return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3376 if ((flags & B_ACTIVATED) != 0)
3377 return _FrameShadowColor(base, flags & ~B_ACTIVATED);
3379 rgb_color frameLightColor;
3381 if ((flags & B_DISABLED) != 0) {
3382 // TODO: B_BLEND_FRAME
3383 frameLightColor = tint_color(base, 1.145);
3385 if ((flags & B_DEFAULT_BUTTON) != 0)
3386 frameLightColor = tint_color(frameLightColor, 1.14);
3387 } else {
3388 if ((flags & B_BLEND_FRAME) != 0)
3389 frameLightColor = (rgb_color){ 0, 0, 0, 75 };
3390 else
3391 frameLightColor = tint_color(base, 1.33);
3393 if ((flags & B_DEFAULT_BUTTON) != 0)
3394 frameLightColor = tint_color(frameLightColor, 1.35);
3397 return frameLightColor;
3401 rgb_color
3402 HaikuControlLook::_FrameShadowColor(const rgb_color& base, uint32 flags)
3404 if ((flags & B_FOCUSED) != 0)
3405 return ui_color(B_KEYBOARD_NAVIGATION_COLOR);
3407 if ((flags & B_ACTIVATED) != 0)
3408 return _FrameLightColor(base, flags & ~B_ACTIVATED);
3410 rgb_color frameShadowColor;
3412 if ((flags & B_DISABLED) != 0) {
3413 // TODO: B_BLEND_FRAME
3414 frameShadowColor = tint_color(base, 1.24);
3416 if ((flags & B_DEFAULT_BUTTON) != 0) {
3417 frameShadowColor = tint_color(base, 1.145);
3418 frameShadowColor = tint_color(frameShadowColor, 1.12);
3420 } else {
3421 if ((flags & B_DEFAULT_BUTTON) != 0) {
3422 if ((flags & B_BLEND_FRAME) != 0)
3423 frameShadowColor = (rgb_color){ 0, 0, 0, 75 };
3424 else
3425 frameShadowColor = tint_color(base, 1.33);
3427 frameShadowColor = tint_color(frameShadowColor, 1.5);
3428 } else {
3429 if ((flags & B_BLEND_FRAME) != 0)
3430 frameShadowColor = (rgb_color){ 0, 0, 0, 95 };
3431 else
3432 frameShadowColor = tint_color(base, 1.47);
3436 return frameShadowColor;
3440 rgb_color
3441 HaikuControlLook::_BevelLightColor(const rgb_color& base, uint32 flags)
3443 rgb_color bevelLightColor = tint_color(base, 0.2);
3445 if ((flags & B_DISABLED) != 0)
3446 bevelLightColor = tint_color(base, B_LIGHTEN_1_TINT);
3448 if ((flags & B_ACTIVATED) != 0)
3449 bevelLightColor = tint_color(base, B_DARKEN_1_TINT);
3451 return bevelLightColor;
3455 rgb_color
3456 HaikuControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags)
3458 rgb_color bevelShadowColor = tint_color(base, 1.08);
3460 if ((flags & B_DISABLED) != 0)
3461 bevelShadowColor = base;
3463 if ((flags & B_ACTIVATED) != 0)
3464 bevelShadowColor = tint_color(base, B_DARKEN_1_TINT);
3466 return bevelShadowColor;
3470 void
3471 HaikuControlLook::_FillGradient(BView* view, const BRect& rect,
3472 const rgb_color& base, float topTint, float bottomTint,
3473 orientation orientation)
3475 BGradientLinear gradient;
3476 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3477 view->FillRect(rect, gradient);
3481 void
3482 HaikuControlLook::_FillGlossyGradient(BView* view, const BRect& rect,
3483 const rgb_color& base, float topTint, float middle1Tint,
3484 float middle2Tint, float bottomTint, orientation orientation)
3486 BGradientLinear gradient;
3487 _MakeGlossyGradient(gradient, rect, base, topTint, middle1Tint,
3488 middle2Tint, bottomTint, orientation);
3489 view->FillRect(rect, gradient);
3493 void
3494 HaikuControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect,
3495 const rgb_color& base, float topTint, float bottomTint,
3496 orientation orientation) const
3498 gradient.AddColor(tint_color(base, topTint), 0);
3499 gradient.AddColor(tint_color(base, bottomTint), 255);
3500 gradient.SetStart(rect.LeftTop());
3501 if (orientation == B_HORIZONTAL)
3502 gradient.SetEnd(rect.LeftBottom());
3503 else
3504 gradient.SetEnd(rect.RightTop());
3508 void
3509 HaikuControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect,
3510 const rgb_color& base, float topTint, float middle1Tint,
3511 float middle2Tint, float bottomTint,
3512 orientation orientation) const
3514 gradient.AddColor(tint_color(base, topTint), 0);
3515 gradient.AddColor(tint_color(base, middle1Tint), 132);
3516 gradient.AddColor(tint_color(base, middle2Tint), 136);
3517 gradient.AddColor(tint_color(base, bottomTint), 255);
3518 gradient.SetStart(rect.LeftTop());
3519 if (orientation == B_HORIZONTAL)
3520 gradient.SetEnd(rect.LeftBottom());
3521 else
3522 gradient.SetEnd(rect.RightTop());
3526 void
3527 HaikuControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect,
3528 const rgb_color& base, uint32 flags, orientation orientation) const
3530 float topTint = 0.49;
3531 float middleTint1 = 0.62;
3532 float middleTint2 = 0.76;
3533 float bottomTint = 0.90;
3535 if ((flags & B_ACTIVATED) != 0) {
3536 topTint = 1.11;
3537 bottomTint = 1.08;
3540 if ((flags & B_DISABLED) != 0) {
3541 topTint = (topTint + B_NO_TINT) / 2;
3542 middleTint1 = (middleTint1 + B_NO_TINT) / 2;
3543 middleTint2 = (middleTint2 + B_NO_TINT) / 2;
3544 bottomTint = (bottomTint + B_NO_TINT) / 2;
3545 } else if ((flags & B_HOVER) != 0) {
3546 topTint *= kHoverTintFactor;
3547 middleTint1 *= kHoverTintFactor;
3548 middleTint2 *= kHoverTintFactor;
3549 bottomTint *= kHoverTintFactor;
3552 if ((flags & B_ACTIVATED) != 0) {
3553 _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation);
3554 } else {
3555 _MakeGlossyGradient(gradient, rect, base, topTint, middleTint1,
3556 middleTint2, bottomTint, orientation);
3562 bool
3563 HaikuControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
3564 rgb_color& color, uint32 flags) const
3566 if ((flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED)) == 0) {
3567 // no mark to be drawn at all
3568 return false;
3571 color = ui_color(B_CONTROL_MARK_COLOR);
3573 float mix = 1.0;
3575 if ((flags & B_DISABLED) != 0) {
3576 // activated, but disabled
3577 mix = 0.4;
3578 } else if ((flags & B_CLICKED) != 0) {
3579 if ((flags & B_ACTIVATED) != 0) {
3580 // losing activation
3581 mix = 0.7;
3582 } else {
3583 // becoming activated (or losing partial activation)
3584 mix = 0.3;
3586 } else if ((flags & B_PARTIALLY_ACTIVATED) != 0) {
3587 // partially activated
3588 mix = 0.5;
3589 } else {
3590 // simply activated
3593 color.red = uint8(color.red * mix + base.red * (1.0 - mix));
3594 color.green = uint8(color.green * mix + base.green * (1.0 - mix));
3595 color.blue = uint8(color.blue * mix + base.blue * (1.0 - mix));
3597 return true;
3601 } // namespace BPrivate