IK: Update scroll bars for alternative control look

Scroll bars should look and work identically to before on
HaikuControlLook.

Add DrawScrollBarButton() and DrawScrollBarThumb() and
DrawScrollBarBorder() methods. These methods are used to draw scroll
bars in a generic way so that they can be drawn differently by alternative
control look's (e.g. BeControlLook). Also it gives us back drawing of
scroll bar knobs.  However the knob setting is not exposed in the
interface in this commit.

These methods are in addition to the 2 existing DrawScrollBarBackground()
methods that draw the scroll bar background. One draws the area above and
below the thumb and the other is called by the first to actually draw the
area.

The rest of the drawing besides the backgrounds was being done in
BScrollBar before. To draw the scroll bar arrows and thumb we were recyling
other ControlLook methods, while this worked well enough on HaikuControlLook
it wasn't flexible enough for alternative control looks.

DrawScrollBarButton() is used to draw the four scroll buttons and is
typically (so far) used in combination with DrawArrowShape().

DrawScrollBarThumb() draws the scroll bar thumb.

DrawScrollBarBorder() draws a 1px border around the entire scroll bar,
potentially B_KEYBOARD_NAVIGATION_COLOR if focused (although this is
feature not currently used.)

Draw unscrollable scroll bars as if they were disabled including the
buttons with their arrow shapes, background, and thumb.

Add FBC backwords compatibility macros in ControlLook.cpp

