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