2 * Copyright 2005, Jérôme Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers
13 #include "TrackSlider.h"
14 #include "icon_button.h"
16 TrackSlider::TrackSlider(BRect rect
, const char *title
, BMessage
*msg
,
19 BControl(rect
, "slider", NULL
, msg
, resizeFlags
, B_WILL_DRAW
26 fRightTracking(false),
32 fFont
.SetFlags(B_DISABLE_ANTIALIASING
);
34 int32 numFamilies
= count_font_families();
35 for (int32 i
= 0; i
< numFamilies
; i
++ ) {
38 if ((get_font_family(i
, &family
, &flags
) == B_OK
)
39 && (strcmp(family
, "Baskerville") == 0)) {
40 fFont
.SetFamilyAndFace(family
, B_REGULAR_FACE
);
48 TrackSlider::~TrackSlider()
55 TrackSlider::AttachedToWindow()
57 BControl::AttachedToWindow();
58 SetViewColor(B_TRANSPARENT_COLOR
);
65 TrackSlider::_InitBitmap()
68 fBitmap
->RemoveChild(fBitmapView
);
74 BRect rect
= Bounds();
76 fBitmap
= new BBitmap(rect
, BScreen().ColorSpace(), true);
78 fBitmapView
= new SliderOffscreenView(rect
.OffsetToSelf(B_ORIGIN
), "bitmapView");
79 fBitmap
->AddChild(fBitmapView
);
81 fBitmapView
->fRight
= Bounds().right
- kLeftRightTrackSliderWidth
;
82 if (fTotalTime
== 0) {
83 fBitmapView
->fLeftX
= 14;
84 fBitmapView
->fRightX
= fBitmapView
->fRight
;
85 fBitmapView
->fPositionX
= 15;
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
);
96 #define SLIDER_BASE 10
99 TrackSlider::_RenderBitmap()
102 if (fBitmap
->Lock()) {
103 fBitmapView
->DrawX();
110 TrackSlider::Draw(BRect updateRect
)
112 DrawBitmapAsync(fBitmap
, BPoint(0,0));
114 _DrawCounter(fMainTime
, fBitmapView
->fPositionX
, fMainTracking
);
116 _DrawCounter(fLeftTime
, fBitmapView
->fLeftX
, fLeftTracking
);
117 else if (fRightTracking
)
118 _DrawCounter(fRightTime
, fBitmapView
->fRightX
, fRightTracking
);
120 _DrawMarker(fBitmapView
->fPositionX
);
127 TrackSlider::_DrawCounter(bigtime_t timestamp
, float position
, bool isTracking
)
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};
137 _TimeToString(timestamp
, string
);
138 int32 halfwidth
= ((int32
)fFont
.StringWidth(string
)) / 2;
140 float counterX
= position
;
143 if (counterX
> fBitmapView
->fRight
- 23)
144 counterX
= fBitmapView
->fRight
- 23;
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);
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);
169 FillRect(BRect(counterX
-halfwidth
-3,SLIDER_BASE
-8,counterX
+halfwidth
+3,
173 SetDrawingMode(B_OP_OVER
);
175 SetDrawingMode(B_OP_COPY
);
178 SetHighColor(255,255,255);
181 SetLowColor(ViewColor());
184 DrawString(string
, BPoint(counterX
-halfwidth
, SLIDER_BASE
-1));
190 TrackSlider::_DrawMarker(float position
)
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};
199 AddLine(BPoint(position
,SLIDER_BASE
+7), BPoint(position
-4,SLIDER_BASE
+3),
201 AddLine(BPoint(position
-4,SLIDER_BASE
+3), BPoint(position
-4,SLIDER_BASE
+1),
203 AddLine(BPoint(position
-4,SLIDER_BASE
+1), BPoint(position
+4,SLIDER_BASE
+1),
205 AddLine(BPoint(position
+4,SLIDER_BASE
+1), BPoint(position
+4,SLIDER_BASE
+3),
207 AddLine(BPoint(position
+4,SLIDER_BASE
+3), BPoint(position
,SLIDER_BASE
+7),
211 AddLine(BPoint(position
-3,SLIDER_BASE
+2), BPoint(position
+3,SLIDER_BASE
+2),
213 AddLine(BPoint(position
-3,SLIDER_BASE
+3), BPoint(position
-1,SLIDER_BASE
+5),
216 AddLine(BPoint(position
-2,SLIDER_BASE
+3), BPoint(position
+2,SLIDER_BASE
+3),
218 AddLine(BPoint(position
-1,SLIDER_BASE
+4), BPoint(position
+1,SLIDER_BASE
+4),
220 AddLine(BPoint(position
,SLIDER_BASE
+5), BPoint(position
,SLIDER_BASE
+5),
223 AddLine(BPoint(position
,SLIDER_BASE
+6), BPoint(position
+3,SLIDER_BASE
+3),
226 AddLine(BPoint(position
,SLIDER_BASE
+12), BPoint(position
-4,SLIDER_BASE
+16),
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),
236 AddLine(BPoint(position
-4,SLIDER_BASE
+18), BPoint(position
+4,
237 SLIDER_BASE
+18), white
);
239 AddLine(BPoint(position
-3,SLIDER_BASE
+16), BPoint(position
,SLIDER_BASE
+13),
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
);
249 AddLine(BPoint(position
+1,SLIDER_BASE
+14), BPoint(position
+3,
250 SLIDER_BASE
+16), bordeau
);
257 TrackSlider::MouseMoved(BPoint point
, uint32 transit
, const BMessage
*message
)
264 GetMouse(&where
, &mouseButtons
, true);
266 // button not pressed, exit
267 if (! (mouseButtons
& B_PRIMARY_MOUSE_BUTTON
)) {
272 _UpdatePosition(point
);
277 TrackSlider::MouseDown(BPoint point
)
279 if (!Bounds().InsetBySelf(2,2).Contains(point
))
282 _UpdatePosition(point
);
284 SetMouseEventMask(B_POINTER_EVENTS
, B_NO_POINTER_HISTORY
285 | B_LOCK_WINDOW_FOCUS
);
290 TrackSlider::MouseUp(BPoint point
)
294 if (Bounds().InsetBySelf(2,2).Contains(point
)) {
295 _UpdatePosition(point
);
298 fLeftTracking
= fRightTracking
= fMainTracking
= false;
308 TrackSlider::_UpdatePosition(BPoint point
)
310 BRect
leftRect(fBitmapView
->fLeftX
-9, SLIDER_BASE
+3, fBitmapView
->fLeftX
,
312 BRect
rightRect(fBitmapView
->fRightX
, SLIDER_BASE
+3,
313 fBitmapView
->fRightX
+9, SLIDER_BASE
+16);
315 if (!(fRightTracking
|| fMainTracking
) && (fLeftTracking
316 || ((point
.x
< fBitmapView
->fPositionX
-4) && leftRect
.Contains(point
)))) {
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;
325 BMessage msg
= *Message();
326 msg
.AddInt64("left", fLeftTime
);
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
);
342 //printf("fLeftPos : %Ld\n", fLeftTime);
343 } else if (!fMainTracking
&& (fRightTracking
344 || ((point
.x
> fBitmapView
->fPositionX
+4)
345 && rightRect
.Contains(point
)))) {
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;
354 BMessage msg
= *Message();
355 msg
.AddInt64("right", fRightTime
);
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
);
371 //printf("fRightPos : %Ld\n", fRightTime);
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;
378 BMessage msg
= *Message();
379 msg
.AddInt64("main", fMainTime
);
381 if (fBitmapView
->fRightX
< fBitmapView
->fPositionX
) {
382 fBitmapView
->fRightX
= fBitmapView
->fPositionX
;
383 fRightTime
= fMainTime
;
384 msg
.AddInt64("right", fRightTime
);
386 } else if (fBitmapView
->fLeftX
> fBitmapView
->fPositionX
) {
387 fBitmapView
->fLeftX
= fBitmapView
->fPositionX
- 1;
388 fLeftTime
= fMainTime
;
389 msg
.AddInt64("left", fLeftTime
);
394 //printf("fPosition : %Ld\n", fMainTime);
402 TrackSlider::_TimeToString(bigtime_t timestamp
, char *string
)
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
);
417 TrackSlider::SetMainTime(bigtime_t timestamp
, bool reset
)
419 fMainTime
= timestamp
;
420 fBitmapView
->fPositionX
= 15 + (fBitmapView
->fRight
- 14)
421 * ((double)fMainTime
/ fTotalTime
);
423 fRightTime
= fTotalTime
;
425 fBitmapView
->fLeftX
= 14 + (fBitmapView
->fRight
- 15)
426 * ((double)fLeftTime
/ fTotalTime
);
427 fBitmapView
->fRightX
= 15 + (fBitmapView
->fRight
- 16)
428 * ((double)fRightTime
/ fTotalTime
);
435 TrackSlider::SetTotalTime(bigtime_t timestamp
, bool reset
)
437 fTotalTime
= timestamp
;
440 fRightTime
= fTotalTime
;
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
);
455 TrackSlider::ResetMainTime()
457 fMainTime
= fLeftTime
;
458 fBitmapView
->fPositionX
= 15 + (fBitmapView
->fRight
- 14)
459 * ((double)fMainTime
/ fTotalTime
);
465 TrackSlider::FrameResized(float width
, float height
)
467 fBitmapView
->fRight
= Bounds().right
- kLeftRightTrackSliderWidth
;
468 fBitmapView
->fPositionX
= 15 + (fBitmapView
->fRight
- 14)
469 * ((double)fMainTime
/ fTotalTime
);
471 fBitmapView
->fLeftX
= 14 + (fBitmapView
->fRight
- 15)
472 * ((double)fLeftTime
/ fTotalTime
);
473 fBitmapView
->fRightX
= 15 + (fBitmapView
->fRight
- 16)
474 * ((double)fRightTime
/ fTotalTime
);
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
)
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
);
500 SliderOffscreenView::~SliderOffscreenView()
507 SliderOffscreenView::DrawX()
509 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
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));
521 SetDrawingMode(B_OP_OVER
);
522 SetLowColor(HighColor());
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)));
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));
536 StrokeLine(BPoint(fLeftX
- 9, SLIDER_BASE
+ 3), BPoint(fLeftX
- 6,
538 StrokeLine(BPoint(fLeftX
- 9, SLIDER_BASE
+ 4), BPoint(fLeftX
- 7,
540 StrokeLine(BPoint(fLeftX
- 9, SLIDER_BASE
+ 5), BPoint(fLeftX
- 8,
542 StrokeLine(BPoint(fLeftX
- 9, SLIDER_BASE
+ 16), BPoint(fLeftX
- 6,
544 StrokeLine(BPoint(fLeftX
- 9, SLIDER_BASE
+ 15), BPoint(fLeftX
- 7,
546 StrokeLine(BPoint(fLeftX
- 9, SLIDER_BASE
+ 14), BPoint(fLeftX
- 8,
549 if (fRightX
< fRight
- 5) {
550 StrokeLine(BPoint(fRightX
+ 5, SLIDER_BASE
+ 3), BPoint(fRightX
+ 8,
552 StrokeLine(BPoint(fRightX
+ 7, SLIDER_BASE
+ 4), BPoint(fRightX
+ 8,
554 StrokeLine(BPoint(fRightX
+ 8, SLIDER_BASE
+ 5), BPoint(fRightX
+ 8,
556 StrokeLine(BPoint(fRightX
+ 8, SLIDER_BASE
+ 13), BPoint(fRightX
+ 8,
558 StrokeLine(BPoint(fRightX
+ 5, SLIDER_BASE
+ 16), BPoint(fRightX
+ 8,
560 StrokeLine(BPoint(fRightX
+ 7, SLIDER_BASE
+ 15), BPoint(fRightX
+ 8,
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));
571 SetHighColor(128, 128, 128);
572 for (; i
< fLeftX
- 9; i
+= 6) {
573 StrokeLine(BPoint(i
, SLIDER_BASE
+ 7), BPoint(i
, SLIDER_BASE
+ 13));
575 SetHighColor(179, 179, 179);
576 for (; j
< fLeftX
- 9; j
+= 6) {
577 StrokeLine(BPoint(j
, SLIDER_BASE
+ 7), BPoint(j
, SLIDER_BASE
+ 13));
585 SetHighColor(144, 186, 136);
586 for (; i
<= fRightX
; i
+= 6) {
587 StrokeLine(BPoint(i
, SLIDER_BASE
+ 7), BPoint(i
, SLIDER_BASE
+ 13));
589 SetHighColor(189, 244, 178);
590 for (; j
<= fRightX
; j
+= 6) {
591 StrokeLine(BPoint(j
, SLIDER_BASE
+ 7), BPoint(j
, SLIDER_BASE
+ 13));
594 while (i
<= fRightX
+ 9)
596 while (j
<= fRightX
+ 9)
599 SetHighColor(128, 128, 128);
600 for (; i
<= fRight
+ 1; i
+= 6) {
601 StrokeLine(BPoint(i
, SLIDER_BASE
+ 7), BPoint(i
, SLIDER_BASE
+ 13));
603 SetHighColor(179, 179, 179);
604 for (; j
<= fRight
+ 1; j
+= 6) {
605 StrokeLine(BPoint(j
, SLIDER_BASE
+ 7), BPoint(j
, SLIDER_BASE
+ 13));
608 SetLowColor(HighColor());
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)));
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)));