diff --git a/headers/os/interface/ControlLook.h b/headers/os/interface/ControlLook.h index 8e2baae882..2f7af32d19 100644 --- a/headers/os/interface/ControlLook.h +++ b/headers/os/interface/ControlLook.h @@ -86,7 +86,6 @@ public: B_FLAT = 1 << 8, // flat look (e.g. button background) B_INVALID = 1 << 9, // invalid value, use B_FAILURE_COLOR B_IS_CONTROL = 1 << 10, // use control colors - B_SCROLLABLE = 1 << 11, // scroll bar within bounds B_BLEND_FRAME = 1 << 16, }; @@ -225,17 +224,15 @@ public: const rgb_color& base, uint32 flags = 0) = 0; - virtual void DrawScrollBar(BView* view, BRect& rect, + virtual void DrawScrollBarBackground(BView* view, + BRect& rect1, BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation, - bool doubleArrows = false, - int32 buttonDown = -1) = 0; - virtual void DrawScrollBarThumb(BView* view, BRect& rect, - BRect& thumbRect, const BRect& updateRect, + orientation orientation) = 0; + virtual void DrawScrollBarBackground(BView* view, + BRect& rect, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation, - uint32 knobStyle = 0) = 0; + orientation orientation) = 0; virtual void DrawScrollViewFrame(BView* view, BRect& rect, const BRect& updateRect, diff --git a/headers/os/interface/ScrollBar.h b/headers/os/interface/ScrollBar.h index 161575443e..873ab84535 100644 --- a/headers/os/interface/ScrollBar.h +++ b/headers/os/interface/ScrollBar.h @@ -114,7 +114,6 @@ private: // disabled BScrollBar& operator=(const BScrollBar& other); - bool _ScrollingEnabled() const; bool _DoubleArrows() const; void _UpdateThumbFrame(); float _ValueFor(BPoint where) const; @@ -122,6 +121,14 @@ private: BRect _ButtonRectFor(int32 button) const; void _UpdateTargetValue(BPoint where); void _UpdateArrowButtons(); + void _DrawDisabledBackground(BRect area, + const rgb_color& light, + const rgb_color& dark, + const rgb_color& fill); + void _DrawArrowButton(int32 direction, + bool doubleArrows, BRect frame, + const BRect& updateRect, + bool enabled, bool down); BSize _MinSize() const; diff --git a/headers/private/interface/HaikuControlLook.h b/headers/private/interface/HaikuControlLook.h index cbdf430e2e..09d8e69614 100644 --- a/headers/private/interface/HaikuControlLook.h +++ b/headers/private/interface/HaikuControlLook.h @@ -157,17 +157,15 @@ public: const rgb_color& base, uint32 flags = 0); - virtual void DrawScrollBar(BView* view, BRect& rect, + virtual void DrawScrollBarBackground(BView* view, + BRect& rect1, BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation, - bool doubleArrows = false, - int32 buttonDown = -1); - virtual void DrawScrollBarThumb(BView* view, BRect& rect, - BRect& thumbRect, const BRect& updateRect, + orientation orientation); + virtual void DrawScrollBarBackground(BView* view, + BRect& rect, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation, - uint32 knobStyle = 0); + orientation orientation); virtual void DrawScrollViewFrame(BView* view, BRect& rect, const BRect& updateRect, @@ -561,26 +559,6 @@ protected: const rgb_color& base, rgb_color& color, uint32 flags) const; - void _DrawScrollBarBackground(BView* view, - BRect& rect1, BRect& rect2, - const BRect& updateRect, - const rgb_color& base, uint32 flags, - orientation orientation); - void _DrawScrollBarBackground(BView* view, - BRect& rect, const BRect& updateRect, - const rgb_color& base, uint32 flags, - orientation orientation); - void _DrawDisabledScrollBarBackground(BView* view, - BRect rect, orientation orientation, - const rgb_color& light, - const rgb_color& dark, - const rgb_color& fill); - void _DrawScrollBarArrowButton(BView* view, - BRect rect, const BRect& updateRect, - const rgb_color& base, uint32 flags, - int32 direction, orientation orientation, - bool doubleArrows, bool down); - private: bool fCachedOutline; }; diff --git a/headers/private/interface/ScrollBarPrivate.h b/headers/private/interface/ScrollBarPrivate.h deleted file mode 100644 index 7392449d01..0000000000 --- a/headers/private/interface/ScrollBarPrivate.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018 Haiku, Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * John Scipione, jscipione@gmail.com - */ -#ifndef _SCROLL_BAR_PRIVATE_H -#define _SCROLL_BAR_PRIVATE_H - -// Constants for determining which arrow is down and are defined with respect -// to double arrow mode. ARROW_1 and ARROW_4 refer to the outer pair of arrows -// while ARROW_2 and ARROW_3 refer to the inner ones. ARROW_1 point left/up -// and ARROW_4 points right/down. THUMB is the scroll bar thumb. -enum { - SCROLL_NO_ARROW = -1, - SCROLL_ARROW_1, - SCROLL_ARROW_2, - SCROLL_ARROW_3, - SCROLL_ARROW_4, - SCROLL_THUMB -}; - -// constants for determining which knob style to draw on scroll bar -typedef enum { - KNOB_NONE = 0, - KNOB_DOTS, - KNOB_LINES -} knob_style; - - -#endif // _SCROLL_BAR_PRIVATE_H diff --git a/src/kits/interface/HaikuControlLook.cpp b/src/kits/interface/HaikuControlLook.cpp index 8fd5c257f7..cdbb1e1e30 100644 --- a/src/kits/interface/HaikuControlLook.cpp +++ b/src/kits/interface/HaikuControlLook.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -563,359 +562,96 @@ HaikuControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateR void -HaikuControlLook::DrawScrollBar(BView* view, BRect& rect, +HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation, bool doubleArrows, int32 buttonDown) + orientation orientation) { - if (!rect.IsValid() || !rect.Intersects(updateRect)) - return; - - // save the clipping constraints of the view - view->PushState(); - - // set clipping constraints to updateRect - BRegion clipping(updateRect); - view->ConstrainClippingRegion(&clipping); - - // flags - bool isEnabled = (flags & B_DISABLED) == 0; - bool isFocused = (flags & B_FOCUSED) != 0; - - // colors - rgb_color borderColor = tint_color(base, B_DARKEN_2_TINT); - rgb_color navigation = ui_color(B_KEYBOARD_NAVIGATION_COLOR); - - rgb_color light, dark, dark1, dark2; - if (isEnabled) { - light = tint_color(base, B_LIGHTEN_MAX_TINT); - dark = tint_color(base, B_DARKEN_3_TINT); - dark1 = tint_color(base, B_DARKEN_1_TINT); - dark2 = tint_color(base, B_DARKEN_2_TINT); - } else { - light = tint_color(base, B_LIGHTEN_MAX_TINT); - dark = tint_color(base, B_DARKEN_2_TINT); - dark1 = tint_color(base, B_LIGHTEN_2_TINT); - dark2 = tint_color(base, B_LIGHTEN_1_TINT); - } - - // Stroke a dark frame around the scroll bar background independent of - // enabled state, also handle focus highlighting. - view->SetHighColor(isEnabled && isFocused ? navigation : borderColor); - view->StrokeRect(rect); - - // inset past border - rect.InsetBy(1, 1); - - // clipping region of button rects - BRegion buttonRegion = BRegion(); - BRect buttonFrame1(rect); - BRect buttonFrame2(rect); - BRect buttonFrame3(rect); - BRect buttonFrame4(rect); - - // define arrow rects - if (orientation == B_HORIZONTAL) { - buttonFrame1.Set(rect.left, rect.top, - rect.left + rect.Height(), rect.bottom); - if (doubleArrows) { - buttonFrame2 = buttonFrame1.OffsetByCopy(rect.Height() + 1, 0); - buttonFrame3 = buttonFrame2.OffsetToCopy( - rect.right - (rect.Height() * 2 + 1), rect.top); - } - buttonFrame4 = buttonFrame1.OffsetToCopy(rect.right - rect.Height(), - rect.top); - } else { - buttonFrame1.Set(rect.left, rect.top, rect.right, - rect.top + rect.Width()); - if (doubleArrows) { - buttonFrame2 = buttonFrame1.OffsetByCopy(0, rect.Width() + 1); - buttonFrame3 = buttonFrame2.OffsetToCopy(rect.left, rect.bottom - - ((rect.Width() * 2) + 1)); - } - buttonFrame4 = buttonFrame1.OffsetToCopy(rect.left, - rect.bottom - rect.Width()); - } - - // add to clipping region - buttonRegion.Include(buttonFrame1); - if (doubleArrows) { - buttonRegion.Include(buttonFrame2); - buttonRegion.Include(buttonFrame3); - } - buttonRegion.Include(buttonFrame4); - - // clip to button region - view->ConstrainClippingRegion(&buttonRegion); - - // clear B_ACTIVATED flag if set, we set it on down button ourselves - flags &= ~B_ACTIVATED; - - // draw arrow 1 - buttonRegion.Include(buttonFrame1); - _DrawScrollBarArrowButton(view, buttonFrame1, updateRect, base, - buttonDown == SCROLL_ARROW_1 ? (flags | B_ACTIVATED) : flags, - orientation == B_HORIZONTAL ? B_LEFT_ARROW : B_UP_ARROW, orientation, - doubleArrows, buttonDown == SCROLL_ARROW_1); - if (doubleArrows) { - // draw arrow 2 - _DrawScrollBarArrowButton(view, buttonFrame2, updateRect, base, - buttonDown == SCROLL_ARROW_2 ? (flags | B_ACTIVATED) : flags, - orientation == B_HORIZONTAL ? B_RIGHT_ARROW : B_DOWN_ARROW, - orientation, doubleArrows, buttonDown == SCROLL_ARROW_2); - // draw arrow 3 - _DrawScrollBarArrowButton(view, buttonFrame3, updateRect, base, - buttonDown == SCROLL_ARROW_3 ? (flags | B_ACTIVATED) : flags, - orientation == B_HORIZONTAL ? B_LEFT_ARROW : B_UP_ARROW, - orientation, doubleArrows, buttonDown == SCROLL_ARROW_3); - } - // draw arrow 4 - _DrawScrollBarArrowButton(view, buttonFrame4, updateRect, base, - buttonDown == SCROLL_ARROW_4 ? (flags | B_ACTIVATED) : flags, - orientation == B_HORIZONTAL ? B_RIGHT_ARROW : B_DOWN_ARROW, - orientation, doubleArrows, buttonDown == SCROLL_ARROW_4); - - // set rect to background excluding arrows for thumb to draw on - BRegion background = BRegion(rect); - background.Exclude(&buttonRegion); - rect = background.Frame(); - - // restore the clipping constraints of the view - view->PopState(); + DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); + DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); } void -HaikuControlLook::DrawScrollBarThumb(BView* view, BRect& rect, BRect& thumbRect, +HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation, uint32 knobStyle) + orientation orientation) { if (!rect.IsValid() || !rect.Intersects(updateRect)) return; - // save the clipping constraints of the view - view->PushState(); + float gradient1Tint; + float gradient2Tint; + float darkEdge1Tint; + float darkEdge2Tint; + float shadowTint; - // set clipping constraints to the thumb and background region - BRegion clipping(rect); - view->ConstrainClippingRegion(&clipping); - - // flags - bool isEnabled = (flags & B_DISABLED) == 0; - bool isScrollable = (flags & B_SCROLLABLE) != 0; - - // colors - rgb_color thumbColor = ui_color(B_SCROLL_BAR_THUMB_COLOR); - - rgb_color light, dark, dark1, dark2; - if (isEnabled) { - light = tint_color(base, B_LIGHTEN_MAX_TINT); - dark = tint_color(base, B_DARKEN_3_TINT); - dark1 = tint_color(base, B_DARKEN_1_TINT); - dark2 = tint_color(base, B_DARKEN_2_TINT); + if ((flags & B_DISABLED) != 0) { + gradient1Tint = 0.9; + gradient2Tint = 0.8; + darkEdge1Tint = B_DARKEN_2_TINT; + darkEdge2Tint = B_DARKEN_2_TINT; + shadowTint = gradient1Tint; } else { - light = tint_color(base, B_LIGHTEN_MAX_TINT); - dark = tint_color(base, B_DARKEN_2_TINT); - dark1 = tint_color(base, B_LIGHTEN_2_TINT); - dark2 = tint_color(base, B_LIGHTEN_1_TINT); + gradient1Tint = 1.10; + gradient2Tint = 1.05; + darkEdge1Tint = B_DARKEN_3_TINT; + darkEdge2Tint = B_DARKEN_2_TINT; + shadowTint = gradient1Tint; } - BRect beforeThumb = BRect(); - BRect afterThumb = BRect(); + rgb_color darkEdge1 = tint_color(base, darkEdge1Tint); + rgb_color darkEdge2 = tint_color(base, darkEdge2Tint); + rgb_color shadow = tint_color(base, shadowTint); + if (orientation == B_HORIZONTAL) { - // I'm only interested in the horizontal coordinates of thumbRect - thumbRect.top = rect.top; - thumbRect.bottom = rect.bottom; - beforeThumb.Set(rect.left, rect.top, thumbRect.left - 1, rect.bottom); - afterThumb.Set(thumbRect.right + 1, rect.top, rect.right, rect.bottom); + // dark vertical line on left edge + if (rect.Width() > 0) { + view->SetHighColor(darkEdge1); + view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); + rect.left++; + } + // dark vertical line on right edge + if (rect.Width() >= 0) { + view->SetHighColor(darkEdge2); + view->StrokeLine(rect.RightTop(), rect.RightBottom()); + rect.right--; + } + // vertical shadow line after left edge + if (rect.Width() >= 0) { + view->SetHighColor(shadow); + view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); + rect.left++; + } + // fill + if (rect.Width() >= 0) { + _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, + orientation); + } } else { - // I'm only interested in the vertical coordinates of thumbRect - thumbRect.left = rect.left; - thumbRect.right = rect.right; - beforeThumb.Set(rect.left, rect.top, rect.right, thumbRect.top - 1); - afterThumb.Set(rect.left, thumbRect.bottom + 1, rect.right, - rect.bottom); - } - - if (beforeThumb.IsValid() && afterThumb.IsValid()) { - // clip to background region - BRegion besidesThumb = BRegion(); - besidesThumb.Include(beforeThumb); - besidesThumb.Include(afterThumb); - view->ConstrainClippingRegion(&besidesThumb); - - // draw background besides thumb - _DrawScrollBarBackground(view, beforeThumb, afterThumb, updateRect, - base, flags, orientation); - } else { - // before/after rects are invalid, draw thumb on whole rect - thumbRect = rect; - } - - // clip to thumb - BRegion thumbRegion(thumbRect); - view->ConstrainClippingRegion(&thumbRegion); - - // draw scroll bar thumb - if (isEnabled) { - // fill the clickable surface of the thumb - DrawButtonBackground(view, thumbRect, updateRect, thumbColor, 0, - B_ALL_BORDERS, orientation); - } else { - if (!isScrollable) { - // we cannot scroll at all, use rect here not thumbRect - _DrawDisabledScrollBarBackground(view, rect, orientation, - light, dark, dark1); - } else { - // we could scroll, but we're disabled - - // thumb bevel - view->BeginLineArray(4); - view->AddLine(BPoint(thumbRect.left, thumbRect.bottom), - BPoint(thumbRect.left, thumbRect.top), light); - view->AddLine(BPoint(thumbRect.left + 1, thumbRect.top), - BPoint(thumbRect.right, thumbRect.top), light); - view->AddLine(BPoint(thumbRect.right, thumbRect.top + 1), - BPoint(thumbRect.right, thumbRect.bottom), dark2); - view->AddLine(BPoint(thumbRect.right - 1, thumbRect.bottom), - BPoint(thumbRect.left + 1, thumbRect.bottom), dark2); - view->EndLineArray(); - - // thumb fill - view->SetHighColor(dark1); - view->FillRect(thumbRect.InsetBySelf(1, 1)); - // and inset past bevel + // dark vertical line on top edge + if (rect.Height() > 0) { + view->SetHighColor(darkEdge1); + view->StrokeLine(rect.LeftTop(), rect.RightTop()); + rect.top++; + } + // dark vertical line on bottom edge + if (rect.Height() >= 0) { + view->SetHighColor(darkEdge2); + view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); + rect.bottom--; + } + // horizontal shadow line after top edge + if (rect.Height() >= 0) { + view->SetHighColor(shadow); + view->StrokeLine(rect.LeftTop(), rect.RightTop()); + rect.top++; + } + // fill + if (rect.Height() >= 0) { + _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, + orientation); } } - - // draw knob style - if (knobStyle != KNOB_NONE) { - rgb_color knobLight = isEnabled - ? tint_color(thumbColor, B_LIGHTEN_MAX_TINT) - : tint_color(dark1, B_LIGHTEN_1_TINT); - rgb_color knobDark = isEnabled - ? tint_color(thumbColor, 1.22) - : tint_color(knobLight, B_DARKEN_1_TINT); - - if (knobStyle == KNOB_DOTS) { - // draw dots on the scroll bar thumb - float hcenter = thumbRect.left + thumbRect.Width() / 2; - float vmiddle = thumbRect.top + thumbRect.Height() / 2; - BRect knob(hcenter, vmiddle, hcenter, vmiddle); - - if (orientation == B_HORIZONTAL) { - view->SetHighColor(knobDark); - view->FillRect(knob); - view->SetHighColor(knobLight); - view->FillRect(knob.OffsetByCopy(1, 1)); - - float spacer = thumbRect.Height(); - - if (thumbRect.left + 3 < hcenter - spacer) { - view->SetHighColor(knobDark); - view->FillRect(knob.OffsetByCopy(-spacer, 0)); - view->SetHighColor(knobLight); - view->FillRect(knob.OffsetByCopy(-spacer + 1, 1)); - } - - if (thumbRect.right - 3 > hcenter + spacer) { - view->SetHighColor(knobDark); - view->FillRect(knob.OffsetByCopy(spacer, 0)); - view->SetHighColor(knobLight); - view->FillRect(knob.OffsetByCopy(spacer + 1, 1)); - } - } else { - // B_VERTICAL - view->SetHighColor(knobDark); - view->FillRect(knob); - view->SetHighColor(knobLight); - view->FillRect(knob.OffsetByCopy(1, 1)); - - float spacer = thumbRect.Width(); - - if (thumbRect.top + 3 < vmiddle - spacer) { - view->SetHighColor(knobDark); - view->FillRect(knob.OffsetByCopy(0, -spacer)); - view->SetHighColor(knobLight); - view->FillRect(knob.OffsetByCopy(1, -spacer + 1)); - } - - if (thumbRect.bottom - 3 > vmiddle + spacer) { - view->SetHighColor(knobDark); - view->FillRect(knob.OffsetByCopy(0, spacer)); - view->SetHighColor(knobLight); - view->FillRect(knob.OffsetByCopy(1, spacer + 1)); - } - } - } else if (knobStyle == KNOB_LINES) { - // draw lines on the scroll bar thumb - if (orientation == B_HORIZONTAL) { - float middle = thumbRect.Width() / 2; - - view->BeginLineArray(6); - view->AddLine( - BPoint(thumbRect.left + middle - 3, thumbRect.top + 2), - BPoint(thumbRect.left + middle - 3, thumbRect.bottom - 2), - knobDark); - view->AddLine( - BPoint(thumbRect.left + middle, thumbRect.top + 2), - BPoint(thumbRect.left + middle, thumbRect.bottom - 2), - knobDark); - view->AddLine( - BPoint(thumbRect.left + middle + 3, thumbRect.top + 2), - BPoint(thumbRect.left + middle + 3, thumbRect.bottom - 2), - knobDark); - view->AddLine( - BPoint(thumbRect.left + middle - 2, thumbRect.top + 2), - BPoint(thumbRect.left + middle - 2, thumbRect.bottom - 2), - knobLight); - view->AddLine( - BPoint(thumbRect.left + middle + 1, thumbRect.top + 2), - BPoint(thumbRect.left + middle + 1, thumbRect.bottom - 2), - knobLight); - view->AddLine( - BPoint(thumbRect.left + middle + 4, thumbRect.top + 2), - BPoint(thumbRect.left + middle + 4, thumbRect.bottom - 2), - knobLight); - view->EndLineArray(); - } else { - // B_VERTICAL - float middle = thumbRect.Height() / 2; - - view->BeginLineArray(6); - view->AddLine( - BPoint(thumbRect.left + 2, thumbRect.top + middle - 3), - BPoint(thumbRect.right - 2, thumbRect.top + middle - 3), - knobDark); - view->AddLine( - BPoint(thumbRect.left + 2, thumbRect.top + middle), - BPoint(thumbRect.right - 2, thumbRect.top + middle), - knobDark); - view->AddLine( - BPoint(thumbRect.left + 2, thumbRect.top + middle + 3), - BPoint(thumbRect.right - 2, thumbRect.top + middle + 3), - knobDark); - view->AddLine( - BPoint(thumbRect.left + 2, thumbRect.top + middle - 2), - BPoint(thumbRect.right - 2, thumbRect.top + middle - 2), - knobLight); - view->AddLine( - BPoint(thumbRect.left + 2, thumbRect.top + middle + 1), - BPoint(thumbRect.right - 2, thumbRect.top + middle + 1), - knobLight); - view->AddLine( - BPoint(thumbRect.left + 2, thumbRect.top + middle + 4), - BPoint(thumbRect.right - 2, thumbRect.top + middle + 4), - knobLight); - view->EndLineArray(); - } - } - } - - // set back to original rect clipping - view->ConstrainClippingRegion(&clipping); - - // restore the clipping constraints of the view - view->PopState(); } @@ -1004,9 +740,8 @@ HaikuControlLook::DrawScrollViewFrame(BView* view, BRect& rect, void -HaikuControlLook::DrawArrowShape(BView* view, BRect& rect, - const BRect& updateRect, const rgb_color& base, uint32 direction, - uint32 flags, float tint) +HaikuControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 direction, uint32 flags, float tint) { BPoint tri1, tri2, tri3; float hInset = rect.Width() / 3; @@ -1269,24 +1004,20 @@ HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect view->BeginLineArray(4); if (orientation == B_HORIZONTAL) { - view->AddLine(barRect.LeftTop(), barRect.RightTop(), - edgeShadowColor); + view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor); view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), edgeLightColor); barRect.InsetBy(0, 1); - view->AddLine(barRect.LeftTop(), barRect.RightTop(), - frameShadowColor); + view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor); view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), frameLightColor); barRect.InsetBy(0, 1); } else { - view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), - edgeShadowColor); + view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor); view->AddLine(barRect.RightTop(), barRect.RightBottom(), edgeLightColor); barRect.InsetBy(1, 0); - view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), - frameShadowColor); + view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor); view->AddLine(barRect.RightTop(), barRect.RightBottom(), frameLightColor); barRect.InsetBy(1, 0); @@ -3867,204 +3598,4 @@ HaikuControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base, } -// #pragma mark - protected scroll bar methods - - -void -HaikuControlLook::_DrawScrollBarBackground(BView* view, BRect& rect1, - BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation) -{ - _DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); - _DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); -} - - -void -HaikuControlLook::_DrawScrollBarBackground(BView* view, BRect& rect, - const BRect& updateRect, const rgb_color& base, uint32 flags, - orientation orientation) -{ - if (!rect.IsValid() || !rect.Intersects(updateRect)) - return; - - float gradient1Tint; - float gradient2Tint; - float darkEdge1Tint; - float darkEdge2Tint; - float shadowTint; - - if ((flags & B_DISABLED) != 0) { - gradient1Tint = 0.9; - gradient2Tint = 0.8; - darkEdge1Tint = B_DARKEN_2_TINT; - darkEdge2Tint = B_DARKEN_2_TINT; - shadowTint = gradient1Tint; - } else { - gradient1Tint = 1.10; - gradient2Tint = 1.05; - darkEdge1Tint = B_DARKEN_3_TINT; - darkEdge2Tint = B_DARKEN_2_TINT; - shadowTint = gradient1Tint; - } - - rgb_color darkEdge1 = tint_color(base, darkEdge1Tint); - rgb_color darkEdge2 = tint_color(base, darkEdge2Tint); - rgb_color shadow = tint_color(base, shadowTint); - - if (orientation == B_HORIZONTAL) { - // dark vertical line on left edge - if (rect.Width() > 0) { - view->SetHighColor(darkEdge1); - view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); - rect.left++; - } - // dark vertical line on right edge - if (rect.Width() >= 0) { - view->SetHighColor(darkEdge2); - view->StrokeLine(rect.RightTop(), rect.RightBottom()); - rect.right--; - } - // vertical shadow line after left edge - if (rect.Width() >= 0) { - view->SetHighColor(shadow); - view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); - rect.left++; - } - // fill - if (rect.Width() >= 0) { - _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, - orientation); - } - } else { - // dark vertical line on top edge - if (rect.Height() > 0) { - view->SetHighColor(darkEdge1); - view->StrokeLine(rect.LeftTop(), rect.RightTop()); - rect.top++; - } - // dark vertical line on bottom edge - if (rect.Height() >= 0) { - view->SetHighColor(darkEdge2); - view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); - rect.bottom--; - } - // horizontal shadow line after top edge - if (rect.Height() >= 0) { - view->SetHighColor(shadow); - view->StrokeLine(rect.LeftTop(), rect.RightTop()); - rect.top++; - } - // fill - if (rect.Height() >= 0) { - _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, - orientation); - } - } -} - - -void -HaikuControlLook::_DrawDisabledScrollBarBackground(BView* view, BRect rect, - orientation orientation, const rgb_color& light, const rgb_color& dark, - const rgb_color& fill) -{ - if (!rect.IsValid()) - return; - - if (orientation == B_VERTICAL) { - int32 height = rect.IntegerHeight(); - if (height == 0) { - view->SetHighColor(dark); - view->StrokeLine(rect.LeftTop(), rect.RightTop()); - } else if (height == 1) { - view->SetHighColor(dark); - view->FillRect(rect); - } else { - view->BeginLineArray(4); - - view->AddLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.top), dark); - view->AddLine(BPoint(rect.left, rect.bottom - 1), - BPoint(rect.left, rect.top + 1), light); - view->AddLine(BPoint(rect.left + 1, rect.top + 1), - BPoint(rect.right, rect.top + 1), light); - view->AddLine(BPoint(rect.right, rect.bottom), - BPoint(rect.left, rect.bottom), dark); - - view->EndLineArray(); - - rect.left++; - rect.top += 2; - rect.bottom--; - - if (rect.IsValid()) { - view->SetHighColor(fill); - view->FillRect(rect); - } - } - } else { - int32 width = rect.IntegerWidth(); - if (width == 0) { - view->SetHighColor(dark); - view->StrokeLine(rect.LeftBottom(), rect.LeftTop()); - } else if (width == 1) { - view->SetHighColor(dark); - view->FillRect(rect); - } else { - view->BeginLineArray(4); - - view->AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), dark); - view->AddLine(BPoint(rect.left + 1, rect.bottom), - BPoint(rect.left + 1, rect.top + 1), light); - view->AddLine(BPoint(rect.left + 1, rect.top), - BPoint(rect.right - 1, rect.top), light); - view->AddLine(BPoint(rect.right, rect.top), - BPoint(rect.right, rect.bottom), dark); - - view->EndLineArray(); - - rect.left += 2; - rect.top ++; - rect.right--; - - if (rect.IsValid()) { - view->SetHighColor(fill); - view->FillRect(rect); - } - } - } -} - - -void -HaikuControlLook::_DrawScrollBarArrowButton(BView* view, BRect rect, - const BRect& updateRect, const rgb_color& base, uint32 flags, - int32 direction, orientation orientation, bool doubleArrows, bool down) -{ - if (!updateRect.Intersects(rect)) - return; - - // clip to button - BRegion buttonRegion(rect); - view->ConstrainClippingRegion(&buttonRegion); - - // TODO: why do we need this for the scroll bar to draw right? - rgb_color arrowColor = tint_color(base, B_LIGHTEN_1_TINT); - // TODO: Why do we need this negative inset for the arrow to look right? - BRect arrowRect(rect.InsetByCopy(-1, -1)); - - // draw button and arrow - DrawButtonBackground(view, rect, updateRect, arrowColor, flags, - BControlLook::B_ALL_BORDERS, orientation); - DrawArrowShape(view, arrowRect, arrowRect, base, direction, - flags, B_DARKEN_4_TINT); - - // revert clipping constratings back to updateRect for next guy - BRegion clipping(updateRect); - view->ConstrainClippingRegion(&clipping); -} - - } // namespace BPrivate diff --git a/src/kits/interface/ScrollBar.cpp b/src/kits/interface/ScrollBar.cpp index 05bcbcfe0c..8049b990c2 100644 --- a/src/kits/interface/ScrollBar.cpp +++ b/src/kits/interface/ScrollBar.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2015 Haiku, Inc. All rights reserved. + * Copyright 2001-2014 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT license. * * Authors: @@ -27,8 +27,6 @@ #include -#include - //#define TRACE_SCROLLBAR #ifdef TRACE_SCROLLBAR @@ -38,11 +36,31 @@ #endif +typedef enum { + ARROW_LEFT = 0, + ARROW_RIGHT, + ARROW_UP, + ARROW_DOWN, + ARROW_NONE +} arrow_direction; + + #define SBC_SCROLLBYVALUE 0 #define SBC_SETDOUBLE 1 #define SBC_SETPROPORTIONAL 2 #define SBC_SETSTYLE 3 +// Quick constants for determining which arrow is down and are defined with +// respect to double arrow mode. ARROW1 and ARROW4 refer to the outer pair of +// arrows and ARROW2 and ARROW3 refer to the inner ones. ARROW1 points left/up +// and ARROW4 points right/down. +#define ARROW1 0 +#define ARROW2 1 +#define ARROW3 2 +#define ARROW4 3 +#define THUMB 4 +#define NOARROW -1 + static const bigtime_t kRepeatDelay = 300000; @@ -66,7 +84,7 @@ public: fUpArrowsEnabled(true), fDownArrowsEnabled(true), fBorderHighlighted(false), - fButtonDown(SCROLL_NO_ARROW) + fButtonDown(NOARROW) { #ifdef TEST_MODE fScrollBarInfo.proportional = true; @@ -87,14 +105,6 @@ public: } } - typedef enum { - ARROW_LEFT = 0, - ARROW_RIGHT, - ARROW_UP, - ARROW_DOWN, - ARROW_NONE - } arrow_direction; - void DrawScrollBarButton(BScrollBar* owner, arrow_direction direction, BRect frame, bool down = false); @@ -156,7 +166,7 @@ BScrollBar::Private::ButtonRepeaterThread() if (fScrollBar->LockLooper()) { if (fDoRepeat) { float value = fScrollBar->Value() + fThumbInc; - if (fButtonDown == SCROLL_NO_ARROW) { + if (fButtonDown == NOARROW) { // in this case we want to stop when we're under the mouse if (fThumbInc > 0.0 && value <= fStopValue) fScrollBar->SetValue(value); @@ -368,28 +378,205 @@ BScrollBar::DetachedFromWindow() void BScrollBar::Draw(BRect updateRect) { - uint32 flags = 0; - bool scrollingEnabled = _ScrollingEnabled(); - if (scrollingEnabled) - flags |= BControlLook::B_SCROLLABLE; + BRect bounds = Bounds(); - bool isEnabled = fPrivateData->fEnabled && scrollingEnabled; - if (!isEnabled) + rgb_color normal = ui_color(B_PANEL_BACKGROUND_COLOR); + + // stroke a dark frame around the entire scrollbar + // (independent of enabled state) + // take care of border highlighting (scroll target is focus view) + SetHighColor(tint_color(normal, B_DARKEN_2_TINT)); + if (fPrivateData->fBorderHighlighted && fPrivateData->fEnabled) { + rgb_color borderColor = HighColor(); + rgb_color highlightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + BeginLineArray(4); + AddLine(BPoint(bounds.left + 1, bounds.bottom), + BPoint(bounds.right, bounds.bottom), borderColor); + AddLine(BPoint(bounds.right, bounds.top + 1), + BPoint(bounds.right, bounds.bottom - 1), borderColor); + if (fOrientation == B_HORIZONTAL) { + AddLine(BPoint(bounds.left, bounds.top + 1), + BPoint(bounds.left, bounds.bottom), borderColor); + } else { + AddLine(BPoint(bounds.left, bounds.top), + BPoint(bounds.left, bounds.bottom), highlightColor); + } + if (fOrientation == B_HORIZONTAL) { + AddLine(BPoint(bounds.left, bounds.top), + BPoint(bounds.right, bounds.top), highlightColor); + } else { + AddLine(BPoint(bounds.left + 1, bounds.top), + BPoint(bounds.right, bounds.top), borderColor); + } + EndLineArray(); + } else + StrokeRect(bounds); + + bounds.InsetBy(1.0f, 1.0f); + + bool enabled = fPrivateData->fEnabled && fMin < fMax + && fProportion < 1.0f && fProportion >= 0.0f; + + rgb_color light, dark, dark1, dark2; + if (enabled) { + light = tint_color(normal, B_LIGHTEN_MAX_TINT); + dark = tint_color(normal, B_DARKEN_3_TINT); + dark1 = tint_color(normal, B_DARKEN_1_TINT); + dark2 = tint_color(normal, B_DARKEN_2_TINT); + } else { + light = tint_color(normal, B_LIGHTEN_MAX_TINT); + dark = tint_color(normal, B_DARKEN_2_TINT); + dark1 = tint_color(normal, B_LIGHTEN_2_TINT); + dark2 = tint_color(normal, B_LIGHTEN_1_TINT); + } + + SetDrawingMode(B_OP_OVER); + + BRect thumbBG = bounds; + bool doubleArrows = _DoubleArrows(); + + // Draw arrows + if (fOrientation == B_HORIZONTAL) { + BRect buttonFrame(bounds.left, bounds.top, + bounds.left + bounds.Height(), bounds.bottom); + + _DrawArrowButton(ARROW_LEFT, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW1); + + if (doubleArrows) { + buttonFrame.OffsetBy(bounds.Height() + 1, 0.0f); + _DrawArrowButton(ARROW_RIGHT, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW2); + + buttonFrame.OffsetTo(bounds.right - ((bounds.Height() * 2) + 1), + bounds.top); + _DrawArrowButton(ARROW_LEFT, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW3); + + thumbBG.left += bounds.Height() * 2 + 2; + thumbBG.right -= bounds.Height() * 2 + 2; + } else { + thumbBG.left += bounds.Height() + 1; + thumbBG.right -= bounds.Height() + 1; + } + + buttonFrame.OffsetTo(bounds.right - bounds.Height(), bounds.top); + _DrawArrowButton(ARROW_RIGHT, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW4); + } else { + BRect buttonFrame(bounds.left, bounds.top, bounds.right, + bounds.top + bounds.Width()); + + _DrawArrowButton(ARROW_UP, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW1); + + if (doubleArrows) { + buttonFrame.OffsetBy(0.0f, bounds.Width() + 1); + _DrawArrowButton(ARROW_DOWN, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW2); + + buttonFrame.OffsetTo(bounds.left, bounds.bottom + - ((bounds.Width() * 2) + 1)); + _DrawArrowButton(ARROW_UP, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW3); + + thumbBG.top += bounds.Width() * 2 + 2; + thumbBG.bottom -= bounds.Width() * 2 + 2; + } else { + thumbBG.top += bounds.Width() + 1; + thumbBG.bottom -= bounds.Width() + 1; + } + + buttonFrame.OffsetTo(bounds.left, bounds.bottom - bounds.Width()); + _DrawArrowButton(ARROW_DOWN, doubleArrows, buttonFrame, updateRect, + enabled, fPrivateData->fButtonDown == ARROW4); + } + + SetDrawingMode(B_OP_COPY); + + // background for thumb area + BRect rect(fPrivateData->fThumbFrame); + + SetHighColor(dark1); + + uint32 flags = 0; + if (!enabled) flags |= BControlLook::B_DISABLED; - bool isFocused = fPrivateData->fBorderHighlighted; - if (isFocused) - flags |= BControlLook::B_FOCUSED; + // fill background besides the thumb + if (fOrientation == B_HORIZONTAL) { + BRect leftOfThumb(thumbBG.left, thumbBG.top, rect.left - 1, + thumbBG.bottom); + BRect rightOfThumb(rect.right + 1, thumbBG.top, thumbBG.right, + thumbBG.bottom); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + be_control_look->DrawScrollBarBackground(this, leftOfThumb, + rightOfThumb, updateRect, normal, flags, fOrientation); + } else { + BRect topOfThumb(thumbBG.left, thumbBG.top, + thumbBG.right, rect.top - 1); - BRect rect(Bounds()); - BRect thumbRect(fPrivateData->fThumbFrame); + BRect bottomOfThumb(thumbBG.left, rect.bottom + 1, + thumbBG.right, thumbBG.bottom); - be_control_look->DrawScrollBar(this, rect, updateRect, base, - flags, fOrientation, _DoubleArrows(), fPrivateData->fButtonDown); - be_control_look->DrawScrollBarThumb(this, rect, thumbRect, updateRect, base, - flags, fOrientation, fPrivateData->fScrollBarInfo.knob); + be_control_look->DrawScrollBarBackground(this, topOfThumb, + bottomOfThumb, updateRect, normal, flags, fOrientation); + } + + rgb_color thumbColor = ui_color(B_SCROLL_BAR_THUMB_COLOR); + + // Draw scroll thumb + if (enabled) { + // fill the clickable surface of the thumb + be_control_look->DrawButtonBackground(this, rect, updateRect, + thumbColor, 0, BControlLook::B_ALL_BORDERS, fOrientation); + // TODO: Add the other thumb styles - dots and lines + } else { + if (fMin >= fMax || fProportion >= 1.0f || fProportion < 0.0f) { + // we cannot scroll at all + _DrawDisabledBackground(thumbBG, light, dark, dark1); + } else { + // we could scroll, but we're simply disabled + float bgTint = 1.06; + rgb_color bgLight = tint_color(light, bgTint * 3); + rgb_color bgShadow = tint_color(dark, bgTint); + rgb_color bgFill = tint_color(dark1, bgTint); + if (fOrientation == B_HORIZONTAL) { + // left of thumb + BRect besidesThumb(thumbBG); + besidesThumb.right = rect.left - 1; + _DrawDisabledBackground(besidesThumb, bgLight, bgShadow, bgFill); + // right of thumb + besidesThumb.left = rect.right + 1; + besidesThumb.right = thumbBG.right; + _DrawDisabledBackground(besidesThumb, bgLight, bgShadow, bgFill); + } else { + // above thumb + BRect besidesThumb(thumbBG); + besidesThumb.bottom = rect.top - 1; + _DrawDisabledBackground(besidesThumb, bgLight, bgShadow, bgFill); + // below thumb + besidesThumb.top = rect.bottom + 1; + besidesThumb.bottom = thumbBG.bottom; + _DrawDisabledBackground(besidesThumb, bgLight, bgShadow, bgFill); + } + // thumb bevel + BeginLineArray(4); + AddLine(BPoint(rect.left, rect.bottom), + BPoint(rect.left, rect.top), light); + AddLine(BPoint(rect.left + 1, rect.top), + BPoint(rect.right, rect.top), light); + AddLine(BPoint(rect.right, rect.top + 1), + BPoint(rect.right, rect.bottom), dark2); + AddLine(BPoint(rect.right - 1, rect.bottom), + BPoint(rect.left + 1, rect.bottom), dark2); + EndLineArray(); + // thumb fill + rect.InsetBy(1.0, 1.0); + SetHighColor(dark1); + FillRect(rect); + } + } } @@ -460,16 +647,12 @@ BScrollBar::MouseDown(BPoint where) if (buttons & B_SECONDARY_MOUSE_BUTTON) { // special absolute scrolling: move thumb to where we clicked - fPrivateData->fButtonDown = SCROLL_THUMB; - fPrivateData->fClickOffset - = fPrivateData->fThumbFrame.LeftTop() - where; - if (Orientation() == B_HORIZONTAL) { - fPrivateData->fClickOffset.x - = -fPrivateData->fThumbFrame.Width() / 2; - } else { - fPrivateData->fClickOffset.y - = -fPrivateData->fThumbFrame.Height() / 2; - } + fPrivateData->fButtonDown = THUMB; + fPrivateData->fClickOffset = fPrivateData->fThumbFrame.LeftTop() - where; + if (Orientation() == B_HORIZONTAL) + fPrivateData->fClickOffset.x = -fPrivateData->fThumbFrame.Width() / 2; + else + fPrivateData->fClickOffset.y = -fPrivateData->fThumbFrame.Height() / 2; SetValue(_ValueFor(where + fPrivateData->fClickOffset)); return; @@ -477,9 +660,8 @@ BScrollBar::MouseDown(BPoint where) // hit test for the thumb if (fPrivateData->fThumbFrame.Contains(where)) { - fPrivateData->fButtonDown = SCROLL_THUMB; - fPrivateData->fClickOffset - = fPrivateData->fThumbFrame.LeftTop() - where; + fPrivateData->fButtonDown = THUMB; + fPrivateData->fClickOffset = fPrivateData->fThumbFrame.LeftTop() - where; Invalidate(fPrivateData->fThumbFrame); return; } @@ -493,23 +675,23 @@ BScrollBar::MouseDown(BPoint where) fPrivateData->fButtonDown = _ButtonFor(where); switch (fPrivateData->fButtonDown) { - case SCROLL_ARROW_1: + case ARROW1: scrollValue = -buttonStepSize; break; - case SCROLL_ARROW_2: + case ARROW2: scrollValue = buttonStepSize; break; - case SCROLL_ARROW_3: + case ARROW3: scrollValue = -buttonStepSize; break; - case SCROLL_ARROW_4: + case ARROW4: scrollValue = buttonStepSize; break; - case SCROLL_NO_ARROW: + case NOARROW: // we hit the empty area, figure out which side of the thumb if (fOrientation == B_VERTICAL) { if (where.y < fPrivateData->fThumbFrame.top) @@ -551,11 +733,13 @@ BScrollBar::MouseDown(BPoint where) void BScrollBar::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) { - if (!fPrivateData->fEnabled || !_ScrollingEnabled()) + if (!fPrivateData->fEnabled || fMin >= fMax || fProportion >= 1.0f + || fProportion < 0.0f) { return; + } - if (fPrivateData->fButtonDown != SCROLL_NO_ARROW) { - if (fPrivateData->fButtonDown == SCROLL_THUMB) { + if (fPrivateData->fButtonDown != NOARROW) { + if (fPrivateData->fButtonDown == THUMB) { SetValue(_ValueFor(where + fPrivateData->fClickOffset)); } else { // suspend the repeating if the mouse is not over the button @@ -585,12 +769,12 @@ BScrollBar::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) void BScrollBar::MouseUp(BPoint where) { - if (fPrivateData->fButtonDown == SCROLL_THUMB) + if (fPrivateData->fButtonDown == THUMB) Invalidate(fPrivateData->fThumbFrame); else Invalidate(_ButtonRectFor(fPrivateData->fButtonDown)); - fPrivateData->fButtonDown = SCROLL_NO_ARROW; + fPrivateData->fButtonDown = NOARROW; fPrivateData->fExitRepeater = true; fPrivateData->fDoRepeat = false; } @@ -674,11 +858,13 @@ BScrollBar::SetProportion(float value) TRACE("BScrollBar(%s)::SetProportion(%.1f)\n", Name(), value); - bool oldEnabled = fPrivateData->fEnabled && _ScrollingEnabled(); + bool oldEnabled = fPrivateData->fEnabled && fMin < fMax + && fProportion < 1.0f && fProportion >= 0.0f; fProportion = value; - bool newEnabled = fPrivateData->fEnabled && _ScrollingEnabled(); + bool newEnabled = fPrivateData->fEnabled && fMin < fMax + && fProportion < 1.0f && fProportion >= 0.0f; _UpdateThumbFrame(); @@ -1030,13 +1216,6 @@ BScrollBar::operator=(const BScrollBar&) } -bool -BScrollBar::_ScrollingEnabled() const -{ - return fMin < fMax && fProportion >= 0.0f && fProportion < 1.0f; -} - - bool BScrollBar::_DoubleArrows() const { @@ -1208,39 +1387,39 @@ BScrollBar::_ButtonFor(BPoint where) const if (fOrientation == B_VERTICAL) { if (rect.Contains(where)) - return SCROLL_ARROW_1; + return ARROW1; if (_DoubleArrows()) { rect.OffsetBy(0.0, buttonSize); if (rect.Contains(where)) - return SCROLL_ARROW_2; + return ARROW2; rect.OffsetTo(bounds.left, bounds.bottom - 2 * buttonSize); if (rect.Contains(where)) - return SCROLL_ARROW_3; + return ARROW3; } rect.OffsetTo(bounds.left, bounds.bottom - buttonSize); if (rect.Contains(where)) - return SCROLL_ARROW_4; + return ARROW4; } else { if (rect.Contains(where)) - return SCROLL_ARROW_1; + return ARROW1; if (_DoubleArrows()) { rect.OffsetBy(buttonSize, 0.0); if (rect.Contains(where)) - return SCROLL_ARROW_2; + return ARROW2; rect.OffsetTo(bounds.right - 2 * buttonSize, bounds.top); if (rect.Contains(where)) - return SCROLL_ARROW_3; + return ARROW3; } rect.OffsetTo(bounds.right - buttonSize, bounds.top); if (rect.Contains(where)) - return SCROLL_ARROW_4; + return ARROW4; } - return SCROLL_NO_ARROW; + return NOARROW; } @@ -1259,35 +1438,35 @@ BScrollBar::_ButtonRectFor(int32 button) const if (fOrientation == B_VERTICAL) { switch (button) { - case SCROLL_ARROW_1: + case ARROW1: break; - case SCROLL_ARROW_2: + case ARROW2: rect.OffsetBy(0.0, buttonSize); break; - case SCROLL_ARROW_3: + case ARROW3: rect.OffsetTo(bounds.left, bounds.bottom - 2 * buttonSize + 1); break; - case SCROLL_ARROW_4: + case ARROW4: rect.OffsetTo(bounds.left, bounds.bottom - buttonSize + 1); break; } } else { switch (button) { - case SCROLL_ARROW_1: + case ARROW1: break; - case SCROLL_ARROW_2: + case ARROW2: rect.OffsetBy(buttonSize, 0.0); break; - case SCROLL_ARROW_3: + case ARROW3: rect.OffsetTo(bounds.right - 2 * buttonSize + 1, bounds.top); break; - case SCROLL_ARROW_4: + case ARROW4: rect.OffsetTo(bounds.right - buttonSize + 1, bounds.top); break; } @@ -1316,17 +1495,17 @@ BScrollBar::_UpdateArrowButtons() bool upEnabled = fValue > fMin; if (fPrivateData->fUpArrowsEnabled != upEnabled) { fPrivateData->fUpArrowsEnabled = upEnabled; - Invalidate(_ButtonRectFor(SCROLL_ARROW_1)); + Invalidate(_ButtonRectFor(ARROW1)); if (_DoubleArrows()) - Invalidate(_ButtonRectFor(SCROLL_ARROW_3)); + Invalidate(_ButtonRectFor(ARROW3)); } bool downEnabled = fValue < fMax; if (fPrivateData->fDownArrowsEnabled != downEnabled) { fPrivateData->fDownArrowsEnabled = downEnabled; - Invalidate(_ButtonRectFor(SCROLL_ARROW_4)); + Invalidate(_ButtonRectFor(ARROW4)); if (_DoubleArrows()) - Invalidate(_ButtonRectFor(SCROLL_ARROW_2)); + Invalidate(_ButtonRectFor(ARROW2)); } } @@ -1373,6 +1552,101 @@ control_scrollbar(scroll_bar_info* info, BScrollBar* bar) } +void +BScrollBar::_DrawDisabledBackground(BRect area, const rgb_color& light, + const rgb_color& dark, const rgb_color& fill) +{ + if (!area.IsValid()) + return; + + if (fOrientation == B_VERTICAL) { + int32 height = area.IntegerHeight(); + if (height == 0) { + SetHighColor(dark); + StrokeLine(area.LeftTop(), area.RightTop()); + } else if (height == 1) { + SetHighColor(dark); + FillRect(area); + } else { + BeginLineArray(4); + AddLine(BPoint(area.left, area.top), + BPoint(area.right, area.top), dark); + AddLine(BPoint(area.left, area.bottom - 1), + BPoint(area.left, area.top + 1), light); + AddLine(BPoint(area.left + 1, area.top + 1), + BPoint(area.right, area.top + 1), light); + AddLine(BPoint(area.right, area.bottom), + BPoint(area.left, area.bottom), dark); + EndLineArray(); + area.left++; + area.top += 2; + area.bottom--; + if (area.IsValid()) { + SetHighColor(fill); + FillRect(area); + } + } + } else { + int32 width = area.IntegerWidth(); + if (width == 0) { + SetHighColor(dark); + StrokeLine(area.LeftBottom(), area.LeftTop()); + } else if (width == 1) { + SetHighColor(dark); + FillRect(area); + } else { + BeginLineArray(4); + AddLine(BPoint(area.left, area.bottom), + BPoint(area.left, area.top), dark); + AddLine(BPoint(area.left + 1, area.bottom), + BPoint(area.left + 1, area.top + 1), light); + AddLine(BPoint(area.left + 1, area.top), + BPoint(area.right - 1, area.top), light); + AddLine(BPoint(area.right, area.top), + BPoint(area.right, area.bottom), dark); + EndLineArray(); + area.left += 2; + area.top ++; + area.right--; + if (area.IsValid()) { + SetHighColor(fill); + FillRect(area); + } + } + } +} + + +void +BScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect rect, + const BRect& updateRect, bool enabled, bool down) +{ + if (!updateRect.Intersects(rect)) + return; + + uint32 flags = 0; + if (!enabled) + flags |= BControlLook::B_DISABLED; + + if (down && fPrivateData->fDoRepeat) + flags |= BControlLook::B_ACTIVATED; + + // TODO: Why does BControlLook need this as the base color for the + // scrollbar to look right? + rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_1_TINT); + + be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor, + flags, BControlLook::B_ALL_BORDERS, fOrientation); + + // TODO: Why does BControlLook need this negative inset for the arrow to + // look right? + rect.InsetBy(-1.0f, -1.0f); + be_control_look->DrawArrowShape(this, rect, updateRect, + baseColor, direction, flags, B_DARKEN_MAX_TINT); +} + + BSize BScrollBar::_MinSize() const { diff --git a/src/preferences/appearance/FakeScrollBar.cpp b/src/preferences/appearance/FakeScrollBar.cpp index f5230abb6b..e8a792928e 100644 --- a/src/preferences/appearance/FakeScrollBar.cpp +++ b/src/preferences/appearance/FakeScrollBar.cpp @@ -35,10 +35,8 @@ FakeScrollBar::FakeScrollBar(bool drawArrows, bool doubleArrows, fDrawArrows(drawArrows), fDoubleArrows(doubleArrows) { - // add some height to draw the ring around the scroll bar - float height = B_H_SCROLL_BAR_HEIGHT + 8; - SetExplicitMinSize(BSize(200, height)); - SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, height)); + SetExplicitMinSize(BSize(160, 20)); + SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 20)); } @@ -50,42 +48,99 @@ FakeScrollBar::~FakeScrollBar(void) void FakeScrollBar::Draw(BRect updateRect) { - BRect rect(Bounds()); + BRect bounds = Bounds(); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color normal = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 flags = BControlLook::B_SCROLLABLE; - if (IsFocus()) - flags |= BControlLook::B_FOCUSED; + if (IsFocus()) { + // draw the focus indicator + SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR)); + StrokeRect(bounds); + bounds.InsetBy(1.0, 1.0); - if (Value() == B_CONTROL_ON) - SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); - else - SetHighColor(base); + // Draw the selected border (1px) + if (Value() == B_CONTROL_ON) + SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); + else + SetHighColor(normal); - // Draw the selected border (2px) - StrokeRect(rect); - rect.InsetBy(1, 1); - StrokeRect(rect); - rect.InsetBy(1, 1); + StrokeRect(bounds); + bounds.InsetBy(1.0, 1.0); + } else { + // Draw the selected border (2px) + if (Value() == B_CONTROL_ON) + SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); + else + SetHighColor(normal); - // draw a 1px gap - SetHighColor(base); - StrokeRect(rect); - rect.InsetBy(1, 1); + StrokeRect(bounds); + bounds.InsetBy(1.0, 1.0); + StrokeRect(bounds); + bounds.InsetBy(1.0, 1.0); + } - // draw a 1px border around control - SetHighColor(tint_color(base, B_DARKEN_1_TINT)); - StrokeRect(rect); - rect.InsetBy(1, 1); - SetHighColor(base); + // draw a gap (1px) + SetHighColor(normal); + StrokeRect(bounds); + bounds.InsetBy(1.0, 1.0); - be_control_look->DrawScrollBar(this, rect, updateRect, base, - flags, B_HORIZONTAL, fDoubleArrows); - float less = floorf(rect.Width() / 3); // thumb takes up 1/3 full width - BRect thumbRect(rect.left + less, rect.top, rect.right - less, rect.bottom); - be_control_look->DrawScrollBarThumb(this, rect, thumbRect, updateRect, base, - flags, B_HORIZONTAL, fKnobStyle); + // draw a border around control (1px) + SetHighColor(tint_color(normal, B_DARKEN_1_TINT)); + StrokeRect(bounds); + bounds.InsetBy(1.0, 1.0); + + BRect thumbBG = bounds; + BRect bgRect = bounds; + + if (fDrawArrows) { + // draw arrows + SetDrawingMode(B_OP_OVER); + + BRect buttonFrame(bounds.left, bounds.top, + bounds.left + bounds.Height(), bounds.bottom); + + _DrawArrowButton(ARROW_LEFT, buttonFrame, updateRect); + + if (fDoubleArrows) { + buttonFrame.OffsetBy(bounds.Height() + 1, 0.0); + _DrawArrowButton(ARROW_RIGHT, buttonFrame, + updateRect); + + buttonFrame.OffsetTo(bounds.right - ((bounds.Height() * 2) + 1), + bounds.top); + _DrawArrowButton(ARROW_LEFT, buttonFrame, + updateRect); + + thumbBG.left += bounds.Height() * 2 + 2; + thumbBG.right -= bounds.Height() * 2 + 2; + } else { + thumbBG.left += bounds.Height() + 1; + thumbBG.right -= bounds.Height() + 1; + } + + buttonFrame.OffsetTo(bounds.right - bounds.Height(), bounds.top); + _DrawArrowButton(ARROW_RIGHT, buttonFrame, updateRect); + + SetDrawingMode(B_OP_COPY); + + bgRect = bounds.InsetByCopy(48, 0); + } else + bgRect = bounds.InsetByCopy(16, 0); + + // fill background besides the thumb + BRect leftOfThumb(thumbBG.left, thumbBG.top, bgRect.left - 1, + thumbBG.bottom); + BRect rightOfThumb(bgRect.right + 1, thumbBG.top, thumbBG.right, + thumbBG.bottom); + + be_control_look->DrawScrollBarBackground(this, leftOfThumb, + rightOfThumb, updateRect, normal, 0, B_HORIZONTAL); + + // Draw scroll thumb + + // fill the clickable surface of the thumb + be_control_look->DrawButtonBackground(this, bgRect, updateRect, + normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL); }