aseprite/src/gui/jslider.cpp

282 lines
6.4 KiB
C++

// ASE gui library
// Copyright (C) 2001-2010 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include "config.h"
#include <allegro.h>
#include "gui/jfont.h"
#include "gui/jmanager.h"
#include "gui/jmessage.h"
#include "gui/jrect.h"
#include "gui/jsystem.h"
#include "gui/jtheme.h"
#include "gui/jwidget.h"
typedef struct Slider
{
int min;
int max;
int value;
} Slider;
static int slider_press_x;
static int slider_press_value;
static int slider_press_left;
static bool slider_msg_proc(JWidget widget, JMessage msg);
static void slider_request_size(JWidget widget, int *w, int *h);
static void slider_setcursor(JWidget widget);
JWidget jslider_new(int min, int max, int value)
{
Widget* widget = new Widget(JI_SLIDER);
Slider* slider = jnew(Slider, 1);
slider->min = min;
slider->max = max;
slider->value = MID(min, value, max);
jwidget_add_hook(widget, JI_SLIDER, slider_msg_proc, slider);
jwidget_focusrest(widget, true);
jwidget_init_theme(widget);
return widget;
}
void jslider_set_range(JWidget widget, int min, int max)
{
Slider* slider = reinterpret_cast<Slider*>(jwidget_get_data(widget, JI_SLIDER));
slider->min = min;
slider->max = max;
slider->value = MID(min, slider->value, max);
jwidget_dirty(widget);
}
void jslider_set_value(JWidget widget, int value)
{
Slider* slider = reinterpret_cast<Slider*>(jwidget_get_data(widget, JI_SLIDER));
int old_value = slider->value;
slider->value = MID(slider->min, value, slider->max);
if (slider->value != old_value)
jwidget_dirty(widget);
/* it DOES NOT emit CHANGE signal! to avoid recursive calls */
}
int jslider_get_value(JWidget widget)
{
Slider* slider = reinterpret_cast<Slider*>(jwidget_get_data(widget, JI_SLIDER));
return slider->value;
}
void jtheme_slider_info(JWidget widget, int *min, int *max, int *value)
{
Slider* slider = reinterpret_cast<Slider*>(jwidget_get_data(widget, JI_SLIDER));
if (min) *min = slider->min;
if (max) *max = slider->max;
if (value) *value = slider->value;
}
static bool slider_msg_proc(JWidget widget, JMessage msg)
{
Slider* slider = reinterpret_cast<Slider*>(jwidget_get_data(widget, JI_SLIDER));
switch (msg->type) {
case JM_DESTROY:
jfree(slider);
break;
case JM_REQSIZE:
slider_request_size(widget, &msg->reqsize.w, &msg->reqsize.h);
return true;
case JM_DRAW:
widget->theme->draw_slider(widget, &msg->draw.rect);
return true;
case JM_FOCUSENTER:
case JM_FOCUSLEAVE:
if (widget->isEnabled())
jwidget_dirty(widget);
break;
case JM_BUTTONPRESSED:
if (!widget->isEnabled())
return true;
widget->setSelected(true);
widget->captureMouse();
slider_press_x = msg->mouse.x;
slider_press_value = slider->value;
slider_press_left = msg->mouse.left;
slider_setcursor(widget);
/* continue to JM_MOTION */
case JM_MOTION:
if (widget->hasCapture()) {
int value, accuracy, range;
JRect rc = jwidget_get_child_rect(widget);
range = slider->max - slider->min + 1;
/* with left click */
if (slider_press_left) {
value = slider->min + range * (msg->mouse.x - rc->x1) / jrect_w(rc);
}
/* with right click */
else {
accuracy = MID(1, jrect_w(rc) / range, jrect_w(rc));
value = slider_press_value +
(msg->mouse.x - slider_press_x) / accuracy;
}
value = MID(slider->min, value, slider->max);
if (slider->value != value) {
jslider_set_value(widget, value);
jwidget_emit_signal(widget, JI_SIGNAL_SLIDER_CHANGE);
}
/* for left click */
if (slider_press_left) {
int x = jmouse_x(0);
if (x < rc->x1-1)
x = rc->x1-1;
else if (x > rc->x2)
x = rc->x2;
if (x != jmouse_x(0))
jmouse_set_position(x, jmouse_y(0));
}
/* for right click */
else if (jmouse_control_infinite_scroll(rc)) {
slider_press_x = jmouse_x(0);
slider_press_value = slider->value;
}
jrect_free(rc);
return true;
}
break;
case JM_BUTTONRELEASED:
if (widget->hasCapture()) {
widget->setSelected(false);
widget->releaseMouse();
slider_setcursor(widget);
}
break;
case JM_MOUSEENTER:
case JM_MOUSELEAVE:
/* if (jwidget_is_enabled(widget) && */
/* jwidget_has_capture(widget)) { */
/* /\* swap the select status *\/ */
/* if (jwidget_is_selected(widget)) */
/* jwidget_deselect(widget); */
/* else */
/* jwidget_select(widget); */
/* /\* TODO switch slider signal *\/ */
/* } */
/* TODO theme stuff */
if (widget->isEnabled())
jwidget_dirty(widget);
break;
case JM_KEYPRESSED:
if (widget->hasFocus()) {
int min = slider->min;
int max = slider->max;
int value = slider->value;
switch (msg->key.scancode) {
case KEY_LEFT: value = MAX(value-1, min); break;
case KEY_RIGHT: value = MIN(value+1, max); break;
case KEY_PGDN: value = MAX(value-(max-min+1)/4, min); break;
case KEY_PGUP: value = MIN(value+(max-min+1)/4, max); break;
case KEY_HOME: value = min; break;
case KEY_END: value = max; break;
default:
return false;
}
if (slider->value != value) {
jslider_set_value(widget, value);
jwidget_emit_signal(widget, JI_SIGNAL_SLIDER_CHANGE);
}
return true;
}
break;
case JM_WHEEL:
if (widget->isEnabled()) {
int value = slider->value + jmouse_z(0) - jmouse_z(1);
value = MID(slider->min, value, slider->max);
if (slider->value != value) {
jslider_set_value(widget, value);
jwidget_emit_signal(widget, JI_SIGNAL_SLIDER_CHANGE);
}
return true;
}
break;
case JM_SETCURSOR:
slider_setcursor(widget);
return true;
}
return false;
}
static void slider_request_size(JWidget widget, int *w, int *h)
{
Slider* slider = reinterpret_cast<Slider*>(jwidget_get_data(widget, JI_SLIDER));
int min_w, max_w;
char buf[256];
usprintf(buf, "%d", slider->min);
min_w = ji_font_text_len(widget->getFont(), buf);
usprintf(buf, "%d", slider->max);
max_w = ji_font_text_len(widget->getFont(), buf);
*w = MAX(min_w, max_w);
*h = text_height(widget->getFont());
*w += widget->border_width.l + widget->border_width.r;
*h += widget->border_width.t + widget->border_width.b;
}
static void slider_setcursor(JWidget widget)
{
if (widget->hasCapture()) {
if (slider_press_left)
jmouse_set_cursor(JI_CURSOR_NORMAL);
else
jmouse_set_cursor(JI_CURSOR_SIZE_L);
}
else
jmouse_set_cursor(JI_CURSOR_NORMAL);
}