xref: /haiku/src/apps/icon-o-matic/generic/gui/popup_control/SliderView.cpp (revision 128277c969aa806add78941cd2972754c37a1572)
1 /*
2  * Copyright 2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  *		Ingo Weinhold <bonefish@cs.tu-berlin.de>
8  */
9 
10 #include "SliderView.h"
11 
12 #include <math.h>
13 #include <stdio.h>
14 
15 #include <Message.h>
16 #include <Window.h>
17 
18 #include "PopupSlider.h"
19 
20 // constructor
SliderView(PopupSlider * target,int32 min,int32 max,int32 value,const char * formatString)21 SliderView::SliderView(PopupSlider* target,
22 					   int32 min, int32 max, int32 value,
23 					   const char* formatString)
24 	: PopupView("slider"),
25 	  fTarget(target),
26 	  fFormatString(formatString),
27 	  fMin(min),
28 	  fMax(max),
29 	  fValue(value),
30 	  fButtonRect(0.0, 0.0, -1.0, -1.0),
31 	  fDragOffset(0.0)
32 {
33 	SetViewColor(B_TRANSPARENT_32_BIT);
34 	if (Max() < Min())
35 		SetMax(Min());
36 	BFont font;
37 	GetFont(&font);
38 	float buttonWidth, buttonHeight;
39 	GetSliderButtonDimensions(Max(), FormatString(), &font,
40 							  buttonWidth, buttonHeight);
41 
42 	fButtonRect.right = fButtonRect.left + buttonWidth;
43 	fButtonRect.bottom = fButtonRect.top + buttonHeight;
44 	float size = Max() - Min();
45 	if (size > 200)
46 		size = 200;
47 	ResizeTo(6.0 + fButtonRect.Width() + size + 6.0,
48 			 6.0 + fButtonRect.Height() + 6.0);
49 }
50 
51 // destructor
~SliderView()52 SliderView::~SliderView()
53 {
54 }
55 
56 // minimax
57 minimax
layoutprefs()58 SliderView::layoutprefs()
59 {
60 	mpm.mini.x = mpm.maxi.x = Bounds().Width() + 1.0;
61 	mpm.mini.y = mpm.maxi.y = Bounds().Height() + 1.0;
62 
63 	mpm.weight = 1.0;
64 
65 	return mpm;
66 }
67 
68 // layout
69 BRect
layout(BRect frame)70 SliderView::layout(BRect frame)
71 {
72 	MoveTo(frame.LeftTop());
73 	ResizeTo(frame.Width(), frame.Height());
74 	return Frame();
75 }
76 
77 // Draw
78 void
Draw(BRect updateRect)79 SliderView::Draw(BRect updateRect)
80 {
81 	fButtonRect.OffsetTo(ButtonOffset(), 6.0);
82 
83 	rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
84 	rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
85 	rgb_color lightShadow = tint_color(background, B_DARKEN_1_TINT);
86 	rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
87 	rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
88 
89 	BRect r(Bounds());
90 	BeginLineArray(24);
91 		// outer dark line
92 		AddLine(BPoint(r.left, r.bottom),
93 				BPoint(r.left, r.top), lightShadow);
94 		AddLine(BPoint(r.left + 1.0, r.top),
95 				BPoint(r.right, r.top), lightShadow);
96 		AddLine(BPoint(r.right, r.top + 1.0),
97 				BPoint(r.right, r.bottom), darkShadow);
98 		AddLine(BPoint(r.right - 1.0, r.bottom),
99 				BPoint(r.left + 1.0, r.bottom), darkShadow);
100 		// second line (raised)
101 		r.InsetBy(1.0, 1.0);
102 		AddLine(BPoint(r.left, r.bottom),
103 				BPoint(r.left, r.top), light);
104 		AddLine(BPoint(r.left + 1.0, r.top),
105 				BPoint(r.right, r.top), light);
106 		AddLine(BPoint(r.right, r.top + 1.0),
107 				BPoint(r.right, r.bottom), shadow);
108 		AddLine(BPoint(r.right - 1.0, r.bottom),
109 				BPoint(r.left + 1.0, r.bottom), shadow);
110 		// third line (normal)
111 		r.InsetBy(1.0, 1.0);
112 		AddLine(BPoint(r.left, r.bottom),
113 				BPoint(r.left, r.top), background);
114 		AddLine(BPoint(r.left + 1.0, r.top),
115 				BPoint(r.right, r.top), background);
116 		AddLine(BPoint(r.right, r.top + 1.0),
117 				BPoint(r.right, r.bottom), background);
118 		AddLine(BPoint(r.right - 1.0, r.bottom),
119 				BPoint(r.left + 1.0, r.bottom), background);
120 		// fourth line (normal)
121 		r.InsetBy(1.0, 1.0);
122 		AddLine(BPoint(r.left, r.bottom),
123 				BPoint(r.left, r.top), background);
124 		AddLine(BPoint(r.left + 1.0, r.top),
125 				BPoint(r.right, r.top), background);
126 		AddLine(BPoint(r.right, r.top + 1.0),
127 				BPoint(r.right, r.bottom), background);
128 		AddLine(BPoint(r.right - 1.0, r.bottom),
129 				BPoint(r.left + 1.0, r.bottom), background);
130 		// fifth line (depressed)
131 		r.InsetBy(1.0, 1.0);
132 		AddLine(BPoint(r.left, r.bottom),
133 				BPoint(r.left, r.top), lightShadow);
134 		AddLine(BPoint(r.left + 1.0, r.top),
135 				BPoint(r.right, r.top), lightShadow);
136 		AddLine(BPoint(r.right, r.top + 1.0),
137 				BPoint(r.right, r.bottom), light);
138 		AddLine(BPoint(r.right - 1.0, r.bottom),
139 				BPoint(r.left + 1.0, r.bottom), light);
140 		// fifth line (strongly depressed)
141 		r.InsetBy(1.0, 1.0);
142 		AddLine(BPoint(r.left, r.bottom),
143 				BPoint(r.left, r.top), darkShadow);
144 		AddLine(BPoint(r.left + 1.0, r.top),
145 				BPoint(r.right, r.top), darkShadow);
146 		AddLine(BPoint(r.right, r.top + 1.0),
147 				BPoint(r.right, r.bottom), shadow);
148 		AddLine(BPoint(r.right - 1.0, r.bottom),
149 				BPoint(r.left + 1.0, r.bottom), shadow);
150 	EndLineArray();
151 
152 	r.InsetBy(1.0, 1.0);
153 	SetLowColor(lightShadow);
154 	BRect leftOfButton(r.left + 1.0, r.top + 1.0, fButtonRect.left - 2.0, r.bottom);
155 	if (leftOfButton.IsValid())
156 		FillRect(leftOfButton, B_SOLID_LOW);
157 	BRect rightOfButton(fButtonRect.right + 2.0, r.top + 1.0,
158 						r.right, r.bottom);
159 	if (rightOfButton.IsValid())
160 		FillRect(rightOfButton, B_SOLID_LOW);
161 
162 	// inner shadow and knob out lines
163 	BeginLineArray(5);
164 		// shadow
165 		AddLine(BPoint(r.left, r.bottom),
166 				BPoint(r.left, r.top), shadow);
167 		AddLine(BPoint(r.left + 1.0, r.top),
168 				BPoint(r.right, r.top), shadow);
169 		// at knob
170 		if (fButtonRect.left == 6.0)
171 			AddLine(BPoint(fButtonRect.left - 1.0, r.top),
172 					BPoint(fButtonRect.left - 1.0, r.bottom), darkShadow);
173 		else
174 			AddLine(BPoint(fButtonRect.left - 1.0, r.top),
175 					BPoint(fButtonRect.left - 1.0, r.bottom), shadow);
176 		AddLine(BPoint(fButtonRect.left, fButtonRect.bottom + 1.0),
177 				BPoint(fButtonRect.right + 1.0, fButtonRect.bottom + 1.0), darkShadow);
178 		AddLine(BPoint(fButtonRect.right + 1.0, fButtonRect.bottom),
179 				BPoint(fButtonRect.right + 1.0, fButtonRect.top), darkShadow);
180 	EndLineArray();
181 
182 
183 	DrawSliderButton(this, fButtonRect, fValue, fFormatString.String(), fTarget->IsEnabled());
184 }
185 
186 // MouseUp
187 void
MouseUp(BPoint where)188 SliderView::MouseUp(BPoint where)
189 {
190 	PopupDone(false);
191 	fTarget->TriggerValueChanged(fTarget->Message());
192 }
193 
194 // MouseMoved
195 void
MouseMoved(BPoint where,uint32 transit,const BMessage * message)196 SliderView::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
197 {
198 	uint32 buttons = 0;
199 	if (BMessage* message = Window()->CurrentMessage()) {
200 		if (message->FindInt32("buttons", (int32*)&buttons) < B_OK)
201 			buttons = 0;
202 	}
203 
204 	if (buttons == 0) {
205 		MouseUp(where);
206 		return;
207 	}
208 
209 	SetValue(_ValueAt(where.x - fDragOffset - 6.0));
210 }
211 
212 // MessageReceived
213 void
MessageReceived(BMessage * message)214 SliderView::MessageReceived(BMessage* message)
215 {
216 	switch (message->what) {
217 		default:
218 			PopupView::MessageReceived(message);
219 			break;
220 	}
221 }
222 
223 // SetValue
224 void
SetValue(int32 value)225 SliderView::SetValue(int32 value)
226 {
227 	if (value < fMin)
228 		value = fMin;
229 	if (value > fMax)
230 		value = fMax;
231 	if (value != fValue) {
232 		fValue = value;
233 		fTarget->SetValue(value);
234 		Invalidate();
235 	}
236 }
237 
238 // Value
239 int32
Value() const240 SliderView::Value() const
241 {
242 	return fValue;
243 }
244 
245 // SetMin
246 void
SetMin(int32 min)247 SliderView::SetMin(int32 min)
248 {
249 	if (min != fMax) {
250 		fMin = min;
251 		if (fValue < fMin)
252 			SetValue(fMin);
253 		Invalidate();
254 	}
255 }
256 
257 // Min
258 int32
Min() const259 SliderView::Min() const
260 {
261 	return fMin;
262 }
263 
264 // SetMax
265 void
SetMax(int32 max)266 SliderView::SetMax(int32 max)
267 {
268 	if (max != fMax) {
269 		fMax = max;
270 		if (fValue > fMax)
271 			SetValue(fMax);
272 		Invalidate();
273 	}
274 }
275 
276 // Max
277 int32
Max() const278 SliderView::Max() const
279 {
280 	return fMax;
281 }
282 
283 // SetFormatString
284 void
SetFormatString(const char * formatString)285 SliderView::SetFormatString(const char* formatString)
286 {
287 	// TODO: check if formatString contains "%ld"
288 	fFormatString.SetTo(formatString);
289 }
290 
291 // FormatString
292 const char*
FormatString() const293 SliderView::FormatString() const
294 {
295 	return fFormatString.String();
296 }
297 
298 // SetDragOffset
299 void
SetDragOffset(float offset)300 SliderView::SetDragOffset(float offset)
301 {
302 	fDragOffset = offset;
303 }
304 
305 // ButtonOffset
306 float
ButtonOffset()307 SliderView::ButtonOffset()
308 {
309 //	float range = Bounds().Width() - 12.0 - fButtonRect.Width() + 1.0;
310 //	return 6.0 + range / (float)(fMax - fMin + 1) * (float)(fValue - fMin);
311 	float ratio = fTarget->DeScale((float)(fValue - fMin) / (float)(fMax - fMin));
312 	return 6.0 + ratio * (Bounds().Width() - 12.0 - fButtonRect.Width());
313 }
314 
315 // GetSliderButtonDimensions
316 void
GetSliderButtonDimensions(int32 max,const char * formatString,BFont * font,float & width,float & height)317 SliderView::GetSliderButtonDimensions(int32 max, const char* formatString,
318 									  BFont* font,
319 									  float& width, float& height)
320 {
321 	if (font) {
322 		char label[256];
323 		sprintf(label, formatString, max);
324 		font_height fh;
325 		font->GetHeight(&fh);
326 		// 4 pixels room on each side,
327 		// 1 pixel room at top and bottom
328 		width = 5.0 + ceilf(font->StringWidth(label)) + 5.0;
329 		height = 2.0 + ceilf(fh.ascent + fh.descent) + 2.0;
330 	}
331 }
332 
333 // DrawSliderButton
334 void
DrawSliderButton(BView * v,BRect r,int32 value,const char * formatString,bool enabled)335 SliderView::DrawSliderButton(BView* v, BRect r, int32 value,
336 							 const char* formatString, bool enabled)
337 {
338 	rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
339 	rgb_color light;
340 	rgb_color shadow;
341 	rgb_color button;
342 	rgb_color black;
343 	if (enabled) {
344 		light = tint_color(background, B_LIGHTEN_MAX_TINT);
345 		shadow = tint_color(background, B_DARKEN_1_TINT);
346 		button = tint_color(background, B_LIGHTEN_1_TINT);
347 		black = tint_color(background, B_DARKEN_MAX_TINT);
348 	} else {
349 		light = tint_color(background, B_LIGHTEN_1_TINT);
350 		shadow = tint_color(background, 1.1);
351 		button = tint_color(background, 0.8);
352 		black = tint_color(background, B_DISABLED_LABEL_TINT);
353 	}
354 	// border
355 	v->BeginLineArray(4);
356 		v->AddLine(BPoint(r.left, r.bottom),
357 				   BPoint(r.left, r.top), light);
358 		v->AddLine(BPoint(r.left + 1.0, r.top),
359 				   BPoint(r.right, r.top), light);
360 		v->AddLine(BPoint(r.right, r.top + 1.0),
361 				   BPoint(r.right, r.bottom), shadow);
362 		v->AddLine(BPoint(r.right - 1.0, r.bottom),
363 				   BPoint(r.left + 1.0, r.bottom), shadow);
364 	v->EndLineArray();
365 	// background & label
366 	r.InsetBy(1.0, 1.0);
367 	char label[256];
368 	sprintf(label, formatString, value);
369 	float width = v->StringWidth(label);
370 	font_height fh;
371 	v->GetFontHeight(&fh);
372 	BPoint textPoint((r.left + r.right) / 2.0 - width / 2.0,
373 					 (r.top + r.bottom) / 2.0 + fh.ascent / 2.0);
374 	v->SetHighColor(black);
375 	v->SetLowColor(button);
376 	v->FillRect(r, B_SOLID_LOW);
377 	v->DrawString(label, textPoint);
378 }
379 
380 // _ValueAt
381 int32
_ValueAt(float h)382 SliderView::_ValueAt(float h)
383 {
384 /*	return fMin + (int32)(((float)(fMax - fMin + 1) * h) /
385 		   (Bounds().Width() - fButtonRect.Width() - 12.0));*/
386 	float ratio = h / (Bounds().Width() - fButtonRect.Width() - 12.0);
387 	if (ratio < 0.0)
388 		ratio = 0.0;
389 	if (ratio > 1.0)
390 		ratio = 1.0;
391 	ratio = fTarget->Scale(ratio);
392 	return fMin + (int32)((fMax - fMin + 1) * ratio);
393 }
394 
395 
396 
397 
398