xref: /haiku/src/preferences/appearance/FakeScrollBar.cpp (revision ecab567301ceaf3118144d69879adca0fec15c13)
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