nuclear@6: /* nuclear@6: GoatKit - a themable/animated widget toolkit for games nuclear@6: Copyright (C) 2014 John Tsiombikas nuclear@6: nuclear@6: This program is free software: you can redistribute it and/or modify nuclear@6: it under the terms of the GNU Lesser General Public License as published by nuclear@6: the Free Software Foundation, either version 3 of the License, or nuclear@6: (at your option) any later version. nuclear@6: nuclear@6: This program is distributed in the hope that it will be useful, nuclear@6: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@6: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@6: GNU Lesser General Public License for more details. nuclear@6: nuclear@6: You should have received a copy of the GNU Lesser General Public License nuclear@6: along with this program. If not, see . nuclear@6: */ nuclear@6: #include nuclear@6: #include nuclear@6: #include "slider.h" nuclear@6: #include "screen.h" nuclear@6: nuclear@6: namespace goatkit { nuclear@6: nuclear@6: struct SliderImpl { nuclear@6: float value, prev_value; nuclear@6: float range_min, range_max; nuclear@6: float padding; nuclear@6: float step; nuclear@6: bool dragging; nuclear@6: bool cont_change; nuclear@6: }; nuclear@6: nuclear@6: static float remap(float val, float inlow, float inhigh, float outlow, float outhigh); nuclear@6: nuclear@6: Slider::Slider() nuclear@6: { nuclear@6: slider = new SliderImpl; nuclear@6: slider->value = slider->prev_value = 0.0f; nuclear@6: slider->dragging = false; nuclear@6: slider->cont_change = true; nuclear@6: nuclear@6: slider->range_min = 0.0; nuclear@6: slider->range_max = 1.0; nuclear@6: slider->step = 0.0; nuclear@6: nuclear@6: slider->padding = -1.0; nuclear@6: } nuclear@6: nuclear@6: Slider::~Slider() nuclear@6: { nuclear@6: delete slider; nuclear@6: } nuclear@6: nuclear@6: const char *Slider::get_type_name() const nuclear@6: { nuclear@6: return "slider"; nuclear@6: } nuclear@6: nuclear@6: void Slider::set_value(float val) nuclear@6: { nuclear@6: slider->value = remap(val, slider->range_min, slider->range_max, 0, 1); nuclear@6: } nuclear@6: nuclear@6: float Slider::get_value() const nuclear@6: { nuclear@6: return remap(slider->value, 0, 1, slider->range_min, slider->range_max); nuclear@6: } nuclear@6: nuclear@6: void Slider::set_value_norm(float val) nuclear@6: { nuclear@6: slider->value = val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val); nuclear@6: } nuclear@6: nuclear@6: float Slider::get_value_norm() const nuclear@6: { nuclear@6: return slider->value; nuclear@6: } nuclear@6: nuclear@6: void Slider::set_padding(float pad) nuclear@6: { nuclear@6: slider->padding = pad; nuclear@6: } nuclear@6: nuclear@6: float Slider::get_padding() const nuclear@6: { nuclear@6: if(slider->padding < 0.0) { nuclear@6: BBox box = get_box(); nuclear@6: return (box.bmax.y - box.bmin.y) * 0.25; nuclear@6: } nuclear@6: return slider->padding; nuclear@6: } nuclear@6: nuclear@6: void Slider::set_continuous_change(bool cont) nuclear@6: { nuclear@6: slider->cont_change = cont; nuclear@6: } nuclear@6: nuclear@6: bool Slider::get_continuous_change() const nuclear@6: { nuclear@6: return slider->cont_change; nuclear@6: } nuclear@6: nuclear@6: void Slider::set_range(float min, float max) nuclear@6: { nuclear@6: slider->range_min = min; nuclear@6: slider->range_max = max; nuclear@6: } nuclear@6: nuclear@6: float Slider::get_range_min() const nuclear@6: { nuclear@6: return slider->range_min; nuclear@6: } nuclear@6: nuclear@6: float Slider::get_range_max() const nuclear@6: { nuclear@6: return slider->range_max; nuclear@6: } nuclear@6: nuclear@6: void Slider::set_step(float step) nuclear@6: { nuclear@6: slider->step = step; nuclear@6: } nuclear@6: nuclear@6: float Slider::get_step() const nuclear@6: { nuclear@6: return slider->step; nuclear@6: } nuclear@6: nuclear@6: void Slider::on_mouse_button(const ButtonEvent &ev) nuclear@6: { nuclear@6: if(ev.button == 0) { nuclear@6: Screen *scr = get_screen(); nuclear@6: nuclear@6: slider->dragging = ev.press; nuclear@6: if(ev.press) { nuclear@6: if(scr) scr->grab_mouse(this); nuclear@6: } else { nuclear@6: if(scr) scr->grab_mouse(0); nuclear@6: nuclear@6: // on release, if the value has changed send the appropriate event nuclear@6: if(slider->prev_value != slider->value) { nuclear@6: Event ev; nuclear@6: ev.type = EV_CHANGE; nuclear@6: handle_event(ev); nuclear@6: slider->prev_value = slider->value; nuclear@6: } nuclear@6: } nuclear@6: } nuclear@6: } nuclear@6: nuclear@6: #define ROUND(x) floor((x) + 0.5) nuclear@6: nuclear@6: void Slider::on_mouse_motion(const MotionEvent &ev) nuclear@6: { nuclear@6: if(!slider->dragging) { nuclear@6: return; nuclear@6: } nuclear@6: nuclear@6: BBox box = get_box(); nuclear@6: nuclear@6: float padding = get_padding(); nuclear@6: float start = box.bmin.x + padding; nuclear@6: float end = box.bmax.x - padding; nuclear@6: float new_val = (ev.pos.x - start) / (end - start); nuclear@6: nuclear@6: // if we have a non-zero step, snap to the nearest value nuclear@6: if(slider->step > 0.0) { nuclear@6: float range = slider->range_max - slider->range_min; nuclear@6: float st = slider->step / range; nuclear@6: nuclear@6: new_val = ROUND(new_val / st) * st; nuclear@6: } nuclear@6: nuclear@6: if(new_val < 0.0) new_val = 0.0; nuclear@6: if(new_val > 1.0) new_val = 1.0; nuclear@6: nuclear@6: if(new_val != slider->value) { nuclear@6: slider->value = new_val; nuclear@6: if(slider->cont_change) { nuclear@6: Event cev; nuclear@6: cev.type = EV_CHANGE; nuclear@6: handle_event(cev); nuclear@6: } nuclear@6: } nuclear@6: } nuclear@6: nuclear@6: static float remap(float val, float inlow, float inhigh, float outlow, float outhigh) nuclear@6: { nuclear@6: float t = (val - inlow) / (inhigh - inlow); nuclear@6: if(t < 0.0) t = 0.0; nuclear@6: if(t > 1.0) t = 1.0; nuclear@6: return t * (outhigh - outlow) + outlow; nuclear@6: } nuclear@6: nuclear@6: } // namespace goatkit