#include "PopupSlider.h"
#include <math.h>
#include <stdio.h>
#include <Message.h>
#include <MDividable.h>
#include <MWindow.h>
#include "SliderView.h"
PopupSlider::PopupSlider(const char* name, const char* label,
BMessage* model, BHandler* target,
int32 min, int32 max, int32 value,
const char* formatString)
: PopupControl(name, fSlider = new SliderView(this, min, max, value,
formatString)),
MDividable(),
fModel(model),
fPressModel(NULL),
fReleaseModel(NULL),
fTarget(target),
fLabel(label),
fSliderButtonRect(0.0, 0.0, -1.0, -1.0),
fEnabled(true),
fTracking(false)
{
SetViewColor(B_TRANSPARENT_32_BIT);
}
PopupSlider::~PopupSlider()
{
delete fModel;
if (BWindow* window = fSlider->Window()) {
window->Lock();
window->RemoveChild(fSlider);
window->Unlock();
}
delete fSlider;
}
minimax
PopupSlider::layoutprefs()
{
BFont font;
GetFont(&font);
font_height fh;
font.GetHeight(&fh);
float labelHeight = 2.0 + ceilf(fh.ascent + fh.descent) + 2.0;
float sliderWidth, sliderHeight;
SliderView::GetSliderButtonDimensions(Max(), FormatString(), &font,
sliderWidth, sliderHeight);
float height = labelHeight > sliderHeight + 2.0 ?
labelHeight : sliderHeight + 2.0;
float minLabelWidth = LabelWidth();
if (rolemodel)
labelwidth = rolemodel->LabelWidth();
labelwidth = minLabelWidth > labelwidth ? minLabelWidth : labelwidth;
fSliderButtonRect.left = labelwidth;
fSliderButtonRect.right = fSliderButtonRect.left + sliderWidth + 2.0;
fSliderButtonRect.top = floorf(height / 2.0 - (sliderHeight + 2.0) / 2.0);
fSliderButtonRect.bottom = fSliderButtonRect.top + sliderHeight + 2.0;
fSliderButtonRect.OffsetTo(Bounds().right - fSliderButtonRect.Width(),
fSliderButtonRect.top);
mpm.mini.x = labelwidth + fSliderButtonRect.Width() + 1.0;
mpm.maxi.x = 10000.0;
mpm.mini.y = mpm.maxi.y = height + 1.0;
mpm.weight = 1.0;
return mpm;
}
BRect
PopupSlider::layout(BRect frame)
{
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
fSliderButtonRect.OffsetTo(Bounds().right - fSliderButtonRect.Width(),
fSliderButtonRect.top);
return Frame();
}
void
PopupSlider::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
PopupControl::MessageReceived(message);
break;
}
}
void
PopupSlider::AttachedToWindow()
{
fSliderButtonRect.OffsetTo(Bounds().right - fSliderButtonRect.Width(),
fSliderButtonRect.top);
PopupControl::AttachedToWindow();
}
void
PopupSlider::Draw(BRect updateRect)
{
bool enabled = IsEnabled();
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color black;
if (enabled) {
black = tint_color(background, B_DARKEN_MAX_TINT);
} else {
black = tint_color(background, B_DISABLED_LABEL_TINT);
}
BRect r(Bounds());
r.right = fSliderButtonRect.left - 1.0;
font_height fh;
GetFontHeight(&fh);
BPoint textPoint(0.0, (r.top + r.bottom) / 2.0 + fh.ascent / 2.0);
SetLowColor(background);
SetHighColor(black);
FillRect(r, B_SOLID_LOW);
DrawString(fLabel.String(), textPoint);
DrawSlider(fSliderButtonRect, enabled);
}
void
PopupSlider::MouseDown(BPoint where)
{
if (fEnabled && fSliderButtonRect.Contains(where) &&
!fSlider->LockLooper()) {
SetPopupLocation(BPoint(fSliderButtonRect.left + 1.0
- fSlider->ButtonOffset(),
-5.0));
where.x -= fSliderButtonRect.left + 1.0;
fSlider->SetDragOffset(where.x);
fTracking = true;
ShowPopup(&where);
}
}
void
PopupSlider::PopupShown()
{
TriggerValueChanged(fPressModel);
fTracking = true;
}
void
PopupSlider::PopupHidden(bool canceled)
{
TriggerValueChanged(fReleaseModel);
fTracking = false;
}
void
PopupSlider::SetValue(int32 value)
{
if (!fTracking) {
if (value != Value()) {
fSlider->SetValue(value);
if (LockLooperWithTimeout(0) >= B_OK) {
Invalidate();
UnlockLooper();
}
}
} else
ValueChanged(value);
}
int32
PopupSlider::Value() const
{
int32 value = 0;
value = fSlider->Value();
return value;
}
void
PopupSlider::SetEnabled(bool enable)
{
if (enable != fEnabled) {
fEnabled = enable;
if (LockLooper()) {
Invalidate();
UnlockLooper();
}
}
}
bool
PopupSlider::IsEnabled() const
{
return fEnabled;
}
void
PopupSlider::TriggerValueChanged(const BMessage* message) const
{
if (message && fTarget) {
BMessage msg(*message);
msg.AddInt64("be:when", system_time());
msg.AddInt32("be:value", Value());
msg.AddPointer("be:source", (void*)this);
if (BLooper* looper = fTarget->Looper())
looper->PostMessage(&msg, fTarget);
}
}
bool
PopupSlider::IsTracking() const
{
return fTracking;
}
void
PopupSlider::ValueChanged(int32 newValue)
{
TriggerValueChanged(fModel);
}
void
PopupSlider::DrawSlider(BRect frame, bool enabled)
{
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color lightShadow;
rgb_color darkShadow;
if (enabled) {
lightShadow = tint_color(background, B_DARKEN_2_TINT);
darkShadow = tint_color(background, B_DARKEN_4_TINT);
} else {
lightShadow = tint_color(background, B_DARKEN_1_TINT);
darkShadow = tint_color(background, B_DARKEN_2_TINT);
}
BeginLineArray(4);
AddLine(BPoint(frame.left, frame.bottom),
BPoint(frame.left, frame.top), lightShadow);
AddLine(BPoint(frame.left + 1.0, frame.top),
BPoint(frame.right, frame.top), lightShadow);
AddLine(BPoint(frame.right, frame.top + 1.0),
BPoint(frame.right, frame.bottom), darkShadow);
AddLine(BPoint(frame.right - 1.0, frame.bottom),
BPoint(frame.left + 1.0, frame.bottom), darkShadow);
EndLineArray();
frame.InsetBy(1.0, 1.0);
SliderView::DrawSliderButton(this, frame, Value(), FormatString(), enabled);
}
float
PopupSlider::Scale(float ratio) const
{
return ratio;
}
float
PopupSlider::DeScale(float ratio) const
{
return ratio;
}
void
PopupSlider::SetMessage(BMessage* message)
{
delete fModel;
fModel = message;
}
void
PopupSlider::SetPressedMessage(BMessage* message)
{
delete fPressModel;
fPressModel = message;
}
void
PopupSlider::SetReleasedMessage(BMessage* message)
{
delete fReleaseModel;
fReleaseModel = message;
}
void
PopupSlider::SetMin(int32 min)
{
fSlider->SetMin(min);
}
int32
PopupSlider::Min() const
{
int32 value = 0;
value = fSlider->Min();
return value;
}
void
PopupSlider::SetMax(int32 max)
{
fSlider->SetMax(max);
}
int32
PopupSlider::Max() const
{
int32 value = 0;
value = fSlider->Max();
return value;
}
void
PopupSlider::SetLabel(const char* label)
{
fLabel.SetTo(label);
Invalidate();
}
const char*
PopupSlider::Label() const
{
return fLabel.String();
}
float
PopupSlider::LabelWidth()
{
return _MinLabelWidth();
}
const char*
PopupSlider::StringForValue(int32 value)
{
return NULL;
}
float
PopupSlider::MaxValueStringWidth()
{
return 0.0;
}
void
PopupSlider::SetFormatString(const char* formatString)
{
fSlider->SetFormatString(formatString);
}
const char*
PopupSlider::FormatString() const
{
return fSlider->FormatString();
}
float
PopupSlider::_MinLabelWidth() const
{
return ceilf(StringWidth(fLabel.String())) + 5.0;
}