aseprite/src/ui/slider.cpp

263 lines
5.5 KiB
C++
Raw Normal View History

// Aseprite UI Library
2013-01-27 12:13:13 -03:00
// Copyright (C) 2001-2013 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
2007-09-18 23:57:02 +00:00
#ifdef HAVE_CONFIG_H
2009-07-12 20:29:16 +00:00
#include "config.h"
#endif
2009-07-12 20:29:16 +00:00
2012-06-17 22:49:58 -03:00
#include "ui/font.h"
#include "ui/manager.h"
#include "ui/message.h"
#include "ui/preferred_size_event.h"
#include "ui/slider.h"
#include "ui/system.h"
#include "ui/theme.h"
#include "ui/widget.h"
2007-09-18 23:57:02 +00:00
#include <cstdio>
namespace ui {
static int slider_press_x;
static int slider_press_value;
static bool slider_press_left;
Slider::Slider(int min, int max, int value)
: Widget(kSliderWidget)
2007-09-18 23:57:02 +00:00
{
m_min = min;
m_max = max;
m_value = MID(min, value, max);
2007-09-18 23:57:02 +00:00
this->setFocusStop(true);
initTheme();
2007-09-18 23:57:02 +00:00
}
void Slider::setRange(int min, int max)
2007-09-18 23:57:02 +00:00
{
m_min = min;
m_max = max;
m_value = MID(min, m_value, max);
2007-09-18 23:57:02 +00:00
invalidate();
2007-09-18 23:57:02 +00:00
}
void Slider::setValue(int value)
2007-09-18 23:57:02 +00:00
{
int old_value = m_value;
2007-09-18 23:57:02 +00:00
m_value = MID(m_min, value, m_max);
2007-09-18 23:57:02 +00:00
if (m_value != old_value)
invalidate();
2007-09-18 23:57:02 +00:00
// It DOES NOT emit CHANGE signal! to avoid recursive calls.
2007-09-18 23:57:02 +00:00
}
void Slider::getSliderThemeInfo(int* min, int* max, int* value)
2007-09-18 23:57:02 +00:00
{
if (min) *min = m_min;
if (max) *max = m_max;
if (value) *value = m_value;
2007-09-18 23:57:02 +00:00
}
bool Slider::onProcessMessage(Message* msg)
2007-09-18 23:57:02 +00:00
{
switch (msg->type()) {
2007-09-18 23:57:02 +00:00
case kFocusEnterMessage:
case kFocusLeaveMessage:
if (isEnabled())
invalidate();
2007-09-18 23:57:02 +00:00
break;
case kMouseDownMessage:
if (!isEnabled())
return true;
setSelected(true);
captureMouse();
2007-09-18 23:57:02 +00:00
{
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
slider_press_x = mousePos.x;
slider_press_value = m_value;
slider_press_left = static_cast<MouseMessage*>(msg)->left();
}
setupSliderCursor();
2007-09-18 23:57:02 +00:00
2014-02-08 19:26:13 -03:00
// Fall through
case kMouseMoveMessage:
if (hasCapture()) {
int value, accuracy, range;
gfx::Rect rc = getChildrenBounds();
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
range = m_max - m_min + 1;
// With left click
if (slider_press_left) {
value = m_min + range * (mousePos.x - rc.x) / rc.w;
}
// With right click
else {
accuracy = MID(1, rc.w / range, rc.w);
value = slider_press_value +
(mousePos.x - slider_press_x) / accuracy;
}
value = MID(m_min, value, m_max);
if (m_value != value) {
setValue(value);
onChange();
}
// For left click
if (slider_press_left) {
int x = mousePos.x;
if (x < rc.x-1)
x = rc.x-1;
else if (x > rc.x2())
x = rc.x2();
if (x != mousePos.x)
ui::set_mouse_position(gfx::Point(x, mousePos.y));
}
// For right click
else {
gfx::Point newPoint =
ui::control_infinite_scroll(this, getBounds() - getBorder(), mousePos);
if (newPoint != mousePos) {
slider_press_x = newPoint.x;
slider_press_value = m_value;
}
}
return true;
2007-09-18 23:57:02 +00:00
}
break;
case kMouseUpMessage:
if (hasCapture()) {
setSelected(false);
releaseMouse();
setupSliderCursor();
onSliderReleased();
2007-09-18 23:57:02 +00:00
}
break;
case kMouseEnterMessage:
case kMouseLeaveMessage:
// TODO theme stuff
if (isEnabled())
invalidate();
2007-09-18 23:57:02 +00:00
break;
case kKeyDownMessage:
if (hasFocus()) {
int min = m_min;
int max = m_max;
int value = m_value;
switch (static_cast<KeyMessage*>(msg)->scancode()) {
case kKeyLeft: value = MAX(value-1, min); break;
case kKeyRight: value = MIN(value+1, max); break;
case kKeyPageDown: value = MAX(value-(max-min+1)/4, min); break;
case kKeyPageUp: value = MIN(value+(max-min+1)/4, max); break;
case kKeyHome: value = min; break;
case kKeyEnd: value = max; break;
default:
goto not_used;
}
if (m_value != value) {
setValue(value);
onChange();
}
return true;
2007-09-18 23:57:02 +00:00
}
break;
case kMouseWheelMessage:
if (isEnabled()) {
int value = m_value + static_cast<MouseMessage*>(msg)->wheelDelta();
2007-09-18 23:57:02 +00:00
value = MID(m_min, value, m_max);
2007-09-18 23:57:02 +00:00
if (m_value != value) {
this->setValue(value);
onChange();
}
return true;
2007-09-18 23:57:02 +00:00
}
break;
case kSetCursorMessage:
setupSliderCursor();
return true;
2007-09-18 23:57:02 +00:00
}
not_used:;
return Widget::onProcessMessage(msg);
2007-09-18 23:57:02 +00:00
}
void Slider::onPreferredSize(PreferredSizeEvent& ev)
2007-09-18 23:57:02 +00:00
{
int w, h, min_w, max_w;
2007-09-18 23:57:02 +00:00
char buf[256];
std::sprintf(buf, "%d", m_min);
min_w = ji_font_text_len(this->getFont(), buf);
std::sprintf(buf, "%d", m_max);
max_w = ji_font_text_len(this->getFont(), buf);
w = MAX(min_w, max_w);
h = getTextHeight();
2007-09-18 23:57:02 +00:00
w += this->border_width.l + this->border_width.r;
h += this->border_width.t + this->border_width.b;
2007-09-18 23:57:02 +00:00
ev.setPreferredSize(w, h);
}
2007-09-18 23:57:02 +00:00
void Slider::onPaint(PaintEvent& ev)
{
getTheme()->paintSlider(ev);
}
void Slider::onChange()
{
Change(); // Emit Change signal
}
void Slider::onSliderReleased()
{
SliderReleased();
2007-09-18 23:57:02 +00:00
}
void Slider::setupSliderCursor()
{
if (hasCapture()) {
if (slider_press_left)
jmouse_set_cursor(kArrowCursor);
else
jmouse_set_cursor(kSizeLCursor);
}
else
jmouse_set_cursor(kArrowCursor);
}
} // namespace ui