xref: /haiku/src/apps/soundrecorder/TrackSlider.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
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 	SetDrawingMode(B_OP_COPY);
151 	if (isTracking)
152 		SetHighColor(255,255,255);
153 	else
154 		SetHighColor(0,0,0);
155 	SetLowColor(ViewColor());
156 
157 	SetFont(&fFont);
158 	DrawString(string, BPoint(counterX-halfwidth, SLIDER_BASE-1));
159 
160 }
161 
162 
163 void
164 TrackSlider::DrawMarker(float position)
165 {
166 	rgb_color black = {0,0,0};
167 	rgb_color rose = {255,152,152};
168 	rgb_color red = {255,0,0};
169 	rgb_color bordeau = {178,0,0};
170 	rgb_color white = {255,255,255};
171 
172 	BeginLineArray(30);
173 	AddLine(BPoint(position,SLIDER_BASE+7), BPoint(position-4,SLIDER_BASE+3), black);
174 	AddLine(BPoint(position-4,SLIDER_BASE+3), BPoint(position-4,SLIDER_BASE+1), black);
175 	AddLine(BPoint(position-4,SLIDER_BASE+1), BPoint(position+4,SLIDER_BASE+1), black);
176 	AddLine(BPoint(position+4,SLIDER_BASE+1), BPoint(position+4,SLIDER_BASE+3), black);
177 	AddLine(BPoint(position+4,SLIDER_BASE+3), BPoint(position,SLIDER_BASE+7), black);
178 
179 
180 	AddLine(BPoint(position-3,SLIDER_BASE+2), BPoint(position+3,SLIDER_BASE+2), rose);
181 	AddLine(BPoint(position-3,SLIDER_BASE+3), BPoint(position-1,SLIDER_BASE+5), rose);
182 
183 	AddLine(BPoint(position-2,SLIDER_BASE+3), BPoint(position+2,SLIDER_BASE+3), red);
184 	AddLine(BPoint(position-1,SLIDER_BASE+4), BPoint(position+1,SLIDER_BASE+4), red);
185 	AddLine(BPoint(position,SLIDER_BASE+5), BPoint(position,SLIDER_BASE+5), red);
186 
187 	AddLine(BPoint(position,SLIDER_BASE+6), BPoint(position+3,SLIDER_BASE+3), bordeau);
188 
189 	AddLine(BPoint(position,SLIDER_BASE+12), BPoint(position-4,SLIDER_BASE+16), black);
190 	AddLine(BPoint(position-4,SLIDER_BASE+16), BPoint(position-4,SLIDER_BASE+17), black);
191 	AddLine(BPoint(position-4,SLIDER_BASE+17), BPoint(position+4,SLIDER_BASE+17), black);
192 	AddLine(BPoint(position+4,SLIDER_BASE+17), BPoint(position+4,SLIDER_BASE+16), black);
193 	AddLine(BPoint(position+4,SLIDER_BASE+16), BPoint(position,SLIDER_BASE+12), black);
194 	AddLine(BPoint(position-4,SLIDER_BASE+18), BPoint(position+4,SLIDER_BASE+18), white);
195 
196 	AddLine(BPoint(position-3,SLIDER_BASE+16), BPoint(position,SLIDER_BASE+13), rose);
197 
198 	AddLine(BPoint(position-2,SLIDER_BASE+16), BPoint(position+2,SLIDER_BASE+16), red);
199 	AddLine(BPoint(position-1,SLIDER_BASE+15), BPoint(position+1,SLIDER_BASE+15), red);
200 	AddLine(BPoint(position,SLIDER_BASE+14), BPoint(position,SLIDER_BASE+14), red);
201 
202 	AddLine(BPoint(position+1,SLIDER_BASE+14), BPoint(position+3,SLIDER_BASE+16), bordeau);
203 
204 	EndLineArray();
205 }
206 
207 
208 void
209 TrackSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
210 {
211 	if (!IsTracking())
212 		return;
213 
214 	uint32 mouseButtons;
215 	BPoint where;
216 	GetMouse(&where, &mouseButtons, true);
217 
218 	// button not pressed, exit
219 	if (! (mouseButtons & B_PRIMARY_MOUSE_BUTTON)) {
220 		Invoke();
221 		SetTracking(false);
222 	}
223 
224 	UpdatePosition(point);
225 }
226 
227 
228 void
229 TrackSlider::MouseDown(BPoint point)
230 {
231 	if (!Bounds().InsetBySelf(2,2).Contains(point))
232 		return;
233 
234 	UpdatePosition(point);
235 	SetTracking(true);
236 	SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS);
237 }
238 
239 
240 void
241 TrackSlider::MouseUp(BPoint point)
242 {
243 	if (!IsTracking())
244 		return;
245 	if (Bounds().InsetBySelf(2,2).Contains(point)) {
246 		UpdatePosition(point);
247 	}
248 
249 	fLeftTracking = fRightTracking = fMainTracking = false;
250 
251 	Invoke();
252 	SetTracking(false);
253 	Draw(Bounds());
254 	Flush();
255 }
256 
257 
258 void
259 TrackSlider::UpdatePosition(BPoint point)
260 {
261 	BRect leftRect(fBitmapView->fLeftX-9, SLIDER_BASE+3, fBitmapView->fLeftX, SLIDER_BASE+16);
262 	BRect rightRect(fBitmapView->fRightX, SLIDER_BASE+3, fBitmapView->fRightX+9, SLIDER_BASE+16);
263 
264 	if (!(fRightTracking || fMainTracking) && (fLeftTracking || ((point.x < fBitmapView->fPositionX-4) && leftRect.Contains(point)))) {
265 		if (!IsTracking())
266 			fBitmapView->fLastX = point.x - fBitmapView->fLeftX;
267 		fBitmapView->fLeftX = MIN(MAX(point.x - fBitmapView->fLastX, 15), fBitmapView->fRight);
268 		fLeftTime = (bigtime_t)(MAX(MIN((fBitmapView->fLeftX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
269 		fLeftTracking = true;
270 
271 		BMessage msg = *Message();
272 		msg.AddInt64("left", fLeftTime);
273 
274 		if (fBitmapView->fPositionX < fBitmapView->fLeftX) {
275 			fBitmapView->fPositionX = fBitmapView->fLeftX + 1;
276 			fMainTime = fLeftTime;
277 			msg.AddInt64("main", fMainTime);
278 			if (fBitmapView->fRightX < fBitmapView->fPositionX) {
279 				fBitmapView->fRightX = fBitmapView->fPositionX;
280 				fRightTime = fMainTime;
281 				msg.AddInt64("right", fRightTime);
282 			}
283 		}
284 
285 		Invoke(&msg);
286 		RenderBitmap();
287 
288 		//printf("fLeftPos : %Ld\n", fLeftTime);
289 	} else if (!fMainTracking && (fRightTracking || ((point.x > fBitmapView->fPositionX+4) && rightRect.Contains(point)))) {
290 		if (!IsTracking())
291 			fBitmapView->fLastX = point.x - fBitmapView->fRightX;
292 		fBitmapView->fRightX = MIN(MAX(point.x - fBitmapView->fLastX, 15), fBitmapView->fRight);
293 		fRightTime = (bigtime_t)(MAX(MIN((fBitmapView->fRightX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
294 		fRightTracking = true;
295 
296 		BMessage msg = *Message();
297 		msg.AddInt64("right", fRightTime);
298 
299 		if (fBitmapView->fPositionX > fBitmapView->fRightX) {
300 			fBitmapView->fPositionX = fBitmapView->fRightX;
301 			fMainTime = fRightTime;
302 			msg.AddInt64("main", fMainTime);
303 			if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
304 				fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
305 				fLeftTime = fMainTime;
306 				msg.AddInt64("left", fLeftTime);
307 			}
308 		}
309 
310 		Invoke(&msg);
311 		RenderBitmap();
312 
313 		//printf("fRightPos : %Ld\n", fRightTime);
314 	} else {
315 		fBitmapView->fPositionX = MIN(MAX(point.x, 15), fBitmapView->fRight);
316 		fMainTime = (bigtime_t)(MAX(MIN((fBitmapView->fPositionX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
317 		fMainTracking = true;
318 
319 		BMessage msg = *Message();
320 		msg.AddInt64("main", fMainTime);
321 
322 		if (fBitmapView->fRightX < fBitmapView->fPositionX) {
323 			fBitmapView->fRightX = fBitmapView->fPositionX;
324 			fRightTime = fMainTime;
325 			msg.AddInt64("right", fRightTime);
326 			RenderBitmap();
327 		} else if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
328 			fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
329 			fLeftTime = fMainTime;
330 			msg.AddInt64("left", fLeftTime);
331 			RenderBitmap();
332 		}
333 
334 		Invoke(&msg);
335 		//printf("fPosition : %Ld\n", fMainTime);
336 	}
337 	Draw(Bounds());
338 	Flush();
339 }
340 
341 
342 void
343 TrackSlider::TimeToString(bigtime_t timestamp, char *string)
344 {
345 	uint32 hours = timestamp / 3600000000LL;
346 	timestamp -= hours * 3600000000LL;
347 	uint32 minutes = timestamp / 60000000LL;
348 	timestamp -= minutes * 60000000LL;
349 	uint32 seconds = timestamp / 1000000LL;
350 	timestamp -= seconds * 1000000LL;
351 	uint32 centiseconds = timestamp / 10000LL;
352 	sprintf(string, "%02ld:%02ld:%02ld:%02ld", hours, minutes, seconds, centiseconds);
353 
354 }
355 
356 
357 void
358 TrackSlider::SetMainTime(bigtime_t timestamp, bool reset)
359 {
360 	fMainTime = timestamp;
361 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
362 	if (reset) {
363 		fRightTime = fTotalTime;
364 		fLeftTime = 0;
365 		fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
366 		fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
367 	}
368 	Invalidate();
369 }
370 
371 void
372 TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset)
373 {
374 	fTotalTime = timestamp;
375 	if (reset) {
376 		fMainTime = 0;
377 		fRightTime = fTotalTime;
378 		fLeftTime = 0;
379 	}
380 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
381 	fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
382 	fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
383 	Invalidate();
384 }
385 
386 
387 void
388 TrackSlider::ResetMainTime()
389 {
390 	fMainTime = fLeftTime;
391 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
392 	Invalidate();
393 }
394 
395 
396 void
397 TrackSlider::FrameResized(float width, float height)
398 {
399 	fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth;
400 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
401 	InitBitmap();
402 	fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
403 	fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
404 	RenderBitmap();
405 	Invalidate();
406 }
407 
408 
409 SliderOffscreenView::SliderOffscreenView(BRect frame, char *name)
410 	: BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW),
411 	leftBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8),
412 	rightBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8),
413 	leftThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8),
414 	rightThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8)
415 {
416 	leftBitmap.SetBits(kLeftTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8);
417 	rightBitmap.SetBits(kRightTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8);
418 	leftThumbBitmap.SetBits(kLeftThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8);
419 	rightThumbBitmap.SetBits(kRightThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8);
420 }
421 
422 
423 SliderOffscreenView::~SliderOffscreenView()
424 {
425 
426 }
427 
428 
429 void
430 SliderOffscreenView::DrawX()
431 {
432 	SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
433 	FillRect(Bounds());
434 
435 	SetHighColor(189, 186, 189);
436 	StrokeLine(BPoint(11, SLIDER_BASE + 1), BPoint(fRight, SLIDER_BASE + 1));
437 	SetHighColor(0, 0, 0);
438 	StrokeLine(BPoint(11, SLIDER_BASE + 2), BPoint(fRight, SLIDER_BASE + 2));
439 	SetHighColor(255, 255, 255);
440 	StrokeLine(BPoint(11, SLIDER_BASE + 17), BPoint(fRight, SLIDER_BASE + 17));
441 	SetHighColor(231, 227, 231);
442 	StrokeLine(BPoint(11, SLIDER_BASE + 18), BPoint(fRight, SLIDER_BASE + 18));
443 
444 	SetDrawingMode(B_OP_OVER);
445 	SetLowColor(HighColor());
446 
447 	BPoint leftPoint(5, SLIDER_BASE + 1);
448 	DrawBitmapAsync(&leftBitmap, BRect(BPoint(0, 0), kLeftRightTrackSliderSize - BPoint(5, 0)),
449 		BRect(leftPoint, leftPoint + kLeftRightTrackSliderSize - BPoint(5, 0)));
450 	BPoint rightPoint(fRight + 1, SLIDER_BASE + 1);
451 	DrawBitmapAsync(&rightBitmap, BRect(BPoint(5, 0), kLeftRightTrackSliderSize),
452 		BRect(rightPoint, rightPoint + kLeftRightTrackSliderSize-BPoint(5, 0)));
453 
454 	SetHighColor(153, 153, 153);
455 	FillRect(BRect(11, SLIDER_BASE + 3, fLeftX - 9, SLIDER_BASE + 16));
456 	FillRect(BRect(fRightX + 9, SLIDER_BASE + 3, fRight, SLIDER_BASE + 16));
457 	if (fLeftX > 19) {
458 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 3), BPoint(fLeftX - 6, SLIDER_BASE + 3));
459 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 4), BPoint(fLeftX - 7, SLIDER_BASE + 4));
460 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 5), BPoint(fLeftX - 8, SLIDER_BASE + 5));
461 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 16), BPoint(fLeftX - 6, SLIDER_BASE + 16));
462 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 15), BPoint(fLeftX - 7, SLIDER_BASE + 15));
463 		StrokeLine(BPoint(fLeftX - 9, SLIDER_BASE + 14), BPoint(fLeftX - 8, SLIDER_BASE + 14));
464 	}
465 	if (fRightX < fRight - 5) {
466 		StrokeLine(BPoint(fRightX + 5, SLIDER_BASE + 3), BPoint(fRightX + 8, SLIDER_BASE + 3));
467 		StrokeLine(BPoint(fRightX + 7, SLIDER_BASE + 4), BPoint(fRightX + 8, SLIDER_BASE + 4));
468 		StrokeLine(BPoint(fRightX + 8, SLIDER_BASE + 5), BPoint(fRightX + 8, SLIDER_BASE + 6));
469 		StrokeLine(BPoint(fRightX + 8, SLIDER_BASE + 13), BPoint(fRightX + 8, SLIDER_BASE + 14));
470 		StrokeLine(BPoint(fRightX + 5, SLIDER_BASE + 16), BPoint(fRightX + 8, SLIDER_BASE + 16));
471 		StrokeLine(BPoint(fRightX + 7, SLIDER_BASE + 15), BPoint(fRightX + 8, SLIDER_BASE + 15));
472 	}
473 	SetHighColor(144, 186, 136);
474 	FillRect(BRect(fLeftX + 1, SLIDER_BASE + 3, fRightX, SLIDER_BASE + 4));
475 	FillRect(BRect(fLeftX + 1, SLIDER_BASE + 5, fLeftX + 2, SLIDER_BASE + 16));
476 	SetHighColor(171, 221, 161);
477 	FillRect(BRect(fLeftX + 3, SLIDER_BASE + 5, fRightX, SLIDER_BASE + 16));
478 
479 	int i = 17;
480 	int j = 18;
481 	SetHighColor(128, 128, 128);
482 	for (; i < fLeftX - 9; i += 6) {
483 		StrokeLine(BPoint(i, SLIDER_BASE + 7), BPoint(i, SLIDER_BASE + 13));
484 	}
485 	SetHighColor(179, 179, 179);
486 	for (; j < fLeftX - 9; j += 6) {
487 		StrokeLine(BPoint(j, SLIDER_BASE + 7), BPoint(j, SLIDER_BASE + 13));
488 	}
489 
490 	while (i <= fLeftX)
491 		i += 6;
492 	while (j <= fLeftX)
493 		j += 6;
494 
495 	SetHighColor(144, 186, 136);
496 	for (; i <= fRightX; i += 6) {
497 		StrokeLine(BPoint(i, SLIDER_BASE + 7), BPoint(i, SLIDER_BASE + 13));
498 	}
499 	SetHighColor(189, 244, 178);
500 	for (; j <= fRightX; j += 6) {
501 		StrokeLine(BPoint(j, SLIDER_BASE + 7), BPoint(j, SLIDER_BASE + 13));
502 	}
503 
504 	while (i <= fRightX + 9)
505 		i += 6;
506 	while (j <= fRightX + 9)
507 		j += 6;
508 
509 	SetHighColor(128, 128, 128);
510 	for (; i <= fRight + 1; i += 6) {
511 		StrokeLine(BPoint(i, SLIDER_BASE + 7), BPoint(i, SLIDER_BASE + 13));
512 	}
513 	SetHighColor(179, 179, 179);
514 	for (; j <= fRight + 1; j += 6) {
515 		StrokeLine(BPoint(j, SLIDER_BASE + 7), BPoint(j, SLIDER_BASE + 13));
516 	}
517 
518 	SetLowColor(HighColor());
519 
520 	BPoint leftThumbPoint(fLeftX - 8, SLIDER_BASE + 3);
521 	DrawBitmapAsync(&leftThumbBitmap, BRect(BPoint(0, 0), kLeftRightThumbSize - BPoint(7, 0)),
522 		BRect(leftThumbPoint, leftThumbPoint + kLeftRightThumbSize - BPoint(7, 0)));
523 
524 	BPoint rightThumbPoint(fRightX, SLIDER_BASE + 3);
525 	DrawBitmapAsync(&rightThumbBitmap, BRect(BPoint(6, 0), kLeftRightThumbSize),
526 		BRect(rightThumbPoint, rightThumbPoint + kLeftRightThumbSize-BPoint(6, 0)));
527 
528 	Sync();
529 }
530