From fe66a314c8ba69e71beb22591d4e51ea2d04508a Mon Sep 17 00:00:00 2001 From: waddlesplash Date: Sun, 22 Jul 2018 18:24:47 +0000 Subject: [PATCH] Revert "BScrollBar: Add lines and dots knob styles to scroll bar" This reverts commit ec1b18c58ae632444200f7e1f952ddd2e31048fa. This was not well enough reviewed, and it seems that at least some consumers of the old API (e.g. WebPositive) need more than the new one provides. Change-Id: Ie7ad1fc70dab889922424298661504b00f66d31d --- headers/os/interface/ControlLook.h | 15 +- headers/os/interface/ScrollBar.h | 9 +- headers/private/interface/HaikuControlLook.h | 34 +- headers/private/interface/ScrollBarPrivate.h | 32 - src/kits/interface/HaikuControlLook.cpp | 623 +++---------------- src/kits/interface/ScrollBar.cpp | 438 ++++++++++--- src/preferences/appearance/FakeScrollBar.cpp | 121 +++- 7 files changed, 541 insertions(+), 731 deletions(-) delete mode 100644 headers/private/interface/ScrollBarPrivate.h 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); }