* Copyright 2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
* Ingo Weinhold <bonefish@cs.tu-berlin.de>
*/
#include "SliderView.h"
#include <math.h>
#include <stdio.h>
#include <Message.h>
#include <Window.h>
#include "PopupSlider.h"
SliderView::SliderView(PopupSlider* target,
int32 min, int32 max, int32 value,
const char* formatString)
: PopupView("slider"),
fTarget(target),
fFormatString(formatString),
fMin(min),
fMax(max),
fValue(value),
fButtonRect(0.0, 0.0, -1.0, -1.0),
fDragOffset(0.0)
{
SetViewColor(B_TRANSPARENT_32_BIT);
if (Max() < Min())
SetMax(Min());
BFont font;
GetFont(&font);
float buttonWidth, buttonHeight;
GetSliderButtonDimensions(Max(), FormatString(), &font,
buttonWidth, buttonHeight);
fButtonRect.right = fButtonRect.left + buttonWidth;
fButtonRect.bottom = fButtonRect.top + buttonHeight;
float size = Max() - Min();
if (size > 200)
size = 200;
ResizeTo(6.0 + fButtonRect.Width() + size + 6.0,
6.0 + fButtonRect.Height() + 6.0);
}
SliderView::~SliderView()
{
}
minimax
SliderView::layoutprefs()
{
mpm.mini.x = mpm.maxi.x = Bounds().Width() + 1.0;
mpm.mini.y = mpm.maxi.y = Bounds().Height() + 1.0;
mpm.weight = 1.0;
return mpm;
}
BRect
SliderView::layout(BRect frame)
{
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
return Frame();
}
void
SliderView::Draw(BRect updateRect)
{
fButtonRect.OffsetTo(ButtonOffset(), 6.0);
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
rgb_color lightShadow = tint_color(background, B_DARKEN_1_TINT);
rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
BRect r(Bounds());
BeginLineArray(24);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), lightShadow);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), lightShadow);
AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), darkShadow);
AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), darkShadow);
r.InsetBy(1.0, 1.0);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), light);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), light);
AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), shadow);
AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), shadow);
r.InsetBy(1.0, 1.0);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), background);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), background);
AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), background);
AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), background);
r.InsetBy(1.0, 1.0);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), background);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), background);
AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), background);
AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), background);
r.InsetBy(1.0, 1.0);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), lightShadow);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), lightShadow);
AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), light);
AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), light);
r.InsetBy(1.0, 1.0);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), darkShadow);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), darkShadow);
AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), shadow);
AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), shadow);
EndLineArray();
r.InsetBy(1.0, 1.0);
SetLowColor(lightShadow);
BRect leftOfButton(r.left + 1.0, r.top + 1.0, fButtonRect.left - 2.0, r.bottom);
if (leftOfButton.IsValid())
FillRect(leftOfButton, B_SOLID_LOW);
BRect rightOfButton(fButtonRect.right + 2.0, r.top + 1.0,
r.right, r.bottom);
if (rightOfButton.IsValid())
FillRect(rightOfButton, B_SOLID_LOW);
BeginLineArray(5);
AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), shadow);
AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), shadow);
if (fButtonRect.left == 6.0)
AddLine(BPoint(fButtonRect.left - 1.0, r.top),
BPoint(fButtonRect.left - 1.0, r.bottom), darkShadow);
else
AddLine(BPoint(fButtonRect.left - 1.0, r.top),
BPoint(fButtonRect.left - 1.0, r.bottom), shadow);
AddLine(BPoint(fButtonRect.left, fButtonRect.bottom + 1.0),
BPoint(fButtonRect.right + 1.0, fButtonRect.bottom + 1.0), darkShadow);
AddLine(BPoint(fButtonRect.right + 1.0, fButtonRect.bottom),
BPoint(fButtonRect.right + 1.0, fButtonRect.top), darkShadow);
EndLineArray();
DrawSliderButton(this, fButtonRect, fValue, fFormatString.String(), fTarget->IsEnabled());
}
void
SliderView::MouseUp(BPoint where)
{
PopupDone(false);
fTarget->TriggerValueChanged(fTarget->Message());
}
void
SliderView::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
{
uint32 buttons = 0;
if (BMessage* message = Window()->CurrentMessage()) {
if (message->FindInt32("buttons", (int32*)&buttons) < B_OK)
buttons = 0;
}
if (buttons == 0) {
MouseUp(where);
return;
}
SetValue(_ValueAt(where.x - fDragOffset - 6.0));
}
void
SliderView::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
PopupView::MessageReceived(message);
break;
}
}
void
SliderView::SetValue(int32 value)
{
if (value < fMin)
value = fMin;
if (value > fMax)
value = fMax;
if (value != fValue) {
fValue = value;
fTarget->SetValue(value);
Invalidate();
}
}
int32
SliderView::Value() const
{
return fValue;
}
void
SliderView::SetMin(int32 min)
{
if (min != fMax) {
fMin = min;
if (fValue < fMin)
SetValue(fMin);
Invalidate();
}
}
int32
SliderView::Min() const
{
return fMin;
}
void
SliderView::SetMax(int32 max)
{
if (max != fMax) {
fMax = max;
if (fValue > fMax)
SetValue(fMax);
Invalidate();
}
}
int32
SliderView::Max() const
{
return fMax;
}
void
SliderView::SetFormatString(const char* formatString)
{
fFormatString.SetTo(formatString);
}
const char*
SliderView::FormatString() const
{
return fFormatString.String();
}
void
SliderView::SetDragOffset(float offset)
{
fDragOffset = offset;
}
float
SliderView::ButtonOffset()
{
float ratio = fTarget->DeScale((float)(fValue - fMin) / (float)(fMax - fMin));
return 6.0 + ratio * (Bounds().Width() - 12.0 - fButtonRect.Width());
}
void
SliderView::GetSliderButtonDimensions(int32 max, const char* formatString,
BFont* font,
float& width, float& height)
{
if (font) {
char label[256];
sprintf(label, formatString, max);
font_height fh;
font->GetHeight(&fh);
width = 5.0 + ceilf(font->StringWidth(label)) + 5.0;
height = 2.0 + ceilf(fh.ascent + fh.descent) + 2.0;
}
}
void
SliderView::DrawSliderButton(BView* v, BRect r, int32 value,
const char* formatString, bool enabled)
{
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color light;
rgb_color shadow;
rgb_color button;
rgb_color black;
if (enabled) {
light = tint_color(background, B_LIGHTEN_MAX_TINT);
shadow = tint_color(background, B_DARKEN_1_TINT);
button = tint_color(background, B_LIGHTEN_1_TINT);
black = tint_color(background, B_DARKEN_MAX_TINT);
} else {
light = tint_color(background, B_LIGHTEN_1_TINT);
shadow = tint_color(background, 1.1);
button = tint_color(background, 0.8);
black = tint_color(background, B_DISABLED_LABEL_TINT);
}
v->BeginLineArray(4);
v->AddLine(BPoint(r.left, r.bottom),
BPoint(r.left, r.top), light);
v->AddLine(BPoint(r.left + 1.0, r.top),
BPoint(r.right, r.top), light);
v->AddLine(BPoint(r.right, r.top + 1.0),
BPoint(r.right, r.bottom), shadow);
v->AddLine(BPoint(r.right - 1.0, r.bottom),
BPoint(r.left + 1.0, r.bottom), shadow);
v->EndLineArray();
r.InsetBy(1.0, 1.0);
char label[256];
sprintf(label, formatString, value);
float width = v->StringWidth(label);
font_height fh;
v->GetFontHeight(&fh);
BPoint textPoint((r.left + r.right) / 2.0 - width / 2.0,
(r.top + r.bottom) / 2.0 + fh.ascent / 2.0);
v->SetHighColor(black);
v->SetLowColor(button);
v->FillRect(r, B_SOLID_LOW);
v->DrawString(label, textPoint);
}
int32
SliderView::_ValueAt(float h)
{
(Bounds().Width() - fButtonRect.Width() - 12.0));*/
float ratio = h / (Bounds().Width() - fButtonRect.Width() - 12.0);
if (ratio < 0.0)
ratio = 0.0;
if (ratio > 1.0)
ratio = 1.0;
ratio = fTarget->Scale(ratio);
return fMin + (int32)((fMax - fMin + 1) * ratio);
}