xref: /haiku/src/preferences/appearance/FakeScrollBar.cpp (revision f9b1a47fa329a440024cfcb45a82841ff6961f42)
1928ffe6dSJohn Scipione /*
2928ffe6dSJohn Scipione  *  Copyright 2010-2012 Haiku, Inc. All rights reserved.
3928ffe6dSJohn Scipione  *  Distributed under the terms of the MIT license.
4928ffe6dSJohn Scipione  *
5928ffe6dSJohn Scipione  *	Authors:
6928ffe6dSJohn Scipione  *		DarkWyrm <bpmagic@columbus.rr.com>
7928ffe6dSJohn Scipione  *		John Scipione <jscipione@gmail.com>
8928ffe6dSJohn Scipione  */
9928ffe6dSJohn Scipione 
10928ffe6dSJohn Scipione 
11928ffe6dSJohn Scipione #include "FakeScrollBar.h"
12928ffe6dSJohn Scipione 
13928ffe6dSJohn Scipione #include <Box.h>
14928ffe6dSJohn Scipione #include <ControlLook.h>
15928ffe6dSJohn Scipione #include <Message.h>
16928ffe6dSJohn Scipione #include <ScrollBar.h>
17928ffe6dSJohn Scipione #include <Shape.h>
18928ffe6dSJohn Scipione #include <Size.h>
19928ffe6dSJohn Scipione #include <Window.h>
20928ffe6dSJohn Scipione 
21928ffe6dSJohn Scipione 
22928ffe6dSJohn Scipione typedef enum {
23928ffe6dSJohn Scipione 	ARROW_LEFT = 0,
24928ffe6dSJohn Scipione 	ARROW_RIGHT,
25928ffe6dSJohn Scipione 	ARROW_UP,
26928ffe6dSJohn Scipione 	ARROW_DOWN,
27928ffe6dSJohn Scipione 	ARROW_NONE
28928ffe6dSJohn Scipione } arrow_direction;
29928ffe6dSJohn Scipione 
30928ffe6dSJohn Scipione 
31928ffe6dSJohn Scipione FakeScrollBar::FakeScrollBar(bool drawArrows, bool doubleArrows,
32b5446310SJohn Scipione 	BMessage* message)
33928ffe6dSJohn Scipione 	:
3412a7abb6SJohn Scipione 	BControl("FakeScrollBar", NULL, message, B_WILL_DRAW | B_NAVIGABLE),
35928ffe6dSJohn Scipione 	fDrawArrows(drawArrows),
36b5446310SJohn Scipione 	fDoubleArrows(doubleArrows)
37928ffe6dSJohn Scipione {
38928ffe6dSJohn Scipione 	SetExplicitMinSize(BSize(160, 20));
39928ffe6dSJohn Scipione 	SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 20));
40928ffe6dSJohn Scipione }
41928ffe6dSJohn Scipione 
42928ffe6dSJohn Scipione 
43928ffe6dSJohn Scipione FakeScrollBar::~FakeScrollBar(void)
44928ffe6dSJohn Scipione {
45928ffe6dSJohn Scipione }
46928ffe6dSJohn Scipione 
47928ffe6dSJohn Scipione 
48928ffe6dSJohn Scipione void
49928ffe6dSJohn Scipione FakeScrollBar::Draw(BRect updateRect)
50928ffe6dSJohn Scipione {
51928ffe6dSJohn Scipione 	BRect bounds = Bounds();
52928ffe6dSJohn Scipione 
53928ffe6dSJohn Scipione 	rgb_color normal = ui_color(B_PANEL_BACKGROUND_COLOR);
54928ffe6dSJohn Scipione 
5512a7abb6SJohn Scipione 	if (IsFocus()) {
5612a7abb6SJohn Scipione 		// draw the focus indicator
5712a7abb6SJohn Scipione 		SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
5812a7abb6SJohn Scipione 		StrokeRect(bounds);
5912a7abb6SJohn Scipione 		bounds.InsetBy(1.0, 1.0);
6012a7abb6SJohn Scipione 
6112a7abb6SJohn Scipione 		// Draw the selected border (1px)
62928ffe6dSJohn Scipione 		if (Value() == B_CONTROL_ON)
63928ffe6dSJohn Scipione 			SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
64928ffe6dSJohn Scipione 		else
65928ffe6dSJohn Scipione 			SetHighColor(normal);
66928ffe6dSJohn Scipione 
6712a7abb6SJohn Scipione 		StrokeRect(bounds);
6812a7abb6SJohn Scipione 		bounds.InsetBy(1.0, 1.0);
6912a7abb6SJohn Scipione 	} else {
70928ffe6dSJohn Scipione 		// Draw the selected border (2px)
7112a7abb6SJohn Scipione 		if (Value() == B_CONTROL_ON)
7212a7abb6SJohn Scipione 			SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
7312a7abb6SJohn Scipione 		else
7412a7abb6SJohn Scipione 			SetHighColor(normal);
7512a7abb6SJohn Scipione 
76928ffe6dSJohn Scipione 		StrokeRect(bounds);
77928ffe6dSJohn Scipione 		bounds.InsetBy(1.0, 1.0);
78928ffe6dSJohn Scipione 		StrokeRect(bounds);
79928ffe6dSJohn Scipione 		bounds.InsetBy(1.0, 1.0);
8012a7abb6SJohn Scipione 	}
81928ffe6dSJohn Scipione 
82928ffe6dSJohn Scipione 	// draw a gap (1px)
83928ffe6dSJohn Scipione 	SetHighColor(normal);
84928ffe6dSJohn Scipione 	StrokeRect(bounds);
85928ffe6dSJohn Scipione 	bounds.InsetBy(1.0, 1.0);
86928ffe6dSJohn Scipione 
87928ffe6dSJohn Scipione 	// draw a border around control (1px)
88928ffe6dSJohn Scipione 	SetHighColor(tint_color(normal, B_DARKEN_1_TINT));
89928ffe6dSJohn Scipione 	StrokeRect(bounds);
90928ffe6dSJohn Scipione 	bounds.InsetBy(1.0, 1.0);
91928ffe6dSJohn Scipione 
92928ffe6dSJohn Scipione 	BRect thumbBG = bounds;
93928ffe6dSJohn Scipione 	BRect bgRect = bounds;
94928ffe6dSJohn Scipione 
95928ffe6dSJohn Scipione 	if (fDrawArrows) {
96928ffe6dSJohn Scipione 		// draw arrows
97928ffe6dSJohn Scipione 		SetDrawingMode(B_OP_OVER);
98928ffe6dSJohn Scipione 
99928ffe6dSJohn Scipione 		BRect buttonFrame(bounds.left, bounds.top,
100928ffe6dSJohn Scipione 			bounds.left + bounds.Height(), bounds.bottom);
101928ffe6dSJohn Scipione 
102*f9b1a47fSRyan Leavengood 		_DrawArrowButton(ARROW_LEFT, buttonFrame, updateRect);
103928ffe6dSJohn Scipione 
104928ffe6dSJohn Scipione 		if (fDoubleArrows) {
105928ffe6dSJohn Scipione 			buttonFrame.OffsetBy(bounds.Height() + 1, 0.0);
106*f9b1a47fSRyan Leavengood 			_DrawArrowButton(ARROW_RIGHT, buttonFrame,
107928ffe6dSJohn Scipione 				updateRect);
108928ffe6dSJohn Scipione 
109928ffe6dSJohn Scipione 			buttonFrame.OffsetTo(bounds.right - ((bounds.Height() * 2) + 1),
110928ffe6dSJohn Scipione 				bounds.top);
111*f9b1a47fSRyan Leavengood 			_DrawArrowButton(ARROW_LEFT, buttonFrame,
112928ffe6dSJohn Scipione 				updateRect);
113928ffe6dSJohn Scipione 
114928ffe6dSJohn Scipione 			thumbBG.left += bounds.Height() * 2 + 2;
115928ffe6dSJohn Scipione 			thumbBG.right -= bounds.Height() * 2 + 2;
116928ffe6dSJohn Scipione 		} else {
117928ffe6dSJohn Scipione 			thumbBG.left += bounds.Height() + 1;
118928ffe6dSJohn Scipione 			thumbBG.right -= bounds.Height() + 1;
119928ffe6dSJohn Scipione 		}
120928ffe6dSJohn Scipione 
121928ffe6dSJohn Scipione 		buttonFrame.OffsetTo(bounds.right - bounds.Height(), bounds.top);
122*f9b1a47fSRyan Leavengood 		_DrawArrowButton(ARROW_RIGHT, buttonFrame, updateRect);
123928ffe6dSJohn Scipione 
124928ffe6dSJohn Scipione 		SetDrawingMode(B_OP_COPY);
125928ffe6dSJohn Scipione 
126928ffe6dSJohn Scipione 		bgRect = bounds.InsetByCopy(48, 0);
127928ffe6dSJohn Scipione 	} else
128928ffe6dSJohn Scipione 		bgRect = bounds.InsetByCopy(16, 0);
129928ffe6dSJohn Scipione 
130928ffe6dSJohn Scipione 	// fill background besides the thumb
131928ffe6dSJohn Scipione 	BRect leftOfThumb(thumbBG.left, thumbBG.top, bgRect.left - 1,
132928ffe6dSJohn Scipione 		thumbBG.bottom);
133928ffe6dSJohn Scipione 	BRect rightOfThumb(bgRect.right + 1, thumbBG.top, thumbBG.right,
134928ffe6dSJohn Scipione 		thumbBG.bottom);
135928ffe6dSJohn Scipione 
136928ffe6dSJohn Scipione 	be_control_look->DrawScrollBarBackground(this, leftOfThumb,
137928ffe6dSJohn Scipione 		rightOfThumb, updateRect, normal, 0, B_HORIZONTAL);
138928ffe6dSJohn Scipione 
139928ffe6dSJohn Scipione 	// Draw scroll thumb
140928ffe6dSJohn Scipione 
141928ffe6dSJohn Scipione 	// fill the clickable surface of the thumb
142928ffe6dSJohn Scipione 	be_control_look->DrawButtonBackground(this, bgRect, updateRect,
143928ffe6dSJohn Scipione 		normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
144928ffe6dSJohn Scipione }
145928ffe6dSJohn Scipione 
146928ffe6dSJohn Scipione 
147928ffe6dSJohn Scipione void
148928ffe6dSJohn Scipione FakeScrollBar::MouseDown(BPoint point)
149928ffe6dSJohn Scipione {
150928ffe6dSJohn Scipione 	BControl::MouseDown(point);
151928ffe6dSJohn Scipione }
152928ffe6dSJohn Scipione 
153928ffe6dSJohn Scipione 
154928ffe6dSJohn Scipione void
155928ffe6dSJohn Scipione FakeScrollBar::MouseMoved(BPoint point, uint32 transit,
156928ffe6dSJohn Scipione 	const BMessage* message)
157928ffe6dSJohn Scipione {
158928ffe6dSJohn Scipione 	BControl::MouseMoved(point, transit, message);
159928ffe6dSJohn Scipione }
160928ffe6dSJohn Scipione 
161928ffe6dSJohn Scipione 
162928ffe6dSJohn Scipione void
163928ffe6dSJohn Scipione FakeScrollBar::MouseUp(BPoint point)
164928ffe6dSJohn Scipione {
165928ffe6dSJohn Scipione 	SetValue(B_CONTROL_ON);
166928ffe6dSJohn Scipione 	Invoke();
167928ffe6dSJohn Scipione 
168928ffe6dSJohn Scipione 	Invalidate();
169928ffe6dSJohn Scipione 
170928ffe6dSJohn Scipione 	BControl::MouseUp(point);
171928ffe6dSJohn Scipione }
172928ffe6dSJohn Scipione 
173928ffe6dSJohn Scipione 
174928ffe6dSJohn Scipione void
175928ffe6dSJohn Scipione FakeScrollBar::SetValue(int32 value)
176928ffe6dSJohn Scipione {
177928ffe6dSJohn Scipione 	if (value != Value()) {
178928ffe6dSJohn Scipione 		BControl::SetValueNoUpdate(value);
179928ffe6dSJohn Scipione 		Invalidate();
180928ffe6dSJohn Scipione 	}
181928ffe6dSJohn Scipione 
182928ffe6dSJohn Scipione 	if (!value)
183928ffe6dSJohn Scipione 		return;
184928ffe6dSJohn Scipione 
185928ffe6dSJohn Scipione 	BView* parent = Parent();
186928ffe6dSJohn Scipione 	BView* child = NULL;
187928ffe6dSJohn Scipione 
188928ffe6dSJohn Scipione 	if (parent != NULL) {
189928ffe6dSJohn Scipione 		// If the parent is a BBox, the group parent is the parent of the BBox
190928ffe6dSJohn Scipione 		BBox* box = dynamic_cast<BBox*>(parent);
191928ffe6dSJohn Scipione 
192928ffe6dSJohn Scipione 		if (box && box->LabelView() == this)
193928ffe6dSJohn Scipione 			parent = box->Parent();
194928ffe6dSJohn Scipione 
195928ffe6dSJohn Scipione 		if (parent != NULL) {
196928ffe6dSJohn Scipione 			BBox* box = dynamic_cast<BBox*>(parent);
197928ffe6dSJohn Scipione 
198928ffe6dSJohn Scipione 			// If the parent is a BBox, skip the label if there is one
199928ffe6dSJohn Scipione 			if (box && box->LabelView())
200928ffe6dSJohn Scipione 				child = parent->ChildAt(1);
201928ffe6dSJohn Scipione 			else
202928ffe6dSJohn Scipione 				child = parent->ChildAt(0);
203928ffe6dSJohn Scipione 		} else
204928ffe6dSJohn Scipione 			child = Window()->ChildAt(0);
205928ffe6dSJohn Scipione 	} else if (Window())
206928ffe6dSJohn Scipione 		child = Window()->ChildAt(0);
207928ffe6dSJohn Scipione 
208928ffe6dSJohn Scipione 	while (child) {
209928ffe6dSJohn Scipione 		FakeScrollBar* scrollbar = dynamic_cast<FakeScrollBar*>(child);
210928ffe6dSJohn Scipione 
211928ffe6dSJohn Scipione 		if (scrollbar != NULL && (scrollbar != this))
212928ffe6dSJohn Scipione 			scrollbar->SetValue(B_CONTROL_OFF);
213928ffe6dSJohn Scipione 		else {
214928ffe6dSJohn Scipione 			// If the child is a BBox, check if the label is a scrollbarbutton
215928ffe6dSJohn Scipione 			BBox* box = dynamic_cast<BBox*>(child);
216928ffe6dSJohn Scipione 
217928ffe6dSJohn Scipione 			if (box && box->LabelView()) {
218928ffe6dSJohn Scipione 				scrollbar = dynamic_cast<FakeScrollBar*>(box->LabelView());
219928ffe6dSJohn Scipione 
220928ffe6dSJohn Scipione 				if (scrollbar != NULL && (scrollbar != this))
221928ffe6dSJohn Scipione 					scrollbar->SetValue(B_CONTROL_OFF);
222928ffe6dSJohn Scipione 			}
223928ffe6dSJohn Scipione 		}
224928ffe6dSJohn Scipione 
225928ffe6dSJohn Scipione 		child = child->NextSibling();
226928ffe6dSJohn Scipione 	}
227928ffe6dSJohn Scipione 
228928ffe6dSJohn Scipione 	//ASSERT(Value() == B_CONTROL_ON);
229928ffe6dSJohn Scipione }
230928ffe6dSJohn Scipione 
231928ffe6dSJohn Scipione 
232928ffe6dSJohn Scipione //	#pragma mark -
233928ffe6dSJohn Scipione 
234928ffe6dSJohn Scipione 
235928ffe6dSJohn Scipione void
23668c70f9bSJohn Scipione FakeScrollBar::SetDoubleArrows(bool doubleArrows)
237928ffe6dSJohn Scipione {
23868c70f9bSJohn Scipione 	fDoubleArrows = doubleArrows;
239928ffe6dSJohn Scipione 	Invalidate();
240928ffe6dSJohn Scipione }
241928ffe6dSJohn Scipione 
242928ffe6dSJohn Scipione 
243928ffe6dSJohn Scipione void
24468c70f9bSJohn Scipione FakeScrollBar::SetKnobStyle(uint32 knobStyle)
245928ffe6dSJohn Scipione {
24668c70f9bSJohn Scipione 	fKnobStyle = knobStyle;
247928ffe6dSJohn Scipione 	Invalidate();
248928ffe6dSJohn Scipione }
249928ffe6dSJohn Scipione 
250928ffe6dSJohn Scipione 
251928ffe6dSJohn Scipione void
252928ffe6dSJohn Scipione FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info)
253928ffe6dSJohn Scipione {
254928ffe6dSJohn Scipione 	fDoubleArrows = info.double_arrows;
255928ffe6dSJohn Scipione 	fKnobStyle = info.knob;
256928ffe6dSJohn Scipione 	Invalidate();
257928ffe6dSJohn Scipione }
258928ffe6dSJohn Scipione 
259928ffe6dSJohn Scipione 
260928ffe6dSJohn Scipione //	#pragma mark -
261928ffe6dSJohn Scipione 
262928ffe6dSJohn Scipione 
263928ffe6dSJohn Scipione void
264*f9b1a47fSRyan Leavengood FakeScrollBar::_DrawArrowButton(int32 direction, BRect rect,
265928ffe6dSJohn Scipione 	const BRect& updateRect)
266928ffe6dSJohn Scipione {
267*f9b1a47fSRyan Leavengood 	if (!updateRect.Intersects(rect))
268928ffe6dSJohn Scipione 		return;
269928ffe6dSJohn Scipione 
270*f9b1a47fSRyan Leavengood 	uint32 flags = 0;
271928ffe6dSJohn Scipione 
272*f9b1a47fSRyan Leavengood 	rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
273*f9b1a47fSRyan Leavengood 		B_LIGHTEN_1_TINT);
274928ffe6dSJohn Scipione 
275*f9b1a47fSRyan Leavengood 	be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor,
276*f9b1a47fSRyan Leavengood 		flags, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
277928ffe6dSJohn Scipione 
278*f9b1a47fSRyan Leavengood 	rect.InsetBy(-1, -1);
279*f9b1a47fSRyan Leavengood 	be_control_look->DrawArrowShape(this, rect, updateRect,
280*f9b1a47fSRyan Leavengood 		baseColor, direction, flags, B_DARKEN_MAX_TINT);
281928ffe6dSJohn Scipione }
282