/* ui/scrollbar.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/button.h" #include "ui/paint.h" #include "ui/scrollbar.h" namespace ui { ScrollBar::ScrollBar(Widget *parent, const float minimum, const float maximum) : Widget(parent) { set_label("scrollbar"); scrollbar_dragging = false; scrollbar_minimum = minimum; scrollbar_maximum = maximum; scrollbar_value = scrollbar_minimum; scrollbar_minbutton = new ui::Button(this, "o"); scrollbar_minbutton->set_border(false); scrollbar_decbutton = new ui::Button(this, "-"); scrollbar_decbutton->set_border(false); scrollbar_incbutton = new ui::Button(this, "+"); scrollbar_incbutton->set_border(false); scrollbar_maxbutton = new ui::Button(this, "o"); scrollbar_maxbutton->set_border(false); set_background(true); set_border(true); validate(); } ScrollBar::~ScrollBar() { } void ScrollBar::set_value(const float value) { scrollbar_value = value; validate(); } void ScrollBar::set_minimum(const float minimum) { scrollbar_minimum = minimum; validate(); } void ScrollBar::set_maximum(const float maximum) { scrollbar_maximum = maximum; validate(); } void ScrollBar::set_range(const float minimum, const float maximum) { scrollbar_minimum = minimum; scrollbar_maximum = maximum; validate(); } void ScrollBar::validate() { if (scrollbar_minimum > scrollbar_maximum) { math::swap(scrollbar_minimum, scrollbar_maximum); } math::clamp(scrollbar_value, scrollbar_minimum, scrollbar_maximum); } void ScrollBar::print(const size_t indent) const { std::string marker(""); con_print << aux::pad_left(marker, indent*2) << label() << " \"" << minimum() << "-" << maximum() << "\"" << std::endl; } bool ScrollBar::on_emit(Widget *sender, const Event event, void *data) { if (event == EventButtonClicked) { if (sender == scrollbar_minbutton) { scrollbar_value = scrollbar_minimum; emit(EventScrollBarChanged, this); return true; } else if (sender == scrollbar_decbutton) { if (scrollbar_value > scrollbar_minimum) { scrollbar_value--; emit(EventScrollBarChanged, this); } return true; } else if (sender == scrollbar_incbutton) { if (scrollbar_value < scrollbar_maximum) { scrollbar_value++; emit(EventScrollBarChanged, this); } return true; } else if (sender == scrollbar_maxbutton) { scrollbar_value = scrollbar_maximum; emit(EventScrollBarChanged, this); return true; } } return false; } bool ScrollBar::on_mousewheel(const math::Vector2f & direction) { if (direction.y() > 0 ) { if (scrollbar_value > scrollbar_minimum) { scrollbar_value--; emit(EventScrollBarChanged, this); } return true; } else if (direction.y() < 0 ) { if (scrollbar_value < scrollbar_maximum) { scrollbar_value++; emit(EventScrollBarChanged, this); } return true; } return false; } bool ScrollBar::on_mousepress(const unsigned int button) { if (button == SDL_BUTTON_LEFT) { if (scrollbar_maximum > scrollbar_minimum) { // TODO position hit test scrollbar_dragging = true; } return true; } return false; } bool ScrollBar::on_mouserelease(const unsigned int button) { if (button == SDL_BUTTON_LEFT) { scrollbar_dragging = false; return true; } return false; } void ScrollBar::on_mousemove(const math::Vector2f &cursor) { if ((width() <= 0) || (height() <= 0)) { return; } if (scrollbar_dragging && (scrollbar_maximum > scrollbar_minimum)) { float y = cursor.y(); math::clamp(y, 2.0f * width() , height() - 2.0f * width()); const float h = (height() - 4.0f * width()); const float s = h / (scrollbar_maximum - scrollbar_minimum); const float p = y - 2.0f * width(); const float newvalue = scrollbar_minimum + round(p / s); if (scrollbar_value != newvalue) { scrollbar_value = newvalue; emit(EventScrollBarChanged, this); } } } void ScrollBar::on_mouseover(const math::Vector2f &cursor) { scrollbar_dragging = false; } void ScrollBar::show() { Widget::show(); resize(); } void ScrollBar::resize() { // note: scrollbar expects height > width scrollbar_minbutton->set_size(width(), width()); scrollbar_minbutton->set_location(0, 0); scrollbar_decbutton->set_size(width(), width()); scrollbar_decbutton->set_location(0, scrollbar_minbutton->bottom()); scrollbar_maxbutton->set_size(width(), width()); scrollbar_maxbutton->set_location(0, height() - scrollbar_maxbutton->height()); scrollbar_incbutton->set_size(width(), width()); scrollbar_incbutton->set_location(0, scrollbar_maxbutton->top() - scrollbar_incbutton->height()); } void ScrollBar::draw() { if (scrollbar_maximum > scrollbar_minimum) { const float range = (scrollbar_value - scrollbar_minimum) / (scrollbar_maximum - scrollbar_minimum); const float y = (height() - 5.0f * width()) * range; if (scrollbar_dragging) { Paint::set_color(palette()->highlight()); } else { Paint::set_color(palette()->foreground()); } Paint::draw_rectangle( math::Vector2f(global_location().x() + 1.0f, global_location().y() + 2.0f * width() + y + 1.0f), math::Vector2f(width() - 2, width() - 2) ); } Widget::draw(); } } // namespace ui