diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/scrollbar.cc | 226 | ||||
-rw-r--r-- | src/ui/scrollbar.h | 121 |
2 files changed, 347 insertions, 0 deletions
diff --git a/src/ui/scrollbar.cc b/src/ui/scrollbar.cc new file mode 100644 index 0000000..9be1432 --- /dev/null +++ b/src/ui/scrollbar.cc @@ -0,0 +1,226 @@ +/* + 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/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_keypress(const int key, const unsigned int modifier) +{ + switch (key) { + + case 512 + SDL_BUTTON_WHEELDOWN: + if (scrollbar_value < scrollbar_maximum) { + scrollbar_value++; + emit(EventScrollBarChanged, this); + } + return true; + break; + + case 512 + SDL_BUTTON_WHEELUP: + if (scrollbar_value > scrollbar_minimum) { + scrollbar_value--; + emit(EventScrollBarChanged, this); + } + return true; + break; + + case 512 + SDL_BUTTON_LEFT: + if (scrollbar_maximum > scrollbar_minimum) { + // TODO position hit test + scrollbar_dragging = true; + } + return true; + break; + + default: + break; + } + + return false; +} + +bool ScrollBar::on_keyrelease(const int key, const unsigned int modifier) +{ + if (key == 512 + 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)) { + // total width of dragable area + if ((cursor.y() >= 2.0f * width()) && (cursor.y() <= height() - 2.0f * width())) { + + const float h = (height() - 4.0f * width()); + const float s = h / (scrollbar_maximum - scrollbar_minimum); + const float p = cursor.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 diff --git a/src/ui/scrollbar.h b/src/ui/scrollbar.h new file mode 100644 index 0000000..0689969 --- /dev/null +++ b/src/ui/scrollbar.h @@ -0,0 +1,121 @@ +/* + ui/scrollbar.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_SCROLLBAR_H__ +#define __INCLUDED_UI_SCROLLBAR_H__ + +#include <string> +#include "ui/button.h" +#include "ui/widget.h" + +namespace ui +{ + +/** + * @brief a scrollbar widget + */ +class ScrollBar : public Widget +{ +public: + ScrollBar(Widget *parent, const float minimum = 0.0f, const float maximum = 1.0f); + + ~ScrollBar(); + + /** + * @brief the current slider value + */ + inline const float value() const { + return scrollbar_value; + } + + /** + * @brief the minimum value + */ + inline const float minimum() const { + return scrollbar_minimum; + } + + /** + * @brief the maximum value + */ + inline const float maximum() const { + return scrollbar_maximum; + } + + /** + * @brief print widget description to console + */ + virtual void print(const size_t indent) const; + + /** + * @brief set the current slider value + * @see value + */ + void set_value(const float value); + + /** + * @brief set the minimum slider value + * @see minimum + */ + void set_minimum(const float minimum); + + /** + * @brief set the maximum slider value + * @see maximum + */ + void set_maximum(const float maximum); + + /** + * @brief set the minimum and maximum slider values + * @see minimum + * @see maximum + */ + void set_range(const float minimum, const float maximum); + + /// show the widget + virtual void show(); + +protected: + + /// resize event handler + virtual void resize(); + + /// draw event handler + virtual void draw(); + + /// emit event handler + virtual bool on_emit(Widget *sender, const Event event, void *data=0); + + /// keypress event handler + virtual bool on_keypress(const int key, const unsigned int modifier); + + /// keyrelease event handler + virtual bool on_keyrelease(const int key, const unsigned int modifier); + + virtual void on_mouseover(const math::Vector2f &cursor); + + /// mouse movement handler + virtual void on_mousemove(const math::Vector2f &cursor); + +private: + /// validate slider value + void validate(); + + float scrollbar_minimum; + float scrollbar_maximum; + float scrollbar_value; + bool scrollbar_dragging; + + Button *scrollbar_minbutton; + Button *scrollbar_decbutton; + Button *scrollbar_incbutton; + Button *scrollbar_maxbutton; +}; + +} + +#endif // __INCLUDED_UI_SCROLLBAR_H__ + |