/* * Copyright 2005, Jérôme Duval. All rights reserved. * Distributed under the terms of the MIT License. * * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) */ #include #include #include "TrackSlider.h" #include "icon_button.h" TrackSlider::TrackSlider(BRect rect, const char *title, BMessage *msg, uint32 resizeFlags) : BControl(rect, "slider", NULL, msg, resizeFlags, B_WILL_DRAW | B_FRAME_EVENTS), leftBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8), rightBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8), leftThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8), rightThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8), fLeftTime(0), fRightTime(1000000), fMainTime(0), fTotalTime(1000000), fLeftTracking(false), fRightTracking(false), fMainTracking(false) { fFont.SetSize(8.0); fFont.SetFlags(B_DISABLE_ANTIALIASING); int32 numFamilies = count_font_families(); for (int32 i = 0; i < numFamilies; i++ ) { font_family family; uint32 flags; if ((get_font_family(i, &family, &flags) == B_OK) && (strcmp(family, "Baskerville") == 0)) { fFont.SetFamilyAndFace(family, B_REGULAR_FACE); break; } } leftBitmap.SetBits(kLeftTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8); rightBitmap.SetBits(kRightTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8); leftThumbBitmap.SetBits(kLeftThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8); rightThumbBitmap.SetBits(kRightThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8); fRight = Bounds().right - kLeftRightTrackSliderWidth; if (fTotalTime == 0) { fLeftX = 14; fRightX = fRight; fPositionX = 15; } else { fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); } } TrackSlider::~TrackSlider() { } void TrackSlider::AttachedToWindow() { BControl::AttachedToWindow(); SetViewColor(B_TRANSPARENT_COLOR); } #define SLIDER_BASE 10 void TrackSlider::Draw(BRect updateRect) { SetHighColor(189,186,189); StrokeLine(BPoint(11,SLIDER_BASE+1), BPoint(fRight,SLIDER_BASE+1)); SetHighColor(0,0,0); StrokeLine(BPoint(11,SLIDER_BASE+2), BPoint(fRight,SLIDER_BASE+2)); SetHighColor(255,255,255); StrokeLine(BPoint(11,SLIDER_BASE+17), BPoint(fRight,SLIDER_BASE+17)); SetHighColor(231,227,231); StrokeLine(BPoint(11,SLIDER_BASE+18), BPoint(fRight,SLIDER_BASE+18)); SetDrawingMode(B_OP_OVER); SetHighColor(216,216,216); FillRect(BRect(0,1,fPositionX < 18 ? 18 : fPositionX-26,SLIDER_BASE)); FillRect(BRect(fPositionX < 18 ? 65 : fPositionX > fRight - 3 ? fRight : fPositionX+26,0,Bounds().right,SLIDER_BASE)); FillRect(BRect(0,0,Bounds().right,0)); FillRect(BRect(0,SLIDER_BASE+18,Bounds().right,SLIDER_BASE+21)); FillRect(BRect(0,0,10,SLIDER_BASE+21)); FillRect(BRect(Bounds().right - 10,0,Bounds().right,SLIDER_BASE+21)); SetLowColor(HighColor()); BPoint leftPoint(5,SLIDER_BASE+1); DrawBitmapAsync(&leftBitmap, BRect(BPoint(0,0), kLeftRightTrackSliderSize - BPoint(5,0)), BRect(leftPoint, leftPoint+kLeftRightTrackSliderSize-BPoint(5,0))); BPoint rightPoint(fRight + 1,SLIDER_BASE+1); DrawBitmapAsync(&rightBitmap, BRect(BPoint(5,0), kLeftRightTrackSliderSize), BRect(rightPoint, rightPoint+kLeftRightTrackSliderSize-BPoint(5,0))); SetHighColor(153,153,153); FillRect(BRect(11,SLIDER_BASE+3,fLeftX-9,SLIDER_BASE+16)); FillRect(BRect(fRightX+9,SLIDER_BASE+3,fRight,SLIDER_BASE+16)); if (fLeftX>19) { StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+3),BPoint(fLeftX-6,SLIDER_BASE+3)); StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+4),BPoint(fLeftX-7,SLIDER_BASE+4)); StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+5),BPoint(fLeftX-8,SLIDER_BASE+5)); StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+16),BPoint(fLeftX-6,SLIDER_BASE+16)); StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+15),BPoint(fLeftX-7,SLIDER_BASE+15)); StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+14),BPoint(fLeftX-8,SLIDER_BASE+14)); } if (fRightX < fRight - 5) { StrokeLine(BPoint(fRightX+5,SLIDER_BASE+3),BPoint(fRightX+8,SLIDER_BASE+3)); StrokeLine(BPoint(fRightX+7,SLIDER_BASE+4),BPoint(fRightX+8,SLIDER_BASE+4)); StrokeLine(BPoint(fRightX+8,SLIDER_BASE+5),BPoint(fRightX+8,SLIDER_BASE+6)); StrokeLine(BPoint(fRightX+8,SLIDER_BASE+13),BPoint(fRightX+8,SLIDER_BASE+14)); StrokeLine(BPoint(fRightX+5,SLIDER_BASE+16),BPoint(fRightX+8,SLIDER_BASE+16)); StrokeLine(BPoint(fRightX+7,SLIDER_BASE+15),BPoint(fRightX+8,SLIDER_BASE+15)); } SetHighColor(144,186,136); FillRect(BRect(fLeftX+1,SLIDER_BASE+3,fRightX,SLIDER_BASE+4)); FillRect(BRect(fLeftX+1,SLIDER_BASE+5,fLeftX+2,SLIDER_BASE+16)); SetHighColor(171,221,161); FillRect(BRect(fLeftX+3,SLIDER_BASE+5,fRightX,SLIDER_BASE+16)); int i = 17; int j = 18; SetHighColor(128,128,128); for (; i fRight - 23) counterX = fRight - 23; BeginLineArray(30); if (!isTracking) { AddLine(BPoint(counterX-24,SLIDER_BASE+1), BPoint(counterX+24,SLIDER_BASE+1), gray); AddLine(BPoint(counterX+25,SLIDER_BASE+1), BPoint(counterX+25,SLIDER_BASE-8), gray); AddLine(BPoint(counterX-25,SLIDER_BASE+1), BPoint(counterX-25,SLIDER_BASE-9), white); AddLine(BPoint(counterX-24,SLIDER_BASE-9), BPoint(counterX+25,SLIDER_BASE-9), white); SetHighColor(216,216,216); } else { AddLine(BPoint(counterX-24,SLIDER_BASE+1), BPoint(counterX+24,SLIDER_BASE+1), blue); AddLine(BPoint(counterX+25,SLIDER_BASE+1), BPoint(counterX+25,SLIDER_BASE-9), blue2); AddLine(BPoint(counterX-25,SLIDER_BASE+1), BPoint(counterX-25,SLIDER_BASE-9), blue2); AddLine(BPoint(counterX-24,SLIDER_BASE-9), BPoint(counterX+24,SLIDER_BASE-9), blue2); SetHighColor(48,48,241); } EndLineArray(); FillRect(BRect(counterX-24,SLIDER_BASE-8,counterX+24,SLIDER_BASE)); SetDrawingMode(B_OP_COPY); if (isTracking) SetHighColor(255,255,255); else SetHighColor(0,0,0); SetLowColor(ViewColor()); SetFont(&fFont); char string[12]; TimeToString(timestamp, string); DrawString(string, BPoint(counterX-22, SLIDER_BASE-1)); } void TrackSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message) { if (!IsTracking()) return; uint32 mouseButtons; BPoint where; GetMouse(&where, &mouseButtons, true); // button not pressed, exit if (! (mouseButtons & B_PRIMARY_MOUSE_BUTTON)) { Invoke(); SetTracking(false); } UpdatePosition(point); } void TrackSlider::MouseDown(BPoint point) { if (!Bounds().InsetBySelf(2,2).Contains(point)) return; UpdatePosition(point); SetTracking(true); SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY| B_LOCK_WINDOW_FOCUS); } void TrackSlider::MouseUp(BPoint point) { if (!IsTracking()) return; if (Bounds().InsetBySelf(2,2).Contains(point)) { UpdatePosition(point); } fLeftTracking = fRightTracking = fMainTracking = false; Invoke(); SetTracking(false); Draw(Bounds()); Flush(); } void TrackSlider::UpdatePosition(BPoint point) { BRect leftRect(fLeftX-9, SLIDER_BASE+3, fLeftX, SLIDER_BASE+16); BRect rightRect(fRightX, SLIDER_BASE+3, fRightX+9, SLIDER_BASE+16); if (!(fRightTracking || fMainTracking) && (fLeftTracking || ((point.x < fPositionX-4) && leftRect.Contains(point)))) { if (!IsTracking()) fLastX = point.x - fLeftX; fLeftX = MIN(MAX(point.x - fLastX, 15), fRight); fLeftTime = (bigtime_t)(MAX(MIN((fLeftX - 15) / (fRight - 14),1), 0) * fTotalTime); fLeftTracking = true; BMessage msg = *Message(); msg.AddInt64("left", fLeftTime); if (fPositionX < fLeftX) { fPositionX = fLeftX + 1; fMainTime = fLeftTime; msg.AddInt64("main", fMainTime); if (fRightX < fPositionX) { fRightX = fPositionX; fRightTime = fMainTime; msg.AddInt64("right", fRightTime); } } Invoke(&msg); //printf("fLeftPos : %Ld\n", fLeftTime); } else if (!fMainTracking && (fRightTracking || ((point.x > fPositionX+4) && rightRect.Contains(point)))) { if (!IsTracking()) fLastX = point.x - fRightX; fRightX = MIN(MAX(point.x - fLastX, 15), fRight); fRightTime = (bigtime_t)(MAX(MIN((fRightX - 15) / (fRight - 14),1), 0) * fTotalTime); fRightTracking = true; BMessage msg = *Message(); msg.AddInt64("right", fRightTime); if (fPositionX > fRightX) { fPositionX = fRightX; fMainTime = fRightTime; msg.AddInt64("main", fMainTime); if (fLeftX > fPositionX) { fLeftX = fPositionX - 1; fLeftTime = fMainTime; msg.AddInt64("left", fLeftTime); } } Invoke(&msg); //printf("fRightPos : %Ld\n", fRightTime); } else { fPositionX = MIN(MAX(point.x, 15), fRight); fMainTime = (bigtime_t)(MAX(MIN((fPositionX - 15) / (fRight - 14),1), 0) * fTotalTime); fMainTracking = true; BMessage msg = *Message(); msg.AddInt64("main", fMainTime); if (fRightX < fPositionX) { fRightX = fPositionX; fRightTime = fMainTime; msg.AddInt64("right", fRightTime); } else if (fLeftX > fPositionX) { fLeftX = fPositionX - 1; fLeftTime = fMainTime; msg.AddInt64("left", fLeftTime); } Invoke(&msg); //printf("fPosition : %Ld\n", fMainTime); } Draw(Bounds()); Flush(); } void TrackSlider::TimeToString(bigtime_t timestamp, char *string) { uint32 hours = timestamp / 3600000000LL; timestamp -= hours * 3600000000LL; uint32 minutes = timestamp / 60000000LL; timestamp -= minutes * 60000000LL; uint32 seconds = timestamp / 1000000LL; timestamp -= seconds * 1000000LL; uint32 centiseconds = timestamp / 10000LL; sprintf(string, "%02ld:%02ld:%02ld:%02ld", hours, minutes, seconds, centiseconds); } void TrackSlider::SetMainTime(bigtime_t timestamp, bool reset) { fMainTime = timestamp; fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); if (reset) { fRightTime = fTotalTime; fLeftTime = 0; fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); } Invalidate(); } void TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset) { fTotalTime = timestamp; if (reset) { fMainTime = 0; fRightTime = fTotalTime; fLeftTime = 0; } fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); Invalidate(); } void TrackSlider::ResetMainTime() { fMainTime = fLeftTime; fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); Invalidate(); } void TrackSlider::FrameResized(float width, float height) { fRight = Bounds().right - kLeftRightTrackSliderWidth; fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); Invalidate(); }