- Horizontal sliders work correctly.
- Only the active channel slider is highlighted now, unlike Beos's version. I like this more. - Added an (experimental) feature: when changing a slider's value with the mouse, its value is displayed (requested by Axel, can you check if it's what you wanted ? http://burton666.neoni.net/shots/channelslider.png ). There are still some problems with the calculations of coordinates, I'd like someone to review my code. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12496 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,10 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005, Haiku Inc. All Rights Reserved.
|
* Copyright 2005, Haiku Inc. All Rights Reserved.
|
||||||
|
* Author: Stefano Ceccherini ([email protected])
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Currently it works correctly only with vertical sliders.
|
|
||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <ChannelSlider.h>
|
#include <ChannelSlider.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
@@ -255,56 +254,57 @@ BChannelSlider::MouseDown(BPoint where)
|
|||||||
frame.OffsetBy(fClickDelta);
|
frame.OffsetBy(fClickDelta);
|
||||||
|
|
||||||
float range = ThumbRangeFor(channel);
|
float range = ThumbRangeFor(channel);
|
||||||
|
|
||||||
if (Vertical()) {
|
if (Vertical()) {
|
||||||
fMinpoint = frame.top + frame.Height() / 2;
|
fMinpoint = frame.top + frame.Height() / 2;
|
||||||
frame.bottom += range;
|
frame.bottom += range;
|
||||||
} else {
|
} else {
|
||||||
fMinpoint = frame.Width();
|
// TODO: Fix this
|
||||||
frame.right += range;
|
frame.right += range;
|
||||||
|
fMinpoint = frame.Width();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Found. Now set the initial values
|
// Found. Now set the initial values
|
||||||
if (frame.Contains(where)) {
|
if (frame.Contains(where)) {
|
||||||
uint32 buttons = 0;
|
|
||||||
BMessage *currentMessage = Window()->CurrentMessage();
|
|
||||||
if (currentMessage != NULL)
|
|
||||||
currentMessage->FindInt32("buttons", (int32 *)&buttons);
|
|
||||||
|
|
||||||
fAllChannels = (buttons & B_SECONDARY_MOUSE_BUTTON) == 0;
|
|
||||||
fCurrentChannel = channel;
|
fCurrentChannel = channel;
|
||||||
|
|
||||||
if (fInitialValues != NULL && fAllChannels) {
|
|
||||||
delete[] fInitialValues;
|
|
||||||
fInitialValues = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fInitialValues == NULL)
|
|
||||||
fInitialValues = new int32[CountChannels()];
|
|
||||||
|
|
||||||
if (fAllChannels) {
|
|
||||||
for (int32 i = 0; i < CountChannels(); i++)
|
|
||||||
fInitialValues[i] = ValueFor(i);
|
|
||||||
} else
|
|
||||||
fInitialValues[fCurrentChannel] = ValueFor(fCurrentChannel);
|
|
||||||
|
|
||||||
if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
|
|
||||||
if (!IsTracking()) {
|
|
||||||
SetTracking(true);
|
|
||||||
DrawThumbs();
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseMovedCommon(where, where);
|
|
||||||
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
debugger("BChannelSlider::MouseDown(): SYNCHRONOUS CONTROLS NOT YET SUPPORTED");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fCurrentChannel != -1) {
|
||||||
|
uint32 buttons = 0;
|
||||||
|
BMessage *currentMessage = Window()->CurrentMessage();
|
||||||
|
if (currentMessage != NULL)
|
||||||
|
currentMessage->FindInt32("buttons", (int32 *)&buttons);
|
||||||
|
|
||||||
|
fAllChannels = (buttons & B_SECONDARY_MOUSE_BUTTON) == 0;
|
||||||
|
|
||||||
|
if (fInitialValues != NULL && fAllChannels) {
|
||||||
|
delete[] fInitialValues;
|
||||||
|
fInitialValues = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fInitialValues == NULL)
|
||||||
|
fInitialValues = new int32[CountChannels()];
|
||||||
|
|
||||||
|
if (fAllChannels) {
|
||||||
|
for (int32 i = 0; i < CountChannels(); i++)
|
||||||
|
fInitialValues[i] = ValueFor(i);
|
||||||
|
} else
|
||||||
|
fInitialValues[fCurrentChannel] = ValueFor(fCurrentChannel);
|
||||||
|
|
||||||
|
if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
|
||||||
|
if (!IsTracking()) {
|
||||||
|
SetTracking(true);
|
||||||
|
DrawThumbs();
|
||||||
|
Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseMovedCommon(where, where);
|
||||||
|
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
debugger("BChannelSlider::MouseDown(): SYNCHRONOUS CONTROLS NOT YET SUPPORTED");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +430,7 @@ BChannelSlider::DrawChannel(BView *into, int32 channel, BRect area, bool pressed
|
|||||||
BPoint bottomRight;
|
BPoint bottomRight;
|
||||||
if (Vertical()) {
|
if (Vertical()) {
|
||||||
leftTop.Set(area.left + hCenter, area.top + vCenter);
|
leftTop.Set(area.left + hCenter, area.top + vCenter);
|
||||||
bottomRight.Set(leftTop.x , leftTop.y + ThumbRangeFor(channel));
|
bottomRight.Set(leftTop.x, leftTop.y + ThumbRangeFor(channel));
|
||||||
} else {
|
} else {
|
||||||
leftTop.Set(area.left, area.top + vCenter);
|
leftTop.Set(area.left, area.top + vCenter);
|
||||||
bottomRight.Set(area.left + ThumbRangeFor(channel), leftTop.y);
|
bottomRight.Set(area.left + ThumbRangeFor(channel), leftTop.y);
|
||||||
@@ -441,6 +441,8 @@ BChannelSlider::DrawChannel(BView *into, int32 channel, BRect area, bool pressed
|
|||||||
BPoint thumbLocation = leftTop;
|
BPoint thumbLocation = leftTop;
|
||||||
if (Vertical())
|
if (Vertical())
|
||||||
thumbLocation.y += ThumbDeltaFor(channel);
|
thumbLocation.y += ThumbDeltaFor(channel);
|
||||||
|
else
|
||||||
|
thumbLocation.x += ThumbDeltaFor(channel);
|
||||||
|
|
||||||
DrawThumb(into, channel, thumbLocation, pressed);
|
DrawThumb(into, channel, thumbLocation, pressed);
|
||||||
}
|
}
|
||||||
@@ -594,7 +596,7 @@ BChannelSlider::FinishChange()
|
|||||||
if (fInitialValues != NULL) {
|
if (fInitialValues != NULL) {
|
||||||
if (fAllChannels) {
|
if (fAllChannels) {
|
||||||
// TODO: Iterate through the list of channels, and invoke only
|
// TODO: Iterate through the list of channels, and invoke only
|
||||||
// for changed values
|
// for changed values ?
|
||||||
|
|
||||||
InvokeChannel();
|
InvokeChannel();
|
||||||
|
|
||||||
@@ -624,29 +626,23 @@ BChannelSlider::UpdateFontDimens()
|
|||||||
void
|
void
|
||||||
BChannelSlider::DrawThumbs()
|
BChannelSlider::DrawThumbs()
|
||||||
{
|
{
|
||||||
BRect first = ThumbFrameFor(0);
|
|
||||||
BRect last = ThumbFrameFor(CountChannels() - 1);
|
|
||||||
|
|
||||||
if (fBacking == NULL) {
|
if (fBacking == NULL) {
|
||||||
BRect bitmapFrame;
|
// This is the idea: we build a bitmap by taking the coordinates
|
||||||
if (Vertical()) {
|
// of the first and last thumb frames (top/left and bottom/right),
|
||||||
bitmapFrame.top = first.top - ThumbRangeFor(0);
|
// and by enlarging this rectangle a bit (hence the "InsetBy(-3, -3)").
|
||||||
bitmapFrame.bottom = last.bottom;
|
BRect first = ThumbFrameFor(0);
|
||||||
bitmapFrame.left = first.left;
|
BRect last = ThumbFrameFor(CountChannels() - 1);
|
||||||
bitmapFrame.right = last.right;
|
BRect bitmapFrame(first.LeftTop(), last.RightBottom());
|
||||||
} else {
|
|
||||||
bitmapFrame.top = first.top;
|
if (Vertical())
|
||||||
bitmapFrame.bottom = last.bottom;
|
bitmapFrame.top -= ThumbRangeFor(0);
|
||||||
bitmapFrame.left = first.left;
|
else
|
||||||
bitmapFrame.right = last.right + ThumbRangeFor(0);
|
bitmapFrame.right += ThumbRangeFor(0);
|
||||||
}
|
|
||||||
|
|
||||||
bitmapFrame.InsetBy(-3, -3);
|
bitmapFrame.InsetBy(-3, -3);
|
||||||
bitmapFrame.OffsetTo(B_ORIGIN);
|
|
||||||
|
|
||||||
fBacking = new BBitmap(bitmapFrame, BScreen(Window()).ColorSpace(), true, false);
|
fBacking = new BBitmap(bitmapFrame, BScreen(Window()).ColorSpace(), true, false);
|
||||||
if (fBacking->Lock()) {
|
if (fBacking->Lock()) {
|
||||||
fBackingView = new BView(bitmapFrame, "backing view", B_FOLLOW_NONE, B_WILL_DRAW);
|
fBackingView = new BView(bitmapFrame.OffsetToCopy(B_ORIGIN), "backing view", B_FOLLOW_NONE, B_WILL_DRAW);
|
||||||
fBacking->AddChild(fBackingView);
|
fBacking->AddChild(fBackingView);
|
||||||
fBackingView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
fBackingView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
fBackingView->SetLowColor(fBackingView->ViewColor());
|
fBackingView->SetLowColor(fBackingView->ViewColor());
|
||||||
@@ -661,24 +657,58 @@ BChannelSlider::DrawThumbs()
|
|||||||
if (fBacking->Lock()) {
|
if (fBacking->Lock()) {
|
||||||
// Clear the view's background
|
// Clear the view's background
|
||||||
fBackingView->FillRect(fBackingView->Bounds(), B_SOLID_LOW);
|
fBackingView->FillRect(fBackingView->Bounds(), B_SOLID_LOW);
|
||||||
|
|
||||||
|
BRect channelArea;
|
||||||
for (int32 channel = 0; channel < CountChannels(); channel++) {
|
for (int32 channel = 0; channel < CountChannels(); channel++) {
|
||||||
BRect channelArea = ThumbFrameFor(channel);
|
channelArea = ThumbFrameFor(channel);
|
||||||
// TODO: HACK!!! What am I missing ?
|
// TODO: This is (apparently) needed because ThumbFrameFor() doesn't
|
||||||
// Why do I need this to draw the channel in the correct location ?
|
// take into account that the view we draw on is attached to an offscreen
|
||||||
channelArea.OffsetBy(3, -21);
|
// bitmap. Still this doesn't make much sense:
|
||||||
DrawChannel(fBackingView, channel, channelArea, fMinpoint != 0);
|
// could be that I'm simply missing something.
|
||||||
|
if (Vertical())
|
||||||
|
channelArea.OffsetBy(0, -channelArea.top);
|
||||||
|
else
|
||||||
|
channelArea.OffsetBy(0, -channelArea.Height());
|
||||||
|
|
||||||
|
bool pressed = fMinpoint != 0 && (channel == fCurrentChannel || fAllChannels);
|
||||||
|
DrawChannel(fBackingView, channel, channelArea, pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fBackingView->Sync();
|
fBackingView->Sync();
|
||||||
fBacking->Unlock();
|
fBacking->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawBitmapAsync(fBacking, drawHere);
|
||||||
|
|
||||||
|
// We also draw the channel value, unlike R5.
|
||||||
|
// TODO: just a prototype for now, it isn't so cool.
|
||||||
|
// for Axel: Not sure if this is what you wanted, feel free to change this
|
||||||
|
if (fCurrentChannel != -1 && fMinpoint != 0) {
|
||||||
|
char valueString[64];
|
||||||
|
snprintf(valueString, 64, "%ld", ValueFor(fCurrentChannel));
|
||||||
|
BPoint stringPoint = drawHere;
|
||||||
|
float stringWidth = StringWidth("100");
|
||||||
|
stringPoint.x += (fBacking->Bounds().Width() - stringWidth) / 2;
|
||||||
|
stringPoint.y += fBacking->Bounds().Height() + fLineFeed;
|
||||||
|
BRect stringRect(stringPoint, stringPoint);
|
||||||
|
stringRect.right += stringWidth;
|
||||||
|
stringRect.top -= fLineFeed;
|
||||||
|
|
||||||
|
SetHighColor(ViewColor());
|
||||||
|
stringRect.InsetBy(-5, -2);
|
||||||
|
FillRect(stringRect);
|
||||||
|
|
||||||
|
SetHighColor(0, 0, 0);
|
||||||
|
DrawString(valueString, stringPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fClickDelta is used in MouseMoved()
|
||||||
fClickDelta = drawHere;
|
fClickDelta = drawHere;
|
||||||
|
|
||||||
// TODO: Look at the above comment
|
if (Vertical())
|
||||||
fClickDelta.y -= 21;
|
fClickDelta.y -= ThumbFrameFor(0).top;
|
||||||
fClickDelta.x += 3;
|
else
|
||||||
|
fClickDelta.y -= ThumbFrameFor(0).Height();
|
||||||
DrawBitmapAsync(fBacking, drawHere);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user