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