TrackSlider now uses an offscreen bitmap to avoid flickering on side thumbs

I'm not so pleased with the code, though it works nice on Dano at least. Still lot of graphics bugs on Haiku
DrawButton is now transparent
little refactoring in ScopeView


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17718 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2006-06-04 13:49:44 +00:00
parent e1aed9319d
commit 42f70a5d3d
4 changed files with 412 additions and 339 deletions

View File

@ -28,6 +28,7 @@ DrawButton::~DrawButton(void)
void
DrawButton::AttachedToWindow()
{
SetViewColor(B_TRANSPARENT_COLOR);
ReplaceTransparentColor(&fOn, Parent()->ViewColor());
ReplaceTransparentColor(&fOff, Parent()->ViewColor());
}

View File

@ -23,6 +23,7 @@ ScopeView::ScopeView(BRect rect, uint32 resizeFlags)
: BView(rect, "scope", resizeFlags, B_WILL_DRAW | B_FRAME_EVENTS),
fThreadId(-1),
fBitmap(NULL),
fBitmapView(NULL),
fIsRendering(false),
fMediaTrack(NULL),
fQuitting(false),
@ -31,14 +32,6 @@ ScopeView::ScopeView(BRect rect, uint32 resizeFlags)
fLeftTime(0),
fTotalTime(1000000)
{
fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true);
memset(fBitmap->Bits(), 0, fBitmap->BitsLength());
rect.OffsetToSelf(B_ORIGIN);
rect.right -= 2;
fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW);
fBitmap->AddChild(fBitmapView);
fRenderSem = create_sem(0, "scope rendering");
fHeight = Bounds().Height();
}
@ -54,6 +47,7 @@ void
ScopeView::AttachedToWindow()
{
SetViewColor(B_TRANSPARENT_COLOR);
InitBitmap();
Run();
}

View File

