/* ui/slider.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include "math/functions.h" #include "ui/paint.h" #include "ui/slider.h" namespace ui { Slider::Slider(Widget *parent, const float minimum, const float maximum) : Widget(parent) { set_label("slider"); slider_dragging = false; slider_minimum = minimum; slider_maximum = maximum; slider_value = slider_minimum; slider_minbutton = new ui::Button(this, "<"); slider_minbutton->set_border(false); slider_decbutton = new ui::Button(this, "-"); slider_decbutton->set_border(false); slider_incbutton = new ui::Button(this, "+"); slider_incbutton->set_border(false); slider_maxbutton = new ui::Button(this, ">"); slider_maxbutton->set_border(false); set_background(true); set_border(true); validate(); } Slider::~Slider() { } void Slider::set_value(const float value) { slider_value = value; validate(); } void Slider::set_minimum(const float minimum) { slider_minimum = minimum; validate(); } void Slider::set_maximum(const float maximum) { slider_maximum = maximum; validate(); } void Slider::set_range(const float minimum, const float maximum) { slider_minimum = minimum; slider_maximum = maximum; validate(); } void Slider::validate() { if (slider_minimum > slider_maximum) { math::swap(slider_minimum, slider_maximum); } math::clamp(slider_value, slider_minimum, slider_maximum); } void Slider::print(const size_t indent) const { std::string marker(""); con_print << aux::pad_left(marker, indent*2) << label() << " \"" << minimum() << "-" << maximum() << "\"" << std::endl; } bool Slider::on_emit(Widget *sender, const Event event, void *data) { if (event == EventButtonClicked) { if (sender == slider_minbutton) { slider_value = slider_minimum; emit(EventSliderChanged, this); return true; } else if (sender == slider_decbutton) { if (slider_value > slider_minimum) { slider_value--; emit(EventSliderChanged, this); } return true; } else if (sender == slider_incbutton) { if (slider_value < slider_maximum) { slider_value++; emit(EventSliderChanged, this); } return true; } else if (sender == slider_maxbutton) { slider_value = slider_maximum; emit(EventSliderChanged, this); return true; } } return false; } bool Slider::on_mousewheel(const math::Vector2f & direction) { if (direction.y() > 0 ) { if (slider_value < slider_maximum) { slider_value++; emit(EventSliderChanged, this); } return true; } else if (direction.y() < 0 ) { if (slider_value > slider_minimum) { slider_value--; emit(EventSliderChanged, this); } return true; } return false; } bool Slider::on_mousepress(const unsigned int button) { if (button == SDL_BUTTON_LEFT) { set_focus(); if (slider_maximum > slider_minimum) { // TODO position hit test slider_dragging = true; } return true; } return false; } bool Slider::on_mouserelease(const unsigned int button) { if (button == SDL_BUTTON_LEFT) { slider_dragging = false; return true; } return false; } void Slider::on_mousemove(const math::Vector2f &cursor) { if ((width() <= 0) || (height() <= 0)) { return; } if (slider_dragging && (slider_maximum > slider_minimum)) { float x = cursor.x(); math::clamp(x, 2.0f * height(), width() - 2.0f * height()); const float w = (width() - 4.0f * height()); const float s = w / (slider_maximum - slider_minimum); const float p = x - 2.0f * height(); const float newvalue = slider_minimum + round(p /s); if (slider_value != newvalue) { slider_value = newvalue; emit(EventSliderChanged, this); } } } void Slider::on_mouseover(const math::Vector2f &cursor) { slider_dragging = false; } void Slider::show() { Widget::show(); resize(); } void Slider::resize() { // note: slider expects width > height slider_minbutton->set_size(height(), height()); slider_minbutton->set_location(0, 0); slider_decbutton->set_size(height(), height()); slider_decbutton->set_location(slider_minbutton->right(), 0); slider_maxbutton->set_size(height(), height()); slider_maxbutton->set_location(width() - slider_maxbutton->width(), 0); slider_incbutton->set_size(height(), height()); slider_incbutton->set_location(slider_maxbutton->left() - slider_incbutton->width() , 0); } void Slider::draw() { if (slider_maximum > slider_minimum) { const float range = (slider_value - slider_minimum) / (slider_maximum - slider_minimum); const float x = (width() - 5.0f * height()) * range; if (slider_dragging) { Paint::set_color(palette()->highlight()); } else { Paint::set_color(palette()->foreground()); } Paint::draw_rectangle(math::Vector2f(global_location().x() + 2.0f * height() + x + 1, global_location().y() +1 ), math::Vector2f(height() - 2, height() - 2)); } Widget::draw(); } } // namespace ui