Revert "BScrollBar: Add lines and dots knob styles to scroll bar"

This reverts commit ec1b18c58a.

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
This commit is contained in:
waddlesplash
2018-07-22 18:26:06 +00:00
parent 49c29fa933
commit fe66a314c8
7 changed files with 541 additions and 731 deletions
+6 -9
View File
@@ -86,7 +86,6 @@ public:
B_FLAT = 1 << 8, // flat look (e.g. button background) B_FLAT = 1 << 8, // flat look (e.g. button background)
B_INVALID = 1 << 9, // invalid value, use B_FAILURE_COLOR B_INVALID = 1 << 9, // invalid value, use B_FAILURE_COLOR
B_IS_CONTROL = 1 << 10, // use control colors B_IS_CONTROL = 1 << 10, // use control colors
B_SCROLLABLE = 1 << 11, // scroll bar within bounds
B_BLEND_FRAME = 1 << 16, B_BLEND_FRAME = 1 << 16,
}; };
@@ -225,17 +224,15 @@ public:
const rgb_color& base, const rgb_color& base,
uint32 flags = 0) = 0; uint32 flags = 0) = 0;
virtual void DrawScrollBar(BView* view, BRect& rect, virtual void DrawScrollBarBackground(BView* view,
BRect& rect1, BRect& rect2,
const BRect& updateRect, const BRect& updateRect,
const rgb_color& base, uint32 flags, const rgb_color& base, uint32 flags,
orientation orientation, orientation orientation) = 0;
bool doubleArrows = false, virtual void DrawScrollBarBackground(BView* view,
int32 buttonDown = -1) = 0; BRect& rect, const BRect& updateRect,
virtual void DrawScrollBarThumb(BView* view, BRect& rect,
BRect& thumbRect, const BRect& updateRect,
const rgb_color& base, uint32 flags, const rgb_color& base, uint32 flags,
orientation orientation, orientation orientation) = 0;
uint32 knobStyle = 0) = 0;
virtual void DrawScrollViewFrame(BView* view, virtual void DrawScrollViewFrame(BView* view,
BRect& rect, const BRect& updateRect, BRect& rect, const BRect& updateRect,
+8 -1
View File
@@ -114,7 +114,6 @@ private:
// disabled // disabled
BScrollBar& operator=(const BScrollBar& other); BScrollBar& operator=(const BScrollBar& other);
bool _ScrollingEnabled() const;
bool _DoubleArrows() const; bool _DoubleArrows() const;
void _UpdateThumbFrame(); void _UpdateThumbFrame();
float _ValueFor(BPoint where) const; float _ValueFor(BPoint where) const;
@@ -122,6 +121,14 @@ private:
BRect _ButtonRectFor(int32 button) const; BRect _ButtonRectFor(int32 button) const;
void _UpdateTargetValue(BPoint where); void _UpdateTargetValue(BPoint where);
void _UpdateArrowButtons(); 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; BSize _MinSize() const;
+6 -28
View File
@@ -157,17 +157,15 @@ public:
const rgb_color& base, const rgb_color& base,
uint32 flags = 0); uint32 flags = 0);
virtual void DrawScrollBar(BView* view, BRect& rect, virtual void DrawScrollBarBackground(BView* view,
BRect& rect1, BRect& rect2,
const BRect& updateRect, const BRect& updateRect,
const rgb_color& base, uint32 flags, const rgb_color& base, uint32 flags,
orientation orientation, orientation orientation);
bool doubleArrows = false, virtual void DrawScrollBarBackground(BView* view,
int32 buttonDown = -1); BRect& rect, const BRect& updateRect,
virtual void DrawScrollBarThumb(BView* view, BRect& rect,
BRect& thumbRect, const BRect& updateRect,
const rgb_color& base, uint32 flags, const rgb_color& base, uint32 flags,
orientation orientation, orientation orientation);
uint32 knobStyle = 0);
virtual void DrawScrollViewFrame(BView* view, virtual void DrawScrollViewFrame(BView* view,
BRect& rect, const BRect& updateRect, BRect& rect, const BRect& updateRect,
@@ -561,26 +559,6 @@ protected:
const rgb_color& base, rgb_color& color, const rgb_color& base, rgb_color& color,
uint32 flags) const; 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: private:
bool fCachedOutline; bool fCachedOutline;
}; };
@@ -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
+77 -546
View File
@@ -18,7 +18,6 @@
#include <GradientLinear.h> #include <GradientLinear.h>
#include <LayoutUtils.h> #include <LayoutUtils.h>
#include <Region.h> #include <Region.h>
#include <ScrollBarPrivate.h>
#include <Shape.h> #include <Shape.h>
#include <String.h> #include <String.h>
#include <View.h> #include <View.h>
@@ -563,359 +562,96 @@ HaikuControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateR
void void
HaikuControlLook::DrawScrollBar(BView* view, BRect& rect, HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2,
const BRect& updateRect, const rgb_color& base, uint32 flags, const BRect& updateRect, const rgb_color& base, uint32 flags,
orientation orientation, bool doubleArrows, int32 buttonDown) orientation orientation)
{ {
if (!rect.IsValid() || !rect.Intersects(updateRect)) DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation);
return; DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation);
// 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();
} }
void void
HaikuControlLook::DrawScrollBarThumb(BView* view, BRect& rect, BRect& thumbRect, HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
const BRect& updateRect, const rgb_color& base, uint32 flags, const BRect& updateRect, const rgb_color& base, uint32 flags,
orientation orientation, uint32 knobStyle) orientation orientation)
{ {
if (!rect.IsValid() || !rect.Intersects(updateRect)) if (!rect.IsValid() || !rect.Intersects(updateRect))
return; return;
// save the clipping constraints of the view float gradient1Tint;
view->PushState(); float gradient2Tint;
float darkEdge1Tint;
float darkEdge2Tint;
float shadowTint;
// set clipping constraints to the thumb and background region if ((flags & B_DISABLED) != 0) {
BRegion clipping(rect); gradient1Tint = 0.9;
view->ConstrainClippingRegion(&clipping); gradient2Tint = 0.8;
darkEdge1Tint = B_DARKEN_2_TINT;
// flags darkEdge2Tint = B_DARKEN_2_TINT;
bool isEnabled = (flags & B_DISABLED) == 0; shadowTint = gradient1Tint;
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);
} else { } else {
light = tint_color(base, B_LIGHTEN_MAX_TINT); gradient1Tint = 1.10;
dark = tint_color(base, B_DARKEN_2_TINT); gradient2Tint = 1.05;
dark1 = tint_color(base, B_LIGHTEN_2_TINT); darkEdge1Tint = B_DARKEN_3_TINT;
dark2 = tint_color(base, B_LIGHTEN_1_TINT); darkEdge2Tint = B_DARKEN_2_TINT;
shadowTint = gradient1Tint;
} }
BRect beforeThumb = BRect(); rgb_color darkEdge1 = tint_color(base, darkEdge1Tint);
BRect afterThumb = BRect(); rgb_color darkEdge2 = tint_color(base, darkEdge2Tint);
rgb_color shadow = tint_color(base, shadowTint);
if (orientation == B_HORIZONTAL) { if (orientation == B_HORIZONTAL) {
// I'm only interested in the horizontal coordinates of thumbRect // dark vertical line on left edge
thumbRect.top = rect.top; if (rect.Width() > 0) {
thumbRect.bottom = rect.bottom; view->SetHighColor(darkEdge1);
beforeThumb.Set(rect.left, rect.top, thumbRect.left - 1, rect.bottom); view->StrokeLine(rect.LeftTop(), rect.LeftBottom());
afterThumb.Set(thumbRect.right + 1, rect.top, rect.right, rect.bottom); 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 { } else {
// I'm only interested in the vertical coordinates of thumbRect // dark vertical line on top edge
thumbRect.left = rect.left; if (rect.Height() > 0) {
thumbRect.right = rect.right; view->SetHighColor(darkEdge1);
beforeThumb.Set(rect.left, rect.top, rect.right, thumbRect.top - 1); view->StrokeLine(rect.LeftTop(), rect.RightTop());
afterThumb.Set(rect.left, thumbRect.bottom + 1, rect.right, rect.top++;
rect.bottom); }
} // dark vertical line on bottom edge
if (rect.Height() >= 0) {
if (beforeThumb.IsValid() && afterThumb.IsValid()) { view->SetHighColor(darkEdge2);
// clip to background region view->StrokeLine(rect.LeftBottom(), rect.RightBottom());
BRegion besidesThumb = BRegion(); rect.bottom--;
besidesThumb.Include(beforeThumb); }
besidesThumb.Include(afterThumb); // horizontal shadow line after top edge
view->ConstrainClippingRegion(&besidesThumb); if (rect.Height() >= 0) {
view->SetHighColor(shadow);
// draw background besides thumb view->StrokeLine(rect.LeftTop(), rect.RightTop());
_DrawScrollBarBackground(view, beforeThumb, afterThumb, updateRect, rect.top++;
base, flags, orientation); }
} else { // fill
// before/after rects are invalid, draw thumb on whole rect if (rect.Height() >= 0) {
thumbRect = rect; _FillGradient(view, rect, base, gradient1Tint, gradient2Tint,
} orientation);
// 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
} }
} }
// 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 void
HaikuControlLook::DrawArrowShape(BView* view, BRect& rect, HaikuControlLook::DrawArrowShape(BView* view, BRect& rect, const BRect& updateRect,
const BRect& updateRect, const rgb_color& base, uint32 direction, const rgb_color& base, uint32 direction, uint32 flags, float tint)
uint32 flags, float tint)
{ {
BPoint tri1, tri2, tri3; BPoint tri1, tri2, tri3;
float hInset = rect.Width() / 3; float hInset = rect.Width() / 3;
@@ -1269,24 +1004,20 @@ HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect
view->BeginLineArray(4); view->BeginLineArray(4);
if (orientation == B_HORIZONTAL) { if (orientation == B_HORIZONTAL) {
view->AddLine(barRect.LeftTop(), barRect.RightTop(), view->AddLine(barRect.LeftTop(), barRect.RightTop(), edgeShadowColor);
edgeShadowColor);
view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
edgeLightColor); edgeLightColor);
barRect.InsetBy(0, 1); barRect.InsetBy(0, 1);
view->AddLine(barRect.LeftTop(), barRect.RightTop(), view->AddLine(barRect.LeftTop(), barRect.RightTop(), frameShadowColor);
frameShadowColor);
view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), view->AddLine(barRect.LeftBottom(), barRect.RightBottom(),
frameLightColor); frameLightColor);
barRect.InsetBy(0, 1); barRect.InsetBy(0, 1);
} else { } else {
view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), edgeShadowColor);
edgeShadowColor);
view->AddLine(barRect.RightTop(), barRect.RightBottom(), view->AddLine(barRect.RightTop(), barRect.RightBottom(),
edgeLightColor); edgeLightColor);
barRect.InsetBy(1, 0); barRect.InsetBy(1, 0);
view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), frameShadowColor);
frameShadowColor);
view->AddLine(barRect.RightTop(), barRect.RightBottom(), view->AddLine(barRect.RightTop(), barRect.RightBottom(),
frameLightColor); frameLightColor);
barRect.InsetBy(1, 0); 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 } // namespace BPrivate
+356 -82
View File
@@ -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. * Distributed under the terms of the MIT license.
* *
* Authors: * Authors:
@@ -27,8 +27,6 @@
#include <binary_compatibility/Interface.h> #include <binary_compatibility/Interface.h>
#include <ScrollBarPrivate.h>
//#define TRACE_SCROLLBAR //#define TRACE_SCROLLBAR
#ifdef TRACE_SCROLLBAR #ifdef TRACE_SCROLLBAR
@@ -38,11 +36,31 @@
#endif #endif
typedef enum {
ARROW_LEFT = 0,
ARROW_RIGHT,
ARROW_UP,
ARROW_DOWN,
ARROW_NONE
} arrow_direction;
#define SBC_SCROLLBYVALUE 0 #define SBC_SCROLLBYVALUE 0
#define SBC_SETDOUBLE 1 #define SBC_SETDOUBLE 1
#define SBC_SETPROPORTIONAL 2 #define SBC_SETPROPORTIONAL 2
#define SBC_SETSTYLE 3 #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; static const bigtime_t kRepeatDelay = 300000;
@@ -66,7 +84,7 @@ public:
fUpArrowsEnabled(true), fUpArrowsEnabled(true),
fDownArrowsEnabled(true), fDownArrowsEnabled(true),
fBorderHighlighted(false), fBorderHighlighted(false),
fButtonDown(SCROLL_NO_ARROW) fButtonDown(NOARROW)
{ {
#ifdef TEST_MODE #ifdef TEST_MODE
fScrollBarInfo.proportional = true; 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, void DrawScrollBarButton(BScrollBar* owner, arrow_direction direction,
BRect frame, bool down = false); BRect frame, bool down = false);
@@ -156,7 +166,7 @@ BScrollBar::Private::ButtonRepeaterThread()
if (fScrollBar->LockLooper()) { if (fScrollBar->LockLooper()) {
if (fDoRepeat) { if (fDoRepeat) {
float value = fScrollBar->Value() + fThumbInc; 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 // in this case we want to stop when we're under the mouse
if (fThumbInc > 0.0 && value <= fStopValue) if (fThumbInc > 0.0 && value <= fStopValue)
fScrollBar->SetValue(value); fScrollBar->SetValue(value);
@@ -368,28 +378,205 @@ BScrollBar::DetachedFromWindow()
void void
BScrollBar::Draw(BRect updateRect) BScrollBar::Draw(BRect updateRect)
{ {
uint32 flags = 0; BRect bounds = Bounds();
bool scrollingEnabled = _ScrollingEnabled();
if (scrollingEnabled)
flags |= BControlLook::B_SCROLLABLE;
bool isEnabled = fPrivateData->fEnabled && scrollingEnabled; rgb_color normal = ui_color(B_PANEL_BACKGROUND_COLOR);
if (!isEnabled)
// 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; flags |= BControlLook::B_DISABLED;
bool isFocused = fPrivateData->fBorderHighlighted; // fill background besides the thumb
if (isFocused) if (fOrientation == B_HORIZONTAL) {
flags |= BControlLook::B_FOCUSED; 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 bottomOfThumb(thumbBG.left, rect.bottom + 1,
BRect thumbRect(fPrivateData->fThumbFrame); thumbBG.right, thumbBG.bottom);
be_control_look->DrawScrollBar(this, rect, updateRect, base, be_control_look->DrawScrollBarBackground(this, topOfThumb,
flags, fOrientation, _DoubleArrows(), fPrivateData->fButtonDown); bottomOfThumb, updateRect, normal, flags, fOrientation);
be_control_look->DrawScrollBarThumb(this, rect, thumbRect, updateRect, base, }
flags, fOrientation, fPrivateData->fScrollBarInfo.knob);
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) { if (buttons & B_SECONDARY_MOUSE_BUTTON) {
// special absolute scrolling: move thumb to where we clicked // special absolute scrolling: move thumb to where we clicked
fPrivateData->fButtonDown = SCROLL_THUMB; fPrivateData->fButtonDown = THUMB;
fPrivateData->fClickOffset fPrivateData->fClickOffset = fPrivateData->fThumbFrame.LeftTop() - where;
= fPrivateData->fThumbFrame.LeftTop() - where; if (Orientation() == B_HORIZONTAL)
if (Orientation() == B_HORIZONTAL) { fPrivateData->fClickOffset.x = -fPrivateData->fThumbFrame.Width() / 2;
fPrivateData->fClickOffset.x else
= -fPrivateData->fThumbFrame.Width() / 2; fPrivateData->fClickOffset.y = -fPrivateData->fThumbFrame.Height() / 2;
} else {
fPrivateData->fClickOffset.y
= -fPrivateData->fThumbFrame.Height() / 2;
}
SetValue(_ValueFor(where + fPrivateData->fClickOffset)); SetValue(_ValueFor(where + fPrivateData->fClickOffset));
return; return;
@@ -477,9 +660,8 @@ BScrollBar::MouseDown(BPoint where)
// hit test for the thumb // hit test for the thumb
if (fPrivateData->fThumbFrame.Contains(where)) { if (fPrivateData->fThumbFrame.Contains(where)) {
fPrivateData->fButtonDown = SCROLL_THUMB; fPrivateData->fButtonDown = THUMB;
fPrivateData->fClickOffset fPrivateData->fClickOffset = fPrivateData->fThumbFrame.LeftTop() - where;
= fPrivateData->fThumbFrame.LeftTop() - where;
Invalidate(fPrivateData->fThumbFrame); Invalidate(fPrivateData->fThumbFrame);
return; return;
} }
@@ -493,23 +675,23 @@ BScrollBar::MouseDown(BPoint where)
fPrivateData->fButtonDown = _ButtonFor(where); fPrivateData->fButtonDown = _ButtonFor(where);
switch (fPrivateData->fButtonDown) { switch (fPrivateData->fButtonDown) {
case SCROLL_ARROW_1: case ARROW1:
scrollValue = -buttonStepSize; scrollValue = -buttonStepSize;
break; break;
case SCROLL_ARROW_2: case ARROW2:
scrollValue = buttonStepSize; scrollValue = buttonStepSize;
break; break;
case SCROLL_ARROW_3: case ARROW3:
scrollValue = -buttonStepSize; scrollValue = -buttonStepSize;
break; break;
case SCROLL_ARROW_4: case ARROW4:
scrollValue = buttonStepSize; scrollValue = buttonStepSize;
break; break;
case SCROLL_NO_ARROW: case NOARROW:
// we hit the empty area, figure out which side of the thumb // we hit the empty area, figure out which side of the thumb
if (fOrientation == B_VERTICAL) { if (fOrientation == B_VERTICAL) {
if (where.y < fPrivateData->fThumbFrame.top) if (where.y < fPrivateData->fThumbFrame.top)
@@ -551,11 +733,13 @@ BScrollBar::MouseDown(BPoint where)
void void
BScrollBar::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) 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; return;
}
if (fPrivateData->fButtonDown != SCROLL_NO_ARROW) { if (fPrivateData->fButtonDown != NOARROW) {
if (fPrivateData->fButtonDown == SCROLL_THUMB) { if (fPrivateData->fButtonDown == THUMB) {
SetValue(_ValueFor(where + fPrivateData->fClickOffset)); SetValue(_ValueFor(where + fPrivateData->fClickOffset));
} else { } else {
// suspend the repeating if the mouse is not over the button // 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 void
BScrollBar::MouseUp(BPoint where) BScrollBar::MouseUp(BPoint where)
{ {
if (fPrivateData->fButtonDown == SCROLL_THUMB) if (fPrivateData->fButtonDown == THUMB)
Invalidate(fPrivateData->fThumbFrame); Invalidate(fPrivateData->fThumbFrame);
else else
Invalidate(_ButtonRectFor(fPrivateData->fButtonDown)); Invalidate(_ButtonRectFor(fPrivateData->fButtonDown));
fPrivateData->fButtonDown = SCROLL_NO_ARROW; fPrivateData->fButtonDown = NOARROW;
fPrivateData->fExitRepeater = true; fPrivateData->fExitRepeater = true;
fPrivateData->fDoRepeat = false; fPrivateData->fDoRepeat = false;
} }
@@ -674,11 +858,13 @@ BScrollBar::SetProportion(float value)
TRACE("BScrollBar(%s)::SetProportion(%.1f)\n", Name(), 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; fProportion = value;
bool newEnabled = fPrivateData->fEnabled && _ScrollingEnabled(); bool newEnabled = fPrivateData->fEnabled && fMin < fMax
&& fProportion < 1.0f && fProportion >= 0.0f;
_UpdateThumbFrame(); _UpdateThumbFrame();
@@ -1030,13 +1216,6 @@ BScrollBar::operator=(const BScrollBar&)
} }
bool
BScrollBar::_ScrollingEnabled() const
{
return fMin < fMax && fProportion >= 0.0f && fProportion < 1.0f;
}
bool bool
BScrollBar::_DoubleArrows() const BScrollBar::_DoubleArrows() const
{ {
@@ -1208,39 +1387,39 @@ BScrollBar::_ButtonFor(BPoint where) const
if (fOrientation == B_VERTICAL) { if (fOrientation == B_VERTICAL) {
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_1; return ARROW1;
if (_DoubleArrows()) { if (_DoubleArrows()) {
rect.OffsetBy(0.0, buttonSize); rect.OffsetBy(0.0, buttonSize);
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_2; return ARROW2;
rect.OffsetTo(bounds.left, bounds.bottom - 2 * buttonSize); rect.OffsetTo(bounds.left, bounds.bottom - 2 * buttonSize);
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_3; return ARROW3;
} }
rect.OffsetTo(bounds.left, bounds.bottom - buttonSize); rect.OffsetTo(bounds.left, bounds.bottom - buttonSize);
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_4; return ARROW4;
} else { } else {
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_1; return ARROW1;
if (_DoubleArrows()) { if (_DoubleArrows()) {
rect.OffsetBy(buttonSize, 0.0); rect.OffsetBy(buttonSize, 0.0);
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_2; return ARROW2;
rect.OffsetTo(bounds.right - 2 * buttonSize, bounds.top); rect.OffsetTo(bounds.right - 2 * buttonSize, bounds.top);
if (rect.Contains(where)) if (rect.Contains(where))
return SCROLL_ARROW_3; return ARROW3;
} }
rect.OffsetTo(bounds.right - buttonSize, bounds.top); rect.OffsetTo(bounds.right - buttonSize, bounds.top);
if (rect.Contains(where)) 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) { if (fOrientation == B_VERTICAL) {
switch (button) { switch (button) {
case SCROLL_ARROW_1: case ARROW1:
break; break;
case SCROLL_ARROW_2: case ARROW2:
rect.OffsetBy(0.0, buttonSize); rect.OffsetBy(0.0, buttonSize);
break; break;
case SCROLL_ARROW_3: case ARROW3:
rect.OffsetTo(bounds.left, bounds.bottom - 2 * buttonSize + 1); rect.OffsetTo(bounds.left, bounds.bottom - 2 * buttonSize + 1);
break; break;
case SCROLL_ARROW_4: case ARROW4:
rect.OffsetTo(bounds.left, bounds.bottom - buttonSize + 1); rect.OffsetTo(bounds.left, bounds.bottom - buttonSize + 1);
break; break;
} }
} else { } else {
switch (button) { switch (button) {
case SCROLL_ARROW_1: case ARROW1:
break; break;
case SCROLL_ARROW_2: case ARROW2:
rect.OffsetBy(buttonSize, 0.0); rect.OffsetBy(buttonSize, 0.0);
break; break;
case SCROLL_ARROW_3: case ARROW3:
rect.OffsetTo(bounds.right - 2 * buttonSize + 1, bounds.top); rect.OffsetTo(bounds.right - 2 * buttonSize + 1, bounds.top);
break; break;
case SCROLL_ARROW_4: case ARROW4:
rect.OffsetTo(bounds.right - buttonSize + 1, bounds.top); rect.OffsetTo(bounds.right - buttonSize + 1, bounds.top);
break; break;
} }
@@ -1316,17 +1495,17 @@ BScrollBar::_UpdateArrowButtons()
bool upEnabled = fValue > fMin; bool upEnabled = fValue > fMin;
if (fPrivateData->fUpArrowsEnabled != upEnabled) { if (fPrivateData->fUpArrowsEnabled != upEnabled) {
fPrivateData->fUpArrowsEnabled = upEnabled; fPrivateData->fUpArrowsEnabled = upEnabled;
Invalidate(_ButtonRectFor(SCROLL_ARROW_1)); Invalidate(_ButtonRectFor(ARROW1));
if (_DoubleArrows()) if (_DoubleArrows())
Invalidate(_ButtonRectFor(SCROLL_ARROW_3)); Invalidate(_ButtonRectFor(ARROW3));
} }
bool downEnabled = fValue < fMax; bool downEnabled = fValue < fMax;
if (fPrivateData->fDownArrowsEnabled != downEnabled) { if (fPrivateData->fDownArrowsEnabled != downEnabled) {
fPrivateData->fDownArrowsEnabled = downEnabled; fPrivateData->fDownArrowsEnabled = downEnabled;
Invalidate(_ButtonRectFor(SCROLL_ARROW_4)); Invalidate(_ButtonRectFor(ARROW4));
if (_DoubleArrows()) 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 BSize
BScrollBar::_MinSize() const BScrollBar::_MinSize() const
{ {
+88 -33
View File
@@ -35,10 +35,8 @@ FakeScrollBar::FakeScrollBar(bool drawArrows, bool doubleArrows,
fDrawArrows(drawArrows), fDrawArrows(drawArrows),
fDoubleArrows(doubleArrows) fDoubleArrows(doubleArrows)
{ {
// add some height to draw the ring around the scroll bar SetExplicitMinSize(BSize(160, 20));
float height = B_H_SCROLL_BAR_HEIGHT + 8; SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 20));
SetExplicitMinSize(BSize(200, height));
SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, height));
} }
@@ -50,42 +48,99 @@ FakeScrollBar::~FakeScrollBar(void)
void void
FakeScrollBar::Draw(BRect updateRect) 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()) {
if (IsFocus()) // draw the focus indicator
flags |= BControlLook::B_FOCUSED; SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
StrokeRect(bounds);
bounds.InsetBy(1.0, 1.0);
if (Value() == B_CONTROL_ON) // Draw the selected border (1px)
SetHighColor(ui_color(B_CONTROL_MARK_COLOR)); if (Value() == B_CONTROL_ON)
else SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
SetHighColor(base); else
SetHighColor(normal);
// Draw the selected border (2px) StrokeRect(bounds);
StrokeRect(rect); bounds.InsetBy(1.0, 1.0);
rect.InsetBy(1, 1); } else {
StrokeRect(rect); // Draw the selected border (2px)
rect.InsetBy(1, 1); if (Value() == B_CONTROL_ON)
SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
else
SetHighColor(normal);
// draw a 1px gap StrokeRect(bounds);
SetHighColor(base); bounds.InsetBy(1.0, 1.0);
StrokeRect(rect); StrokeRect(bounds);
rect.InsetBy(1, 1); bounds.InsetBy(1.0, 1.0);
}
// draw a 1px border around control // draw a gap (1px)
SetHighColor(tint_color(base, B_DARKEN_1_TINT)); SetHighColor(normal);
StrokeRect(rect); StrokeRect(bounds);
rect.InsetBy(1, 1); bounds.InsetBy(1.0, 1.0);
SetHighColor(base);
be_control_look->DrawScrollBar(this, rect, updateRect, base, // draw a border around control (1px)
flags, B_HORIZONTAL, fDoubleArrows); SetHighColor(tint_color(normal, B_DARKEN_1_TINT));
float less = floorf(rect.Width() / 3); // thumb takes up 1/3 full width StrokeRect(bounds);
BRect thumbRect(rect.left + less, rect.top, rect.right - less, rect.bottom); bounds.InsetBy(1.0, 1.0);
be_control_look->DrawScrollBarThumb(this, rect, thumbRect, updateRect, base,
flags, B_HORIZONTAL, fKnobStyle); 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);
} }