xref: /haiku/src/apps/soundrecorder/TrackSlider.cpp (revision 25a7b01d15612846f332751841da3579db313082)
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 
16 TrackSlider::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 
48 TrackSlider::~TrackSlider()
49 {
50 	delete fBitmap;
51 }
52 
53 
54 void
55 TrackSlider::AttachedToWindow()
56 {
57 	BControl::AttachedToWindow();
58 	SetViewColor(B_TRANSPARENT_COLOR);
59 	_InitBitmap();
60 	_RenderBitmap();
61 }
62 
63 
64 void
65 TrackSlider::_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 
98 void
99 TrackSlider::_RenderBitmap()
100 {
101 	/* rendering */
102 	if (fBitmap->Lock()) {
103 		fBitmapView->DrawX();
104 		fBitmap->Unlock();
105 	}
106 }
107 
108 
109 void
110 TrackSlider::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 
126 void
127 TrackSlider::_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 
189 void
190 TrackSlider::_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 
256 void
257 TrackSlider::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 
276 void
277 TrackSlider::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 
289 void
290 TrackSlider::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 
307 void
308 TrackSlider::_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 
401 void
402 TrackSlider::_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 
416 void
417 TrackSlider::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 
434 void
435 TrackSlider::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 
454 void
455 TrackSlider::ResetMainTime()
456 {
457 	fMainTime = fLeftTime;
458 	fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14)
459 		* ((double)fMainTime / fTotalTime);
460 	Invalidate();
461 }
462 
463 
464 void
465 TrackSlider::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 
480 SliderOffscreenView::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 
500 SliderOffscreenView::~SliderOffscreenView()
501 {
502 
503 }
504 
505 
506 void
507 SliderOffscreenView::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