xref: /haiku/src/apps/soundrecorder/TrackSlider.cpp (revision 3c6e2dd68577c34d93e17f19711f6245bf6d0915)
1 /*
2  * Copyright 2005, Jérôme Duval. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers)
6  */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <Screen.h>
11 
12 #include "TrackSlider.h"
13 #include "icon_button.h"
14 
15 TrackSlider::TrackSlider(BRect rect, const char *title, BMessage *msg, uint32 resizeFlags)
16 	: BControl(rect, "slider", NULL, msg, resizeFlags, B_WILL_DRAW | B_FRAME_EVENTS),
17 	fLeftTime(0), fRightTime(1000000), fMainTime(0), fTotalTime(1000000),
18 	fLeftTracking(false), fRightTracking(false), fMainTracking(false),
19 	fBitmap(NULL), fBitmapView(NULL)
20 {
21 	fFont.SetSize(8.0);
22 	fFont.SetFlags(B_DISABLE_ANTIALIASING);
23 
24 	int32 numFamilies = count_font_families();
25 	for (int32 i = 0; i < numFamilies; i++ ) {
26 		font_family family;
27 		uint32 flags;
28 		if ((get_font_family(i, &family, &flags) == B_OK)
29 			&& (strcmp(family, "Baskerville") == 0)) {
30 			fFont.SetFamilyAndFace(family, B_REGULAR_FACE);
31 			break;
32 		}
33 	}
34 
35 }
36 
37 
38 TrackSlider::~TrackSlider()
39 {
40 	delete fBitmap;
41 }
42 
43 
44 void
45 TrackSlider::AttachedToWindow()
46 {
47 	BControl::AttachedToWindow();
48 	SetViewColor(B_TRANSPARENT_COLOR);
49 	_InitBitmap();
50 	_RenderBitmap();
51 }
52 
53 
54 void
55 TrackSlider::_InitBitmap()
56 {
57 	if (fBitmapView) {
58 		fBitmap->RemoveChild(fBitmapView);
59 		delete fBitmapView;
60 	}
61 	if (fBitmap)
62 		delete fBitmap;
63 
64 	BRect rect = Bounds();
65 
66 	fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true);
67 
68 	fBitmapView = new SliderOffscreenView(rect.OffsetToSelf(B_ORIGIN), "bitmapView");
69 	fBitmap->AddChild(fBitmapView);
70 
71 	fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth;
72 	if (fTotalTime == 0) {
73 		fBitmapView->fLeftX = 14;
74 		fBitmapView->fRightX = fBitmapView->fRight;
75 		fBitmapView->fPositionX = 15;
76 	} else {
77 		fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
78 		fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
79 		fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
80 	}
81 }
82 
83 #define SLIDER_BASE 10
84 
85 void
86 TrackSlider::_RenderBitmap()
87 {
88 	/* rendering */
89 	if (fBitmap->Lock()) {
90 		fBitmapView->DrawX();
91 		fBitmap->Unlock();
92 	}
93 }
94 
95 
96 void
97 TrackSlider::Draw(BRect updateRect)
98 {
99 	DrawBitmapAsync(fBitmap, BPoint(0,0));
100 
101 	_DrawCounter(fMainTime, fBitmapView->fPositionX, fMainTracking);
102 	if (fLeftTracking)
103 		_DrawCounter(fLeftTime, fBitmapView->fLeftX, fLeftTracking);
104 	else if (fRightTracking)
105 		_DrawCounter(fRightTime, fBitmapView->fRightX, fRightTracking);
106 
107 	_DrawMarker(fBitmapView->fPositionX);
108 
109 	Sync();
110 }
111 
112 
113 void
114 TrackSlider::_DrawCounter(bigtime_t timestamp, float position, bool isTracking)
115 {
116 	// timecounter
117 
118 	rgb_color gray = {128,128,128};
119 	rgb_color blue = {0,0,140};
120 	rgb_color blue2 = {146,146,214};
121 	rgb_color white = {255,255,255};
122 
123 	char string[12];
124 	_TimeToString(timestamp, string);
125 	int32 halfwidth = ((int32)fFont.StringWidth(string)) / 2;
126 
127 	float counterX = position;
128 	if (counterX < 39)
129 		counterX = 39;
130 	if (counterX > fBitmapView->fRight - 23)
131 		counterX = fBitmapView->fRight - 23;
132 
133 	BeginLineArray(4);
134 	if (!isTracking) {
135 		AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE+1), BPoint(counterX+halfwidth+3,SLIDER_BASE+1), gray);
136 		AddLine(BPoint(counterX+halfwidth+4,SLIDER_BASE+1), BPoint(counterX+halfwidth+4,SLIDER_BASE-8), gray);
137 		AddLine(BPoint(counterX-halfwidth-4,SLIDER_BASE+1), BPoint(counterX-halfwidth-4,SLIDER_BASE-9), white);
138 		AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE-9), BPoint(counterX+halfwidth+4,SLIDER_BASE-9), white);
139 		SetHighColor(216,216,216);
140 	} else {
141 		AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE+1), BPoint(counterX+halfwidth+3,SLIDER_BASE+1), blue);
142 		AddLine(BPoint(counterX+halfwidth+4,SLIDER_BASE+1), BPoint(counterX+halfwidth+4,SLIDER_BASE-9), blue2);
143 		AddLine(BPoint(counterX-halfwidth-4,SLIDER_BASE+1), BPoint(counterX-halfwidth-4,SLIDER_BASE-9), blue2);
144 		AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE-9), BPoint(counterX+halfwidth+3,SLIDER_BASE-9), blue2);
145 		SetHighColor(48,48,241);
146 	}
147 	EndLineArray();
148 	FillRect(BRect(counterX-halfwidth-3,SLIDER_BASE-8,counterX+halfwidth+3,SLIDER_BASE));
149 
150 #ifdef __HAIKU__
151 	SetDrawingMode(B_OP_OVER);
152 #else
153 	SetDrawingMode(B_OP_COPY);
154 #endif
155 	if (isTracking)
156 		SetHighColor(255,255,255);
157 	else
158 		SetHighColor(0,0,0);
159 	SetLowColor(ViewColor());
160 
161 	SetFont(&fFont);
162 	DrawString(string, BPoint(counterX-halfwidth, SLIDER_BASE-1));
163 
164 }
165 
166 
167 void
168 TrackSlider::_DrawMarker(float position)
169 {
170 	rgb_color black = {0,0,0};
171 	rgb_color rose = {255,152,152};
172 	rgb_color red = {255,0,0};
173 	rgb_color bordeau = {178,0,0};
174 	rgb_color white = {255,255,255};
175 
176 	BeginLineArray(30);
177 	AddLine(BPoint(position,SLIDER_BASE+7), BPoint(position-4,SLIDER_BASE+3), black);
178 	AddLine(BPoint(position-4,SLIDER_BASE+3), BPoint(position-4,SLIDER_BASE+1), black);
179 	AddLine(BPoint(position-4,SLIDER_BASE+1), BPoint(position+4,SLIDER_BASE+1), black);
180 	AddLine(BPoint(position+4,SLIDER_BASE+1), BPoint(position+4,SLIDER_BASE+3), black);
181 	AddLine(BPoint(position+4,SLIDER_BASE+3), BPoint(position,SLIDER_BASE+7), black);
182 
183 
184 	AddLine(BPoint(position-3,SLIDER_BASE+2), BPoint(position+3,SLIDER_BASE+2), rose);
185 	AddLine(BPoint(position-3,SLIDER_BASE+3), BPoint(position-1,SLIDER_BASE+5), rose);
186 
187 	AddLine(BPoint(position-2,SLIDER_BASE+3), BPoint(position+2,SLIDER_BASE+3), red);
188 	AddLine(BPoint(position-1,SLIDER_BASE+4), BPoint(position+1,SLIDER_BASE+4), red);
189 	AddLine(BPoint(position,SLIDER_BASE+5), BPoint(position,SLIDER_BASE+5), red);
190 
191 	AddLine(BPoint(position,SLIDER_BASE+6), BPoint(position+3,SLIDER_BASE+3), bordeau);
192 
193 	AddLine(BPoint(position,SLIDER_BASE+12), BPoint(position-4,SLIDER_BASE+16), black);
194 	AddLine(BPoint(position-4,SLIDER_BASE+16), BPoint(position-4,SLIDER_BASE+17), black);
195 	AddLine(BPoint(position-4,SLIDER_BASE+17), BPoint(position+4,SLIDER_BASE+17), black);
196 	AddLine(BPoint(position+4,SLIDER_BASE+17), BPoint(position+4,SLIDER_BASE+16), black);
197 	AddLine(BPoint(position+4,SLIDER_BASE+16), BPoint(position,SLIDER_BASE+12), black);
198 	AddLine(BPoint(position-4,SLIDER_BASE+18), BPoint(position+4,SLIDER_BASE+18), white);
199 
200 	AddLine(BPoint(position-3,SLIDER_BASE+16), BPoint(position,SLIDER_BASE+13), rose);
201 
202 	AddLine(BPoint(position-2,SLIDER_BASE+16), BPoint(position+2,SLIDER_BASE+16), red);
203 	AddLine(BPoint(position-1,SLIDER_BASE+15), BPoint(position+1,SLIDER_BASE+15), red);
204 	AddLine(BPoint(position,SLIDER_BASE+14), BPoint(position,SLIDER_BASE+14), red);
205 
206 	AddLine(BPoint(position+1,SLIDER_BASE+14), BPoint(position+3,SLIDER_BASE+16), bordeau);
207 
208 	EndLineArray();
209 }
210 
211 
212 void
213 TrackSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
214 {
215 	if (!IsTracking())
216 		return;
217 
218 	uint32 mouseButtons;
219 	BPoint where;
220 	GetMouse(&where, &mouseButtons, true);
221 
222 	// button not pressed, exit
223 	if (! (mouseButtons & B_PRIMARY_MOUSE_BUTTON)) {
224 		Invoke();
225 		SetTracking(false);
226 	}
227 
228 	_UpdatePosition(point);
229 }
230 
231 
232 void
233 TrackSlider::MouseDown(BPoint point)
234 {
235 	if (!Bounds().InsetBySelf(2,2).Contains(point))
236 		return;
237 
238 	_UpdatePosition(point);
239 	SetTracking(true);
240 	SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
241 }
242 
243 
244 void
245 TrackSlider::MouseUp(BPoint point)
246 {
247 	if (!IsTracking())
248 		return;
249 	if (Bounds().InsetBySelf(2,2).Contains(point)) {
250 		_UpdatePosition(point);
251 	}
252 
253 	fLeftTracking = fRightTracking = fMainTracking = false;
254 
255 	Invoke();
256 	SetTracking(false);
257 	Draw(Bounds());
258 	Flush();
259 }
260 
261 
262 void
263 TrackSlider::_UpdatePosition(BPoint point)
264 {
265 	BRect leftRect(fBitmapView->fLeftX-9, SLIDER_BASE+3, fBitmapView->fLeftX, SLIDER_BASE+16);
266 	BRect rightRect(fBitmapView->fRightX, SLIDER_BASE+3, fBitmapView->fRightX+9, SLIDER_BASE+16);
267 
268 	if (!(fRightTracking || fMainTracking) && (fLeftTracking || ((point.x < fBitmapView->fPositionX-4) && leftRect.Contains(point)))) {
269 		if (!IsTracking())
270 			fBitmapView->fLastX = point.x - fBitmapView->fLeftX;
271 		fBitmapView->fLeftX = MIN(MAX(point.x - fBitmapView->fLastX, 15), fBitmapView->fRight);
272 		fLeftTime = (bigtime_t)(MAX(MIN((fBitmapView->fLeftX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
273 		fLeftTracking = true;
274 
275 		BMessage msg = *Message();
276 		msg.AddInt64("left", fLeftTime);
277 
278 		if (fBitmapView->fPositionX < fBitmapView->fLeftX) {
279 			fBitmapView->fPositionX = fBitmapView->fLeftX + 1;
280 			fMainTime = fLeftTime;
281 			msg.AddInt64("main", fMainTime);
282 			if (fBitmapView->fRightX < fBitmapView->fPositionX) {
283 				fBitmapView->fRightX = fBitmapView->fPositionX;
284 				fRightTime = fMainTime;
285 				msg.AddInt64("right", fRightTime);
286 			}
287 		}
288 
289 		Invoke(&msg);
290 		_RenderBitmap();
291 
292 		//printf("fLeftPos : %Ld\n", fLeftTime);
293 	} else if (!fMainTracking && (fRightTracking || ((point.x > fBitmapView->fPositionX+4) && rightRect.Contains(point)))) {
294 		if (!IsTracking())
295 			fBitmapView->fLastX = point.x - fBitmapView->fRightX;
296 		fBitmapView->fRightX = MIN(MAX(point.x - fBitmapView->fLastX, 15), fBitmapView->fRight);
297 		fRightTime = (bigtime_t)(MAX(MIN((fBitmapView->fRightX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
298 		fRightTracking = true;
299 
300 		BMessage msg = *Message();
301 		msg.AddInt64("right", fRightTime);
302 
303 		if (fBitmapView->fPositionX > fBitmapView->fRightX) {
304 			fBitmapView->fPositionX = fBitmapView->fRightX;
305 			fMainTime = fRightTime;
306 			msg.AddInt64("main", fMainTime);
307 			if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
308 				fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
309 				fLeftTime = fMainTime;
310 				msg.AddInt64("left", fLeftTime);
311 			}
312 		}
313 
314 		Invoke(&msg);
315 		_RenderBitmap();
316 
317 		//printf("fRightPos : %Ld\n", fRightTime);
318 	} else {
319 		fBitmapView->fPositionX = MIN(MAX(point.x, 15), fBitmapView->fRight);
320 		fMainTime = (bigtime_t)(MAX(MIN((fBitmapView->fPositionX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
321 		fMainTracking = true;
322 
323 		BMessage msg = *Message();
324 		msg.AddInt64("main", fMainTime);
325 
326 		if (fBitmapView->fRightX < fBitmapView->fPositionX) {
327 			fBitmapView->fRightX = fBitmapView->fPositionX;
328 			fRightTime = fMainTime;
329 			msg.AddInt64("right", fRightTime);
330 			_RenderBitmap();
331 		} else if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
332 			fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
333 			fLeftTime = fMainTime;
334 			msg.AddInt64("left", fLeftTime);
335 			_RenderBitmap();
336 		}
337 
338 		Invoke(&msg);
339 		//printf("fPosition : %Ld\n", fMainTime);
340 	}
341 	Draw(Bounds());
342 	Flush();
343 }
344 
345 
346 void
347 TrackSlider::_TimeToString(bigtime_t timestamp, char *string)
348 {
349 	uint32 hours = timestamp / 3600000000LL;
350 	timestamp -= hours * 3600000000LL;
351 	uint32 minutes = timestamp / 60000000LL;
352 	timestamp -= minutes * 60000000LL;
353 	uint32 seconds = timestamp / 1000000LL;
354 	timestamp -= seconds * 1000000LL;
355 	uint32 centiseconds = timestamp / 10000LL;
356 	sprintf(string, "%02ld:%02ld:%02ld:%02ld", hours, minutes, seconds, centiseconds);
357 
358 }
359 
360 
361 void
362 TrackSlider::SetMainTime(bigtime_t timestamp, bool reset)
363 {
364 	fMainTime = timestamp;
365 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
366 	if (reset) {
367 		fRightTime = fTotalTime;
368 		fLeftTime = 0;
369 		fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
370 		fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
371 		_RenderBitmap();
372 	}
373 	Invalidate();
374 }
375 
376 void
377 TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset)
378 {
379 	fTotalTime = timestamp;
380 	if (reset) {
381 		fMainTime = 0;
382 		fRightTime = fTotalTime;
383 		fLeftTime = 0;
384 	}
385 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
386 	fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
387 	fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
388 	_RenderBitmap();
389 	Invalidate();
390 }
391 
392 
393 void
394 TrackSlider::ResetMainTime()
395 {
396 	fMainTime = fLeftTime;
397 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
398 	Invalidate();
399 }
400 
401 
402 void
403 TrackSlider::FrameResized(float width, float height)
404 {
405 	fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth;
406 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
407 	_InitBitmap();
408 	fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
409 	fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
410 	_RenderBitmap();
411 	Invalidate();
412 }
413 
414 
415 SliderOffscreenView::SliderOffscreenView(BRect frame, char *name)
416 	: BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW),
417 	leftBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8),
418 	rightBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8),
419 	leftThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8),
420 	rightThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8)
421 {
422 	leftBitmap.SetBits(kLeftTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8);
423 	rightBitmap.SetBits(kRightTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8);
424 	leftThumbBitmap.SetBits(kLeftThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8);
425 	rightThumbBitmap.SetBits(kRightThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8);
426 }
427 
428 
429 SliderOffscreenView::~SliderOffscreenView()
430 {
431 
432 }
433 
434 
435 void
436 SliderOffscreenView::DrawX()
437 {
438 	SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
439 	FillRect(Bounds());
440 
441 	SetHighColor(189, 186, 189);
442 	StrokeLine(BPoint(11, SLIDER_BASE + 1), BPoint(fRight, SLIDER_BASE + 1));
443 	SetHighColor(0, 0, 0);
444 	StrokeLine(BPoint(11, SLIDER_BASE + 2), BPoint(fRight, SLIDER_BASE + 2));
445 	SetHighColor(255, 255, 255);
446 	StrokeLine(BPoint(11, SLIDER_BASE + 17), BPoint(fRight, SLIDER_BASE + 17));
447 	SetHighColor(231, 227, 231);
448 	StrokeLine(BPoint(11, SLIDER_BASE + 18), BPoint(fRight, SLIDER_BASE + 18));
449 
450 	SetDrawingMode(B_OP_OVER);
451 	SetLowColor(HighColor());
452 
453 	BPoint leftPoint(5, SLIDER_BASE + 1);
454 	DrawBitmapAsync(&leftBitmap, BRect(BPoint(0, 0), kLeftRightTrackSliderSize - BPoint(5, 0)),
455 		BRect(leftPoint, leftPoint + kLeftRightTrackSliderSize - BPoint(5, 0)));
456 	BPoint rightPoint(fRight + 1, SLIDER_BASE + 1);
457 	DrawBitmapAsync(&rightBitmap, BRect(BPoint(5, 0), kLeftRightTrackSliderSize),
458 		BRect(rightPoint, rightPoint + kLeftRightTrackSliderSize-BPoint(5, 0)));
459 
460 	SetHighColor(153, 153, 153);
461 	FillRect(BRect(11, SLIDER_BASE + 3, fLeftX - 9, SLIDER_BASE + 16));
462 	FillRect(BRect(fRightX + 9, SLIDER_BASE + 3, fRight, SLIDER_BASE + 16));
463 	if (fLeftX > 19) {
464 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 3), BPoint(fLeftX - 6, SLIDER_BASE + 3));
465 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 4), BPoint(fLeftX - 7, SLIDER_BASE + 4));
466 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 5), BPoint(fLeftX - 8, SLIDER_BASE + 5));
467 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 16), BPoint(fLeftX - 6, SLIDER_BASE + 16));
468 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 15), BPoint(fLeftX - 7, SLIDER_BASE + 15));
469 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 14), BPoint(fLeftX - 8, SLIDER_BASE + 14));
470 	}
471 	if (fRightX < fRight - 5) {
472 		StrokeLine(BPoint(fRightX + 5, SLIDER_BASE + 3), BPoint(fRightX + 8, SLIDER_BASE + 3));
473 		StrokeLine(BPoint(fRightX + 7, SLIDER_BASE + 4), BPoint(fRightX + 8, SLIDER_BASE + 4));
474 		StrokeLine(BPoint(fRightX + 8, SLIDER_BASE + 5), BPoint(fRightX + 8, SLIDER_BASE + 6));
475 		StrokeLine(BPoint(fRightX + 8, SLIDER_BASE + 13), BPoint(fRightX + 8, SLIDER_BASE + 14));
476 		StrokeLine(BPoint(fRightX + 5, SLIDER_BASE + 16), BPoint(fRightX + 8, SLIDER_BASE + 16));
477 		StrokeLine(BPoint(fRightX + 7, SLIDER_BASE + 15), BPoint(fRightX + 8, SLIDER_BASE + 15));
478 	}
479 	SetHighColor(144, 186, 136);
480 	FillRect(BRect(fLeftX + 1, SLIDER_BASE + 3, fRightX, SLIDER_BASE + 4));
481 	FillRect(BRect(fLeftX + 1, SLIDER_BASE + 5, fLeftX + 2, SLIDER_BASE + 16));
482 	SetHighColor(171, 221, 161);
483 	FillRect(BRect(fLeftX + 3, SLIDER_BASE + 5, fRightX, SLIDER_BASE + 16));
484 
485 	int i = 17;
486 	int j = 18;
487 	SetHighColor(128, 128, 128);
488 	for (; i < fLeftX - 9; i += 6) {
489 		StrokeLine(BPoint(i, SLIDER_BASE + 7), BPoint(i, SLIDER_BASE + 13));
490 	}
491 	SetHighColor(179, 179, 179);
492 	for (; j < fLeftX - 9; j += 6) {
493 		StrokeLine(BPoint(j, SLIDER_BASE + 7), BPoint(j, SLIDER_BASE + 13));
494 	}
495 
496 	while (i <= fLeftX)
497 		i += 6;
498 	while (j <= fLeftX)
499 		j += 6;
500 
501 	SetHighColor(144, 186, 136);
502 	for (; i <= fRightX; i += 6) {
503 		StrokeLine(BPoint(i, SLIDER_BASE + 7), BPoint(i, SLIDER_BASE + 13));
504 	}
505 	SetHighColor(189, 244, 178);
506 	for (; j <= fRightX; j += 6) {
507 		StrokeLine(BPoint(j, SLIDER_BASE + 7), BPoint(j, SLIDER_BASE + 13));
508 	}
509 
510 	while (i <= fRightX + 9)
511 		i += 6;
512 	while (j <= fRightX + 9)
513 		j += 6;
514 
515 	SetHighColor(128, 128, 128);
516 	for (; i <= fRight + 1; i += 6) {
517 		StrokeLine(BPoint(i, SLIDER_BASE + 7), BPoint(i, SLIDER_BASE + 13));
518 	}
519 	SetHighColor(179, 179, 179);
520 	for (; j <= fRight + 1; j += 6) {
521 		StrokeLine(BPoint(j, SLIDER_BASE + 7), BPoint(j, SLIDER_BASE + 13));
522 	}
523 
524 	SetLowColor(HighColor());
525 
526 	BPoint leftThumbPoint(fLeftX - 8, SLIDER_BASE + 3);
527 	DrawBitmapAsync(&leftThumbBitmap, BRect(BPoint(0, 0), kLeftRightThumbSize - BPoint(7, 0)),
528 		BRect(leftThumbPoint, leftThumbPoint + kLeftRightThumbSize - BPoint(7, 0)));
529 
530 	BPoint rightThumbPoint(fRightX, SLIDER_BASE + 3);
531 	DrawBitmapAsync(&rightThumbBitmap, BRect(BPoint(6, 0), kLeftRightThumbSize),
532 		BRect(rightThumbPoint, rightThumbPoint + kLeftRightThumbSize-BPoint(6, 0)));
533 
534 	Sync();
535 }
536