xref: /haiku/src/preferences/appearance/FakeScrollBar.cpp (revision 49c29fa933b65b5efe7897d45b5851b7b86b86b0)
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 
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 	// add some height to draw the ring around the scroll bar
39 	float height = B_H_SCROLL_BAR_HEIGHT + 8;
40 	SetExplicitMinSize(BSize(200, height));
41 	SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, height));
42 }
43 
44 
45 FakeScrollBar::~FakeScrollBar(void)
46 {
47 }
48 
49 
50 void
51 FakeScrollBar::Draw(BRect updateRect)
52 {
53 	BRect rect(Bounds());
54 
55 	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
56 
57 	uint32 flags = BControlLook::B_SCROLLABLE;
58 	if (IsFocus())
59 		flags |= BControlLook::B_FOCUSED;
60 
61 	if (Value() == B_CONTROL_ON)
62 		SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
63 	else
64 		SetHighColor(base);
65 
66 	// Draw the selected border (2px)
67 	StrokeRect(rect);
68 	rect.InsetBy(1, 1);
69 	StrokeRect(rect);
70 	rect.InsetBy(1, 1);
71 
72 	// draw a 1px gap
73 	SetHighColor(base);
74 	StrokeRect(rect);
75 	rect.InsetBy(1, 1);
76 
77 	// draw a 1px border around control
78 	SetHighColor(tint_color(base, B_DARKEN_1_TINT));
79 	StrokeRect(rect);
80 	rect.InsetBy(1, 1);
81 	SetHighColor(base);
82 
83 	be_control_look->DrawScrollBar(this, rect, updateRect, base,
84 		flags, B_HORIZONTAL, fDoubleArrows);
85 	float less = floorf(rect.Width() / 3); // thumb takes up 1/3 full width
86 	BRect thumbRect(rect.left + less, rect.top, rect.right - less, rect.bottom);
87 	be_control_look->DrawScrollBarThumb(this, rect, thumbRect, updateRect, base,
88 		flags, B_HORIZONTAL, fKnobStyle);
89 }
90 
91 
92 void
93 FakeScrollBar::MouseDown(BPoint point)
94 {
95 	BControl::MouseDown(point);
96 }
97 
98 
99 void
100 FakeScrollBar::MouseMoved(BPoint point, uint32 transit,
101 	const BMessage* message)
102 {
103 	BControl::MouseMoved(point, transit, message);
104 }
105 
106 
107 void
108 FakeScrollBar::MouseUp(BPoint point)
109 {
110 	SetValue(B_CONTROL_ON);
111 	Invoke();
112 
113 	Invalidate();
114 
115 	BControl::MouseUp(point);
116 }
117 
118 
119 void
120 FakeScrollBar::SetValue(int32 value)
121 {
122 	if (value != Value()) {
123 		BControl::SetValueNoUpdate(value);
124 		Invalidate();
125 	}
126 
127 	if (!value)
128 		return;
129 
130 	BView* parent = Parent();
131 	BView* child = NULL;
132 
133 	if (parent != NULL) {
134 		// If the parent is a BBox, the group parent is the parent of the BBox
135 		BBox* box = dynamic_cast<BBox*>(parent);
136 
137 		if (box && box->LabelView() == this)
138 			parent = box->Parent();
139 
140 		if (parent != NULL) {
141 			BBox* box = dynamic_cast<BBox*>(parent);
142 
143 			// If the parent is a BBox, skip the label if there is one
144 			if (box && box->LabelView())
145 				child = parent->ChildAt(1);
146 			else
147 				child = parent->ChildAt(0);
148 		} else
149 			child = Window()->ChildAt(0);
150 	} else if (Window())
151 		child = Window()->ChildAt(0);
152 
153 	while (child) {
154 		FakeScrollBar* scrollbar = dynamic_cast<FakeScrollBar*>(child);
155 
156 		if (scrollbar != NULL && (scrollbar != this))
157 			scrollbar->SetValue(B_CONTROL_OFF);
158 		else {
159 			// If the child is a BBox, check if the label is a scrollbarbutton
160 			BBox* box = dynamic_cast<BBox*>(child);
161 
162 			if (box && box->LabelView()) {
163 				scrollbar = dynamic_cast<FakeScrollBar*>(box->LabelView());
164 
165 				if (scrollbar != NULL && (scrollbar != this))
166 					scrollbar->SetValue(B_CONTROL_OFF);
167 			}
168 		}
169 
170 		child = child->NextSibling();
171 	}
172 
173 	//ASSERT(Value() == B_CONTROL_ON);
174 }
175 
176 
177 //	#pragma mark -
178 
179 
180 void
181 FakeScrollBar::SetDoubleArrows(bool doubleArrows)
182 {
183 	fDoubleArrows = doubleArrows;
184 	Invalidate();
185 }
186 
187 
188 void
189 FakeScrollBar::SetKnobStyle(uint32 knobStyle)
190 {
191 	fKnobStyle = knobStyle;
192 	Invalidate();
193 }
194 
195 
196 void
197 FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info)
198 {
199 	fDoubleArrows = info.double_arrows;
200 	fKnobStyle = info.knob;
201 	Invalidate();
202 }
203 
204 
205 //	#pragma mark -
206 
207 
208 void
209 FakeScrollBar::_DrawArrowButton(int32 direction, BRect rect,
210 	const BRect& updateRect)
211 {
212 	if (!updateRect.Intersects(rect))
213 		return;
214 
215 	uint32 flags = 0;
216 
217 	rgb_color baseColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
218 		B_LIGHTEN_1_TINT);
219 
220 	be_control_look->DrawButtonBackground(this, rect, updateRect, baseColor,
221 		flags, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
222 
223 	rect.InsetBy(-1, -1);
224 	be_control_look->DrawArrowShape(this, rect, updateRect,
225 		baseColor, direction, flags, B_DARKEN_MAX_TINT);
226 }
227