Change-Id: I9237c5ce45d17d674785111d51de951e5686306b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/351
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
John Scipione 2020-03-04 05:03:47 -05:00 committed by waddlesplash
parent 67597f4204
commit 1482b250a7
6 changed files with 495 additions and 323 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2017, Haiku, Inc. All rights reserved.
* Copyright 2009-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _CONTROL_LOOK_H
@ -90,6 +90,12 @@ public:
B_BLEND_FRAME = 1 << 16,
};
enum {
B_KNOB_NONE = 0,
B_KNOB_DOTS,
B_KNOB_LINES
};
virtual BAlignment DefaultLabelAlignment() const = 0;
virtual float DefaultLabelSpacing() const = 0;
@ -401,11 +407,24 @@ public:
uint32 borders = B_ALL_BORDERS,
border_style borderStyle = B_FANCY_BORDER,
uint32 side = B_TOP_BORDER) = 0;
virtual void DrawScrollBarButton(BView* view,
BRect rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
int32 direction, orientation orientation,
bool down = false) = 0;
virtual void DrawScrollBarThumb(BView* view,
BRect& rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
orientation orientation,
uint32 knobStyle = B_KNOB_NONE) = 0;
virtual void DrawScrollBarBorder(BView* view,
BRect rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
orientation orientation) = 0;
private:
// FBC padding
virtual void _ReservedControlLook2();
virtual void _ReservedControlLook3();
virtual void _ReservedControlLook4();
virtual void _ReservedControlLook5();
virtual void _ReservedControlLook6();
virtual void _ReservedControlLook7();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2008, Haiku, Inc. All rights reserved.
* Copyright 2001-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _SCROLL_BAR_H
@ -121,14 +121,6 @@ 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;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2017, Haiku, Inc. All rights reserved.
* Copyright 2009-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU_CONTROL_LOOK_H
@ -157,6 +157,15 @@ public:
const rgb_color& base,
uint32 flags = 0);
virtual void DrawScrollBarBorder(BView* view,
BRect rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
orientation orientation);
virtual void DrawScrollBarButton(BView* view,
BRect rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
int32 direction, orientation orientation,
bool down = false);
virtual void DrawScrollBarBackground(BView* view,
BRect& rect1, BRect& rect2,
const BRect& updateRect,
@ -166,6 +175,11 @@ public:
BRect& rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
orientation orientation);
virtual void DrawScrollBarThumb(BView* view,
BRect& rect, const BRect& updateRect,
const rgb_color& base, uint32 flags,
orientation orientation,
uint32 knobStyle = B_KNOB_NONE);
virtual void DrawScrollViewFrame(BView* view,
BRect& rect, const BRect& updateRect,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 Haiku, Inc. All rights reserved.
* Copyright 2012-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@ -91,9 +91,42 @@ B_IF_GCC_2(_ReservedControlLook1__Q28BPrivate12BControlLook,
}
void BControlLook::_ReservedControlLook2() {}
void BControlLook::_ReservedControlLook3() {}
void BControlLook::_ReservedControlLook4() {}
extern "C" void
B_IF_GCC_2(_ReservedControlLook2__Q28BPrivate12BControlLook,
_ZN8BPrivate12BControlLook21_ReservedControlLook2Ev)(
BControlLook* controlLook, BView* view, BRect rect,
const BRect& updateRect, const rgb_color& base, uint32 flags,
int32 direction, orientation orientation, bool down)
{
controlLook->DrawScrollBarButton(view, rect, updateRect, base, flags,
direction, orientation, down);
}
extern "C" void
B_IF_GCC_2(_ReservedControlLook3__Q28BPrivate12BControlLook,
_ZN8BPrivate12BControlLook21_ReservedControlLook3Ev)(
BControlLook* controlLook, BView* view, BRect rect,
const BRect& updateRect, const rgb_color& base, uint32 flags,
int32 direction, orientation orientation, uint32 knobStyle)
{
controlLook->DrawScrollBarThumb(view, rect, updateRect, base, flags,
orientation, knobStyle);
}
extern "C" void
B_IF_GCC_2(_ReservedControlLook4__Q28BPrivate12BControlLook,
_ZN8BPrivate12BControlLook21_ReservedControlLook4Ev)(
BControlLook* controlLook, BView* view, BRect rect,
const BRect& updateRect, const rgb_color& base, uint32 flags,
orientation orientation)
{
controlLook->DrawScrollBarBorder(view, rect, updateRect, base, flags,
orientation);
}
void BControlLook::_ReservedControlLook5() {}
void BControlLook::_ReservedControlLook6() {}
void BControlLook::_ReservedControlLook7() {}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
* Copyright 2012-2017 Haiku, Inc. All rights reserved.
* Copyright 2012-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -28,7 +28,6 @@
namespace BPrivate {
static const float kEdgeBevelLightTint = 0.59;
static const float kEdgeBevelShadowTint = 1.0735;
static const float kHoverTintFactor = 0.85;
@ -563,9 +562,93 @@ HaikuControlLook::DrawRadioButton(BView* view, BRect& rect, const BRect& updateR
void
HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, BRect& rect2,
HaikuControlLook::DrawScrollBarBorder(BView* view, BRect rect,
const BRect& updateRect, const rgb_color& base, uint32 flags,
orientation orientation)
{
if (!rect.IsValid() || !rect.Intersects(updateRect))
return;
view->PushState();
// set clipping constraints to updateRect
BRegion clipping(updateRect);
view->ConstrainClippingRegion(&clipping);
bool isEnabled = (flags & B_DISABLED) == 0;
bool isFocused = (flags & B_FOCUSED) != 0;
view->SetHighColor(tint_color(base, B_DARKEN_2_TINT));
// stroke a line around the entire scrollbar
// take care of border highlighting, scroll target is focus view
if (isEnabled && isFocused) {
rgb_color borderColor = view->HighColor();
rgb_color highlightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
view->BeginLineArray(4);
view->AddLine(BPoint(rect.left + 1, rect.bottom),
BPoint(rect.right, rect.bottom), borderColor);
view->AddLine(BPoint(rect.right, rect.top + 1),
BPoint(rect.right, rect.bottom - 1), borderColor);
if (orientation == B_HORIZONTAL) {
view->AddLine(BPoint(rect.left, rect.top + 1),
BPoint(rect.left, rect.bottom), borderColor);
} else {
view->AddLine(BPoint(rect.left, rect.top),
BPoint(rect.left, rect.bottom), highlightColor);
}
if (orientation == B_HORIZONTAL) {
view->AddLine(BPoint(rect.left, rect.top),
BPoint(rect.right, rect.top), highlightColor);
} else {
view->AddLine(BPoint(rect.left + 1, rect.top),
BPoint(rect.right, rect.top), borderColor);
}
view->EndLineArray();
} else
view->StrokeRect(rect);
view->PopState();
}
void
HaikuControlLook::DrawScrollBarButton(BView* view, BRect rect,
const BRect& updateRect, const rgb_color& base, uint32 flags,
int32 direction, orientation orientation, bool down)
{
if (!rect.IsValid() || !rect.Intersects(updateRect))
return;
// clip to button
BRegion buttonRegion(rect);
view->ConstrainClippingRegion(&buttonRegion);
bool isEnabled = (flags & B_DISABLED) == 0;
rgb_color buttonColor = isEnabled ? base
: tint_color(base, B_LIGHTEN_1_TINT);
DrawButtonBackground(view, rect, updateRect, buttonColor, flags,
BControlLook::B_ALL_BORDERS, orientation);
rect.InsetBy(-1, -1);
DrawArrowShape(view, rect, updateRect, base, direction, flags, 1.9f);
// almost but not quite B_DARKEN_MAX_TINT
// revert clipping constraints
BRegion clipping(updateRect);
view->ConstrainClippingRegion(&clipping);
}
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);
@ -580,24 +663,35 @@ HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
if (!rect.IsValid() || !rect.Intersects(updateRect))
return;
view->PushState();
// set clipping constraints to updateRect
BRegion clipping(updateRect);
view->ConstrainClippingRegion(&clipping);
bool isEnabled = (flags & B_DISABLED) == 0;
// fill background, we'll draw arrows and thumb on top
view->SetDrawingMode(B_OP_COPY);
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 {
if (isEnabled) {
gradient1Tint = 1.10;
gradient2Tint = 1.05;
darkEdge1Tint = B_DARKEN_3_TINT;
darkEdge2Tint = B_DARKEN_2_TINT;
shadowTint = gradient1Tint;
} else {
gradient1Tint = 0.9;
gradient2Tint = 0.8;
darkEdge1Tint = B_DARKEN_2_TINT;
darkEdge2Tint = B_DARKEN_2_TINT;
shadowTint = gradient1Tint;
}
rgb_color darkEdge1 = tint_color(base, darkEdge1Tint);
@ -653,6 +747,198 @@ HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect,
orientation);
}
}
view->PopState();
}
void
HaikuControlLook::DrawScrollBarThumb(BView* view, BRect& rect,
const BRect& updateRect, const rgb_color& base, uint32 flags,
orientation orientation, uint32 knobStyle)
{
if (!rect.IsValid() || !rect.Intersects(updateRect))
return;
view->PushState();
// set clipping constraints to updateRect
BRegion clipping(updateRect);
view->ConstrainClippingRegion(&clipping);
// flags
bool isEnabled = (flags & B_DISABLED) == 0;
// colors
rgb_color thumbColor = ui_color(B_SCROLL_BAR_THUMB_COLOR);
const float bgTint = 1.06;
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);
}
// draw thumb over background
view->SetDrawingMode(B_OP_OVER);
view->SetHighColor(dark1);
// draw scroll thumb
if (isEnabled) {
// fill the clickable surface of the thumb
DrawButtonBackground(view, rect, updateRect, thumbColor, 0,
B_ALL_BORDERS, orientation);
} else {
// thumb bevel
view->BeginLineArray(4);
view->AddLine(BPoint(rect.left, rect.bottom),
BPoint(rect.left, rect.top), light);
view->AddLine(BPoint(rect.left + 1, rect.top),
BPoint(rect.right, rect.top), light);
view->AddLine(BPoint(rect.right, rect.top + 1),
BPoint(rect.right, rect.bottom), dark2);
view->AddLine(BPoint(rect.right - 1, rect.bottom),
BPoint(rect.left + 1, rect.bottom), dark2);
view->EndLineArray();
// thumb fill
rect.InsetBy(1, 1);
view->SetHighColor(dark1);
view->FillRect(rect);
}
// draw knob style
if (knobStyle != B_KNOB_NONE) {
rgb_color knobLight = isEnabled
? tint_color(thumbColor, B_LIGHTEN_MAX_TINT)
: tint_color(dark1, bgTint);
rgb_color knobDark = isEnabled
? tint_color(thumbColor, 1.22)
: tint_color(knobLight, B_DARKEN_1_TINT);
if (knobStyle == B_KNOB_DOTS) {
// draw dots on the scroll bar thumb
float hcenter = rect.left + rect.Width() / 2;
float vmiddle = rect.top + rect.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 = rect.Height();
if (rect.left + 3 < hcenter - spacer) {
view->SetHighColor(knobDark);
view->FillRect(knob.OffsetByCopy(-spacer, 0));
view->SetHighColor(knobLight);
view->FillRect(knob.OffsetByCopy(-spacer + 1, 1));
}
if (rect.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 = rect.Width();
if (rect.top + 3 < vmiddle - spacer) {
view->SetHighColor(knobDark);
view->FillRect(knob.OffsetByCopy(0, -spacer));
view->SetHighColor(knobLight);
view->FillRect(knob.OffsetByCopy(1, -spacer + 1));
}
if (rect.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 == B_KNOB_LINES) {
// draw lines on the scroll bar thumb
if (orientation == B_HORIZONTAL) {
float middle = rect.Width() / 2;
view->BeginLineArray(6);
view->AddLine(
BPoint(rect.left + middle - 3, rect.top + 2),
BPoint(rect.left + middle - 3, rect.bottom - 2),
knobDark);
view->AddLine(
BPoint(rect.left + middle, rect.top + 2),
BPoint(rect.left + middle, rect.bottom - 2),
knobDark);
view->AddLine(
BPoint(rect.left + middle + 3, rect.top + 2),
BPoint(rect.left + middle + 3, rect.bottom - 2),
knobDark);
view->AddLine(
BPoint(rect.left + middle - 2, rect.top + 2),
BPoint(rect.left + middle - 2, rect.bottom - 2),
knobLight);
view->AddLine(
BPoint(rect.left + middle + 1, rect.top + 2),
BPoint(rect.left + middle + 1, rect.bottom - 2),
knobLight);
view->AddLine(
BPoint(rect.left + middle + 4, rect.top + 2),
BPoint(rect.left + middle + 4, rect.bottom - 2),
knobLight);
view->EndLineArray();
} else {
// B_VERTICAL
float middle = rect.Height() / 2;
view->BeginLineArray(6);
view->AddLine(
BPoint(rect.left + 2, rect.top + middle - 3),
BPoint(rect.right - 2, rect.top + middle - 3),
knobDark);
view->AddLine(
BPoint(rect.left + 2, rect.top + middle),
BPoint(rect.right - 2, rect.top + middle),
knobDark);
view->AddLine(
BPoint(rect.left + 2, rect.top + middle + 3),
BPoint(rect.right - 2, rect.top + middle + 3),
knobDark);
view->AddLine(
BPoint(rect.left + 2, rect.top + middle - 2),
BPoint(rect.right - 2, rect.top + middle - 2),
knobLight);
view->AddLine(
BPoint(rect.left + 2, rect.top + middle + 1),
BPoint(rect.right - 2, rect.top + middle + 1),
knobLight);
view->AddLine(
BPoint(rect.left + 2, rect.top + middle + 4),
BPoint(rect.right - 2, rect.top + middle + 4),
knobLight);
view->EndLineArray();
}
}
}
view->PopState();
}
@ -741,8 +1027,9 @@ 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;
@ -1005,20 +1292,24 @@ 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);
@ -3607,7 +3898,6 @@ HaikuControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect,
}
bool
HaikuControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
rgb_color& color, uint32 flags) const
@ -3646,5 +3936,4 @@ HaikuControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
return true;
}
} // namespace BPrivate

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2014 Haiku, Inc. All rights reserved.
* Copyright 2001-2020 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
@ -379,205 +379,120 @@ BScrollBar::DetachedFromWindow()
void
BScrollBar::Draw(BRect updateRect)
{
BRect bounds = Bounds();
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);
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
uint32 flags = 0;
if (!enabled)
bool scrollingEnabled = fMin < fMax
&& fProportion >= 0.0f && fProportion < 1.0f;
if (scrollingEnabled)
flags |= BControlLook::B_PARTIALLY_ACTIVATED;
if (!fPrivateData->fEnabled || !scrollingEnabled)
flags |= BControlLook::B_DISABLED;
// 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);
bool isFocused = fPrivateData->fBorderHighlighted;
if (isFocused)
flags |= BControlLook::B_FOCUSED;
bool doubleArrows = _DoubleArrows();
// draw border
BRect rect = Bounds();
be_control_look->DrawScrollBarBorder(this, rect, updateRect, base, flags,
fOrientation);
// inset past border
rect.InsetBy(1, 1);
// draw arrows buttons
BRect thumbBG = rect;
if (fOrientation == B_HORIZONTAL) {
BRect buttonFrame(rect.left, rect.top,
rect.left + rect.Height(), rect.bottom);
be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect,
base, flags, BControlLook::B_LEFT_ARROW, fOrientation,
fPrivateData->fButtonDown == ARROW1);
if (doubleArrows) {
buttonFrame.OffsetBy(rect.Height() + 1, 0.0f);
be_control_look->DrawScrollBarButton(this, buttonFrame,
updateRect, base, flags, BControlLook::B_RIGHT_ARROW,
fOrientation, fPrivateData->fButtonDown == ARROW2);
buttonFrame.OffsetTo(rect.right - ((rect.Height() * 2) + 1),
rect.top);
be_control_look->DrawScrollBarButton(this, buttonFrame,
updateRect, base, flags, BControlLook::B_LEFT_ARROW,
fOrientation, fPrivateData->fButtonDown == ARROW3);
thumbBG.left += rect.Height() * 2 + 2;
thumbBG.right -= rect.Height() * 2 + 2;
} else {
thumbBG.left += rect.Height() + 1;
thumbBG.right -= rect.Height() + 1;
}
buttonFrame.OffsetTo(rect.right - rect.Height(), rect.top);
be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect,
base, flags, BControlLook::B_RIGHT_ARROW, fOrientation,
fPrivateData->fButtonDown == ARROW4);
} else {
BRect buttonFrame(rect.left, rect.top, rect.right,
rect.top + rect.Width());
be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect,
base, flags, BControlLook::B_UP_ARROW, fOrientation,
fPrivateData->fButtonDown == ARROW1);
if (doubleArrows) {
buttonFrame.OffsetBy(0, rect.Width() + 1);
be_control_look->DrawScrollBarButton(this, buttonFrame,
updateRect, base, flags, BControlLook::B_DOWN_ARROW,
fOrientation, fPrivateData->fButtonDown == ARROW2);
buttonFrame.OffsetTo(rect.left, rect.bottom
- ((rect.Width() * 2) + 1));
be_control_look->DrawScrollBarButton(this, buttonFrame,
updateRect, base, flags, BControlLook::B_UP_ARROW,
fOrientation, fPrivateData->fButtonDown == ARROW3);
thumbBG.top += rect.Width() * 2 + 2;
thumbBG.bottom -= rect.Width() * 2 + 2;
} else {
thumbBG.top += rect.Width() + 1;
thumbBG.bottom -= rect.Width() + 1;
}
buttonFrame.OffsetTo(rect.left, rect.bottom - rect.Width());
be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect,
base, flags, BControlLook::B_DOWN_ARROW, fOrientation,
fPrivateData->fButtonDown == ARROW4);
}
// fill background besides the thumb
rect = fPrivateData->fThumbFrame;
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);
be_control_look->DrawScrollBarBackground(this, leftOfThumb,
rightOfThumb, updateRect, normal, flags, fOrientation);
rightOfThumb, updateRect, base, flags, fOrientation);
} else {
BRect topOfThumb(thumbBG.left, thumbBG.top,
thumbBG.right, rect.top - 1);
BRect bottomOfThumb(thumbBG.left, rect.bottom + 1,
thumbBG.right, thumbBG.bottom);
be_control_look->DrawScrollBarBackground(this, topOfThumb,
bottomOfThumb, updateRect, normal, flags, fOrientation);
bottomOfThumb, updateRect, base, 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);
}
}
// draw thumb
rect = fPrivateData->fThumbFrame;
be_control_look->DrawScrollBarThumb(this, rect, updateRect,
ui_color(B_SCROLL_BAR_THUMB_COLOR), flags, fOrientation,
fPrivateData->fScrollBarInfo.knob);
}
@ -649,11 +564,15 @@ BScrollBar::MouseDown(BPoint where)
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
// special absolute scrolling: move thumb to where we clicked
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;
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;
@ -662,7 +581,8 @@ BScrollBar::MouseDown(BPoint where)
// hit test for the thumb
if (fPrivateData->fThumbFrame.Contains(where)) {
fPrivateData->fButtonDown = THUMB;
fPrivateData->fClickOffset = fPrivateData->fThumbFrame.LeftTop() - where;
fPrivateData->fClickOffset
= fPrivateData->fThumbFrame.LeftTop() - where;
Invalidate(fPrivateData->fThumbFrame);
return;
}
@ -1553,101 +1473,6 @@ 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
{