@ -7,16 +7,13 @@
#include <stdio.h>
#include <string.h>
#include <Screen.h>
#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)
{
@ -33,27 +30,13 @@ TrackSlider::TrackSlider(BRect rect, const char *title, BMessage *msg, uint32 re
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()
{
delete fBitmap;
}
@ -62,14 +45,392 @@ TrackSlider::AttachedToWindow()
{
BControl::AttachedToWindow();
SetViewColor(B_TRANSPARENT_COLOR);
InitBitmap();
RenderBitmap();
}
void
TrackSlider::InitBitmap()
{
if (fBitmapView) {
fBitmap->RemoveChild(fBitmapView);
delete fBitmapView;
}
if (fBitmap)
delete fBitmap;
BRect rect = Bounds();
fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true);
fBitmapView = new SliderOffscreenView(rect.OffsetToSelf(B_ORIGIN), "bitmapView");
fBitmap->AddChild(fBitmapView);
fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth;
if (fTotalTime == 0) {
fBitmapView->fLeftX = 14;
fBitmapView->fRightX = fBitmapView->fRight;
fBitmapView->fPositionX = 15;
} else {
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
}
}
#define SLIDER_BASE 10
void
TrackSlider::RenderBitmap()
{
/* rendering */
if (fBitmap->Lock()) {
fBitmapView->DrawX();
fBitmap->Unlock();
}
}
void
TrackSlider::Draw(BRect updateRect)
{
DrawBitmapAsync(fBitmap, BPoint(0,0));
DrawCounter(fMainTime, fBitmapView->fPositionX, fMainTracking);
if (fLeftTracking)
DrawCounter(fLeftTime, fBitmapView->fLeftX, fLeftTracking);
else if (fRightTracking)
DrawCounter(fRightTime, fBitmapView->fRightX, fRightTracking);
DrawMarker(fBitmapView->fPositionX);
Sync();
}
void
TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking)
{
// timecounter
rgb_color gray = {128,128,128};
rgb_color blue = {0,0,140};
rgb_color blue2 = {146,146,214};
rgb_color white = {255,255,255};
char string[12];
TimeToString(timestamp, string);
int32 halfwidth = ((int32)fFont.StringWidth(string)) / 2;
float counterX = position;
if (counterX < 39)
counterX = 39;
if (counterX > fBitmapView->fRight - 23)
counterX = fBitmapView->fRight - 23;
BeginLineArray(4);
if (!isTracking) {
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE+1), BPoint(counterX+halfwidth+3,SLIDER_BASE+1), gray);
AddLine(BPoint(counterX+halfwidth+4,SLIDER_BASE+1), BPoint(counterX+halfwidth+4,SLIDER_BASE-8), gray);
AddLine(BPoint(counterX-halfwidth-4,SLIDER_BASE+1), BPoint(counterX-halfwidth-4,SLIDER_BASE-9), white);
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE-9), BPoint(counterX+halfwidth+4,SLIDER_BASE-9), white);
SetHighColor(216,216,216);
} else {
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE+1), BPoint(counterX+halfwidth+3,SLIDER_BASE+1), blue);
AddLine(BPoint(counterX+halfwidth+4,SLIDER_BASE+1), BPoint(counterX+halfwidth+4,SLIDER_BASE-9), blue2);
AddLine(BPoint(counterX-halfwidth-4,SLIDER_BASE+1), BPoint(counterX-halfwidth-4,SLIDER_BASE-9), blue2);
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE-9), BPoint(counterX+halfwidth+3,SLIDER_BASE-9), blue2);
SetHighColor(48,48,241);
}
EndLineArray();
FillRect(BRect(counterX-halfwidth-3,SLIDER_BASE-8,counterX+halfwidth+3,SLIDER_BASE));
SetDrawingMode(B_OP_COPY);
if (isTracking)
SetHighColor(255,255,255);
else
SetHighColor(0,0,0);
SetLowColor(ViewColor());
SetFont(&fFont);
DrawString(string, BPoint(counterX-halfwidth, SLIDER_BASE-1));
}
void
TrackSlider::DrawMarker(float position)
{
rgb_color black = {0,0,0};
rgb_color rose = {255,152,152};
rgb_color red = {255,0,0};
rgb_color bordeau = {178,0,0};
rgb_color white = {255,255,255};
BeginLineArray(30);
AddLine(BPoint(position,SLIDER_BASE+7), BPoint(position-4,SLIDER_BASE+3), black);
AddLine(BPoint(position-4,SLIDER_BASE+3), BPoint(position-4,SLIDER_BASE+1), black);
AddLine(BPoint(position-4,SLIDER_BASE+1), BPoint(position+4,SLIDER_BASE+1), black);
AddLine(BPoint(position+4,SLIDER_BASE+1), BPoint(position+4,SLIDER_BASE+3), black);
AddLine(BPoint(position+4,SLIDER_BASE+3), BPoint(position,SLIDER_BASE+7), black);
AddLine(BPoint(position-3,SLIDER_BASE+2), BPoint(position+3,SLIDER_BASE+2), rose);
AddLine(BPoint(position-3,SLIDER_BASE+3), BPoint(position-1,SLIDER_BASE+5), rose);
AddLine(BPoint(position-2,SLIDER_BASE+3), BPoint(position+2,SLIDER_BASE+3), red);
AddLine(BPoint(position-1,SLIDER_BASE+4), BPoint(position+1,SLIDER_BASE+4), red);
AddLine(BPoint(position,SLIDER_BASE+5), BPoint(position,SLIDER_BASE+5), red);
AddLine(BPoint(position,SLIDER_BASE+6), BPoint(position+3,SLIDER_BASE+3), bordeau);
AddLine(BPoint(position,SLIDER_BASE+12), BPoint(position-4,SLIDER_BASE+16), black);
AddLine(BPoint(position-4,SLIDER_BASE+16), BPoint(position-4,SLIDER_BASE+17), black);
AddLine(BPoint(position-4,SLIDER_BASE+17), BPoint(position+4,SLIDER_BASE+17), black);
AddLine(BPoint(position+4,SLIDER_BASE+17), BPoint(position+4,SLIDER_BASE+16), black);
AddLine(BPoint(position+4,SLIDER_BASE+16), BPoint(position,SLIDER_BASE+12), black);
AddLine(BPoint(position-4,SLIDER_BASE+18), BPoint(position+4,SLIDER_BASE+18), white);
AddLine(BPoint(position-3,SLIDER_BASE+16), BPoint(position,SLIDER_BASE+13), rose);
AddLine(BPoint(position-2,SLIDER_BASE+16), BPoint(position+2,SLIDER_BASE+16), red);
AddLine(BPoint(position-1,SLIDER_BASE+15), BPoint(position+1,SLIDER_BASE+15), red);
AddLine(BPoint(position,SLIDER_BASE+14), BPoint(position,SLIDER_BASE+14), red);
AddLine(BPoint(position+1,SLIDER_BASE+14), BPoint(position+3,SLIDER_BASE+16), bordeau);
EndLineArray();
}
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(fBitmapView->fLeftX-9, SLIDER_BASE+3, fBitmapView->fLeftX, SLIDER_BASE+16);
BRect rightRect(fBitmapView->fRightX, SLIDER_BASE+3, fBitmapView->fRightX+9, SLIDER_BASE+16);
if (!(fRightTracking || fMainTracking) && (fLeftTracking || ((point.x < fBitmapView->fPositionX-4) && leftRect.Contains(point)))) {
if (!IsTracking())
fBitmapView->fLastX = point.x - fBitmapView->fLeftX;
fBitmapView->fLeftX = MIN(MAX(point.x - fBitmapView->fLastX, 15), fBitmapView->fRight);
fLeftTime = (bigtime_t)(MAX(MIN((fBitmapView->fLeftX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
fLeftTracking = true;
BMessage msg = *Message();
msg.AddInt64("left", fLeftTime);
if (fBitmapView->fPositionX < fBitmapView->fLeftX) {
fBitmapView->fPositionX = fBitmapView->fLeftX + 1;
fMainTime = fLeftTime;
msg.AddInt64("main", fMainTime);
if (fBitmapView->fRightX < fBitmapView->fPositionX) {
fBitmapView->fRightX = fBitmapView->fPositionX;
fRightTime = fMainTime;
msg.AddInt64("right", fRightTime);
}
}
Invoke(&msg);
RenderBitmap();
//printf("fLeftPos : %Ld\n", fLeftTime);
} else if (!fMainTracking && (fRightTracking || ((point.x > fBitmapView->fPositionX+4) && rightRect.Contains(point)))) {
if (!IsTracking())
fBitmapView->fLastX = point.x - fBitmapView->fRightX;
fBitmapView->fRightX = MIN(MAX(point.x - fBitmapView->fLastX, 15), fBitmapView->fRight);
fRightTime = (bigtime_t)(MAX(MIN((fBitmapView->fRightX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
fRightTracking = true;
BMessage msg = *Message();
msg.AddInt64("right", fRightTime);
if (fBitmapView->fPositionX > fBitmapView->fRightX) {
fBitmapView->fPositionX = fBitmapView->fRightX;
fMainTime = fRightTime;
msg.AddInt64("main", fMainTime);
if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
fLeftTime = fMainTime;
msg.AddInt64("left", fLeftTime);
}
}
Invoke(&msg);
RenderBitmap();
//printf("fRightPos : %Ld\n", fRightTime);
} else {
fBitmapView->fPositionX = MIN(MAX(point.x, 15), fBitmapView->fRight);
fMainTime = (bigtime_t)(MAX(MIN((fBitmapView->fPositionX - 15) / (fBitmapView->fRight - 14),1), 0) * fTotalTime);
fMainTracking = true;
BMessage msg = *Message();
msg.AddInt64("main", fMainTime);
if (fBitmapView->fRightX < fBitmapView->fPositionX) {
fBitmapView->fRightX = fBitmapView->fPositionX;
fRightTime = fMainTime;
msg.AddInt64("right", fRightTime);
RenderBitmap();
} else if (fBitmapView->fLeftX > fBitmapView->fPositionX) {
fBitmapView->fLeftX = fBitmapView->fPositionX - 1;
fLeftTime = fMainTime;
msg.AddInt64("left", fLeftTime);
RenderBitmap();
}
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;
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
if (reset) {
fRightTime = fTotalTime;
fLeftTime = 0;
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
}
Invalidate();
}
void
TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset)
{
fTotalTime = timestamp;
if (reset) {
fMainTime = 0;
fRightTime = fTotalTime;
fLeftTime = 0;
}
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
Invalidate();
}
void
TrackSlider::ResetMainTime()
{
fMainTime = fLeftTime;
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
Invalidate();
}
void
TrackSlider::FrameResized(float width, float height)
{
fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth;
fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime);
InitBitmap();
fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime);
fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime);
RenderBitmap();
Invalidate();
}
SliderOffscreenView::SliderOffscreenView(BRect frame, char *name)
: BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW),
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)
{
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);
}
SliderOffscreenView::~SliderOffscreenView()
{
}
void
SliderOffscreenView::DrawX()
{
SetHighColor(216,216,216);
FillRect(Bounds());
SetHighColor(189,186,189);
StrokeLine(BPoint(11,SLIDER_BASE+1), BPoint(fRight,SLIDER_BASE+1));
SetHighColor(0,0,0);
@ -78,17 +439,8 @@ TrackSlider::Draw(BRect updateRect)
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-22,SLIDER_BASE));
FillRect(BRect(fPositionX < 18 ? 65 : fPositionX > fRight - 3 ? fRight : fPositionX+22,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);
@ -97,7 +449,7 @@ TrackSlider::Draw(BRect updateRect)
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));
@ -172,298 +524,5 @@ TrackSlider::Draw(BRect updateRect)
DrawBitmapAsync(&rightThumbBitmap, BRect(BPoint(6,0), kLeftRightThumbSize),
BRect(rightThumbPoint, rightThumbPoint+kLeftRightThumbSize-BPoint(6,0)));
rgb_color black = {0,0,0};
rgb_color rose = {255,152,152};
rgb_color red = {255,0,0};
rgb_color bordeau = {178,0,0};
rgb_color white = {255,255,255};
DrawCounter(fMainTime, fPositionX, fMainTracking);
if (fLeftTracking)
DrawCounter(fLeftTime, fLeftX, fLeftTracking);
else if (fRightTracking)
DrawCounter(fRightTime, fRightX, fRightTracking);
BeginLineArray(30);
AddLine(BPoint(fPositionX,SLIDER_BASE+7), BPoint(fPositionX-4,SLIDER_BASE+3), black);
AddLine(BPoint(fPositionX-4,SLIDER_BASE+3), BPoint(fPositionX-4,SLIDER_BASE+1), black);
AddLine(BPoint(fPositionX-4,SLIDER_BASE+1), BPoint(fPositionX+4,SLIDER_BASE+1), black);
AddLine(BPoint(fPositionX+4,SLIDER_BASE+1), BPoint(fPositionX+4,SLIDER_BASE+3), black);
AddLine(BPoint(fPositionX+4,SLIDER_BASE+3), BPoint(fPositionX,SLIDER_BASE+7), black);
AddLine(BPoint(fPositionX-3,SLIDER_BASE+2), BPoint(fPositionX+3,SLIDER_BASE+2), rose);
AddLine(BPoint(fPositionX-3,SLIDER_BASE+3), BPoint(fPositionX-1,SLIDER_BASE+5), rose);
AddLine(BPoint(fPositionX-2,SLIDER_BASE+3), BPoint(fPositionX+2,SLIDER_BASE+3), red);
AddLine(BPoint(fPositionX-1,SLIDER_BASE+4), BPoint(fPositionX+1,SLIDER_BASE+4), red);
AddLine(BPoint(fPositionX,SLIDER_BASE+5), BPoint(fPositionX,SLIDER_BASE+5), red);
AddLine(BPoint(fPositionX,SLIDER_BASE+6), BPoint(fPositionX+3,SLIDER_BASE+3), bordeau);
AddLine(BPoint(fPositionX,SLIDER_BASE+12), BPoint(fPositionX-4,SLIDER_BASE+16), black);
AddLine(BPoint(fPositionX-4,SLIDER_BASE+16), BPoint(fPositionX-4,SLIDER_BASE+17), black);
AddLine(BPoint(fPositionX-4,SLIDER_BASE+17), BPoint(fPositionX+4,SLIDER_BASE+17), black);
AddLine(BPoint(fPositionX+4,SLIDER_BASE+17), BPoint(fPositionX+4,SLIDER_BASE+16), black);
AddLine(BPoint(fPositionX+4,SLIDER_BASE+16), BPoint(fPositionX,SLIDER_BASE+12), black);
AddLine(BPoint(fPositionX-4,SLIDER_BASE+18), BPoint(fPositionX+4,SLIDER_BASE+18), white);
AddLine(BPoint(fPositionX-3,SLIDER_BASE+16), BPoint(fPositionX,SLIDER_BASE+13), rose);
AddLine(BPoint(fPositionX-2,SLIDER_BASE+16), BPoint(fPositionX+2,SLIDER_BASE+16), red);
AddLine(BPoint(fPositionX-1,SLIDER_BASE+15), BPoint(fPositionX+1,SLIDER_BASE+15), red);
AddLine(BPoint(fPositionX,SLIDER_BASE+14), BPoint(fPositionX,SLIDER_BASE+14), red);
AddLine(BPoint(fPositionX+1,SLIDER_BASE+14), BPoint(fPositionX+3,SLIDER_BASE+16), bordeau);
EndLineArray();
Flush();
}
void
TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking)
{
// timecounter
rgb_color gray = {128,128,128};
rgb_color blue = {0,0,140};
rgb_color blue2 = {146,146,214};
rgb_color white = {255,255,255};
char string[12];
TimeToString(timestamp, string);
int32 halfwidth = ((int32)fFont.StringWidth(string)) / 2;
float counterX = position;
if (counterX < 39)
counterX = 39;
if (counterX > fRight - 23)
counterX = fRight - 23;
BeginLineArray(4);
if (!isTracking) {
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE+1), BPoint(counterX+halfwidth+3,SLIDER_BASE+1), gray);
AddLine(BPoint(counterX+halfwidth+4,SLIDER_BASE+1), BPoint(counterX+halfwidth+4,SLIDER_BASE-8), gray);
AddLine(BPoint(counterX-halfwidth-4,SLIDER_BASE+1), BPoint(counterX-halfwidth-4,SLIDER_BASE-9), white);
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE-9), BPoint(counterX+halfwidth+4,SLIDER_BASE-9), white);
SetHighColor(216,216,216);
} else {
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE+1), BPoint(counterX+halfwidth+3,SLIDER_BASE+1), blue);
AddLine(BPoint(counterX+halfwidth+4,SLIDER_BASE+1), BPoint(counterX+halfwidth+4,SLIDER_BASE-9), blue2);
AddLine(BPoint(counterX-halfwidth-4,SLIDER_BASE+1), BPoint(counterX-halfwidth-4,SLIDER_BASE-9), blue2);
AddLine(BPoint(counterX-halfwidth-3,SLIDER_BASE-9), BPoint(counterX+halfwidth+3,SLIDER_BASE-9), blue2);
SetHighColor(48,48,241);
}
EndLineArray();
FillRect(BRect(counterX-halfwidth-3,SLIDER_BASE-8,counterX+halfwidth+3,SLIDER_BASE));
SetDrawingMode(B_OP_COPY);
if (isTracking)
SetHighColor(255,255,255);
else
SetHighColor(0,0,0);
SetLowColor(ViewColor());
SetFont(&fFont);
DrawString(string, BPoint(counterX-halfwidth, 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();
Sync();
}

View File

@ -11,6 +11,23 @@
#include <Bitmap.h>
#include <Font.h>
class SliderOffscreenView : public BView {
public:
SliderOffscreenView(BRect frame, char *name);
virtual ~SliderOffscreenView();
virtual void DrawX();
BBitmap leftBitmap, rightBitmap;
BBitmap leftThumbBitmap, rightThumbBitmap;
float fRight;
float fLeftX;
float fRightX;
float fPositionX;
float fLastX;
};
class TrackSlider : public BControl
{
public:
@ -30,25 +47,27 @@ public:
virtual void FrameResized(float width, float height);
private:
void DrawCounter(bigtime_t timestamp, float position, bool isTracking);
void DrawMarker(float position);
void TimeToString(bigtime_t timestamp, char *string);
void UpdatePosition(BPoint point);
BBitmap leftBitmap, rightBitmap, leftThumbBitmap, rightThumbBitmap;
float fRight;
void InitBitmap();
void RenderBitmap();
bigtime_t fLeftTime;
bigtime_t fRightTime;
bigtime_t fMainTime;
bigtime_t fTotalTime;
float fPositionX;
float fLeftX;
float fRightX;
float fLastX;
bool fLeftTracking;
bool fRightTracking;
bool fMainTracking;
BFont fFont;
BBitmap *fBitmap;
SliderOffscreenView *fBitmapView;
};
#endif /* TRACKSLIDER_H */