1 /*
2 * Copyright 2010-2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * John Scipione <jscipione@gmail.com>
8 */
9
10
11 #include "FakeScrollBar.h"
12
13 #include <Box.h>
14 #include <ControlLook.h>
15 #include <Message.h>
16 #include <ScrollBar.h>
17 #include <Shape.h>
18 #include <Size.h>
19 #include <Window.h>
20
21
22 typedef enum {
23 ARROW_LEFT = 0,
24 ARROW_RIGHT,
25 ARROW_UP,
26 ARROW_DOWN,
27 ARROW_NONE
28 } arrow_direction;
29
30
FakeScrollBar(bool drawArrows,bool doubleArrows,BMessage * message)31 FakeScrollBar::FakeScrollBar(bool drawArrows, bool doubleArrows,
32 BMessage* message)
33 :
34 BControl("FakeScrollBar", NULL, message, B_WILL_DRAW | B_NAVIGABLE),
35 fDrawArrows(drawArrows),
36 fDoubleArrows(doubleArrows)
37 {
38 SetExplicitMinSize(BSize(160, 20));
39 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 20));
40 }
41
42
~FakeScrollBar(void)43 FakeScrollBar::~FakeScrollBar(void)
44 {
45 }
46
47
48 void
Draw(BRect updateRect)49 FakeScrollBar::Draw(BRect updateRect)
50 {
51 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
52
53 uint32 flags = BControlLook::B_PARTIALLY_ACTIVATED;
54
55 if (Value() == B_CONTROL_ON)
56 SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
57 else
58 SetHighColor(base);
59
60 BRect rect(Bounds());
61
62 // draw the selected border (2px)
63 StrokeRect(rect);
64 rect.InsetBy(1, 1);
65 StrokeRect(rect);
66 rect.InsetBy(1, 1);
67
68 // draw a 1px gap
69 SetHighColor(base);
70 StrokeRect(rect);
71 rect.InsetBy(1, 1);
72
73 // draw a 1px border around the entire scroll bar
74 be_control_look->DrawScrollBarBorder(this, rect, updateRect, base, flags,
75 B_HORIZONTAL);
76
77 // inset past border
78 rect.InsetBy(1, 1);
79
80 // draw arrow buttons
81 if (fDrawArrows) {
82 BRect buttonFrame(rect.left, rect.top, rect.left + rect.Height(),
83 rect.bottom);
84 be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect,
85 base, flags, BControlLook::B_LEFT_ARROW, B_HORIZONTAL);
86 if (fDoubleArrows) {
87 buttonFrame.OffsetBy(rect.Height() + 1, 0.0f);
88 be_control_look->DrawScrollBarButton(this, buttonFrame,
89 updateRect, base, flags, BControlLook::B_RIGHT_ARROW,
90 B_HORIZONTAL);
91 buttonFrame.OffsetTo(rect.right - ((rect.Height() * 2) + 1),
92 rect.top);
93 be_control_look->DrawScrollBarButton(this, buttonFrame,
94 updateRect, base, flags, BControlLook::B_LEFT_ARROW,
95 B_HORIZONTAL);
96 }
97 buttonFrame.OffsetTo(rect.right - rect.Height(), rect.top);
98 be_control_look->DrawScrollBarButton(this, buttonFrame, updateRect,
99 base, flags, BControlLook::B_RIGHT_ARROW, B_HORIZONTAL);
100 }
101
102 // inset rect to make room for arrows
103 if (fDrawArrows) {
104 if (fDoubleArrows)
105 rect.InsetBy((rect.Height() + 1) * 2, 0.0f);
106 else
107 rect.InsetBy(rect.Height() + 1, 0.0f);
108 }
109
110 // draw background and thumb
111 float less = floorf(rect.Width() / 3);
112 BRect thumbRect(rect.left + less, rect.top, rect.right - less,
113 rect.bottom);
114 BRect leftOfThumb(rect.left, thumbRect.top, thumbRect.left - 1,
115 thumbRect.bottom);
116 BRect rightOfThumb(thumbRect.right + 1, thumbRect.top, rect.right,
117 thumbRect.bottom);
118
119 be_control_look->DrawScrollBarBackground(this, leftOfThumb,
120 rightOfThumb, updateRect, base, flags, B_HORIZONTAL);
121 be_control_look->DrawScrollBarThumb(this, thumbRect, updateRect,
122 ui_color(B_SCROLL_BAR_THUMB_COLOR), flags, B_HORIZONTAL, fKnobStyle);
123 }
124
125
126 void
MouseDown(BPoint point)127 FakeScrollBar::MouseDown(BPoint point)
128 {
129 BControl::MouseDown(point);
130 }
131
132
133 void
MouseMoved(BPoint point,uint32 transit,const BMessage * message)134 FakeScrollBar::MouseMoved(BPoint point, uint32 transit,
135 const BMessage* message)
136 {
137 BControl::MouseMoved(point, transit, message);
138 }
139
140
141 void
MouseUp(BPoint point)142 FakeScrollBar::MouseUp(BPoint point)
143 {
144 SetValue(B_CONTROL_ON);
145 Invoke();
146
147 Invalidate();
148
149 BControl::MouseUp(point);
150 }
151
152
153 void
SetValue(int32 value)154 FakeScrollBar::SetValue(int32 value)
155 {
156 if (value != Value()) {
157 BControl::SetValueNoUpdate(value);
158 Invalidate();
159 }
160
161 if (!value)
162 return;
163
164 BView* parent = Parent();
165 BView* child = NULL;
166
167 if (parent != NULL) {
168 // If the parent is a BBox, the group parent is the parent of the BBox
169 BBox* box = dynamic_cast<BBox*>(parent);
170
171 if (box && box->LabelView() == this)
172 parent = box->Parent();
173
174 if (parent != NULL) {
175 BBox* box = dynamic_cast<BBox*>(parent);
176
177 // If the parent is a BBox, skip the label if there is one
178 if (box && box->LabelView())
179 child = parent->ChildAt(1);
180 else
181 child = parent->ChildAt(0);
182 } else
183 child = Window()->ChildAt(0);
184 } else if (Window())
185 child = Window()->ChildAt(0);
186
187 while (child) {
188 FakeScrollBar* scrollbar = dynamic_cast<FakeScrollBar*>(child);
189
190 if (scrollbar != NULL && (scrollbar != this))
191 scrollbar->SetValue(B_CONTROL_OFF);
192 else {
193 // If the child is a BBox, check if the label is a scrollbarbutton
194 BBox* box = dynamic_cast<BBox*>(child);
195
196 if (box && box->LabelView()) {
197 scrollbar = dynamic_cast<FakeScrollBar*>(box->LabelView());
198
199 if (scrollbar != NULL && (scrollbar != this))
200 scrollbar->SetValue(B_CONTROL_OFF);
201 }
202 }
203
204 child = child->NextSibling();
205 }
206
207 //ASSERT(Value() == B_CONTROL_ON);
208 }
209
210
211 // #pragma mark -
212
213
214 void
SetDoubleArrows(bool doubleArrows)215 FakeScrollBar::SetDoubleArrows(bool doubleArrows)
216 {
217 fDoubleArrows = doubleArrows;
218 Invalidate();
219 }
220
221
222 void
SetKnobStyle(uint32 knobStyle)223 FakeScrollBar::SetKnobStyle(uint32 knobStyle)
224 {
225 fKnobStyle = knobStyle;
226 Invalidate();
227 }
228
229
230 void
SetFromScrollBarInfo(const scroll_bar_info & info)231 FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info)
232 {
233 fDoubleArrows = info.double_arrows;
234 fKnobStyle = info.knob;
235 Invalidate();
236 }
237
238
239 // #pragma mark -
240
241
242 void
_DrawArrowButton(int32 direction,BRect rect,const BRect & updateRect)243 FakeScrollBar::_DrawArrowButton(int32 direction, BRect rect,
244 const BRect& updateRect)
245 {
246 if (!updateRect.Intersects(rect))
247 return;
248
249 uint32 flags = 0;
250
251 rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
252 B_LIGHTEN_1_TINT);
253
254 be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor,
255 flags, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
256
257 rect.InsetBy(-1, -1);
258 be_control_look->DrawArrowShape(this, rect, updateRect,
259 baseColor, direction, flags, B_DARKEN_MAX_TINT);
260 }
261