From b6e20e04b519e50909331f537df2ea6114a137ee Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 23 Jul 2016 19:16:28 +0200 Subject: General ui code improvements, moved layout related variables to ui::UI, added ColorPicker widget. --- src/ui/Makefile.am | 2 + src/ui/bitmap.cc | 4 ++ src/ui/colorpicker.cc | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ui/colorpicker.h | 71 +++++++++++++++++++++++++++ src/ui/definitions.h | 2 - src/ui/inputbox.cc | 107 ++++++++++++++++++++++++++--------------- src/ui/inputbox.h | 47 +++++++++++++----- src/ui/modelview.cc | 0 src/ui/modelview.h | 0 src/ui/scrollbar.cc | 1 + src/ui/scrollbar.h | 8 +-- src/ui/slider.cc | 3 +- src/ui/slider.h | 2 +- src/ui/ui.cc | 18 ++++--- src/ui/ui.h | 6 ++- 15 files changed, 336 insertions(+), 66 deletions(-) create mode 100644 src/ui/colorpicker.cc create mode 100644 src/ui/colorpicker.h mode change 100755 => 100644 src/ui/modelview.cc mode change 100755 => 100644 src/ui/modelview.h diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am index e309dda..340f8fb 100644 --- a/src/ui/Makefile.am +++ b/src/ui/Makefile.am @@ -11,6 +11,7 @@ endif noinst_HEADERS = \ bitmap.h \ button.h \ + colorpicker.h \ console.h \ definitions.h \ font.h \ @@ -34,6 +35,7 @@ noinst_HEADERS = \ libui_la_SOURCES = \ bitmap.cc \ button.cc \ + colorpicker.cc \ console.cc \ font.cc \ iconbutton.cc \ diff --git a/src/ui/bitmap.cc b/src/ui/bitmap.cc index 5caf966..6befa3a 100644 --- a/src/ui/bitmap.cc +++ b/src/ui/bitmap.cc @@ -58,6 +58,10 @@ void Bitmap::draw_background() { if (bitmap_texture.size()) { Paint::draw_bitmap(global_location(), size(), bitmap_color, bitmap_texture, bitmap_preserve_aspect); + } else { + Paint::set_color(bitmap_color); + Paint::draw_rectangle(global_location(), size()); + Paint::set_color(palette()->foreground()); } } diff --git a/src/ui/colorpicker.cc b/src/ui/colorpicker.cc new file mode 100644 index 0000000..4180334 --- /dev/null +++ b/src/ui/colorpicker.cc @@ -0,0 +1,131 @@ +/* + ui/colorpicker.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/bitmap.h" +#include "ui/colorpicker.h" +#include "ui/slider.h" +#include "ui/label.h" +#include "ui/ui.h" + +#include "math/functions.h" + +namespace ui +{ + +ColorPicker::ColorPicker(Widget *parent) : Widget(parent) +{ + set_label("colorpicker"); + + _label_red = new Label(this, "R"); + _label_red->set_alignment(AlignLeft | AlignVCenter); + _label_red->set_border(false); + _label_red->set_background(false); + _slider_red = new Slider(this, 0.0f, 255.0f); + + _label_green = new Label(this, "G"); + _label_green->set_alignment(AlignLeft | AlignVCenter); + _label_green->set_border(false); + _label_green->set_background(false); + _slider_green = new Slider(this, 0.0f, 255.0f); + + _label_blue = new Label(this, "B"); + _label_blue->set_alignment(AlignLeft | AlignVCenter); + _label_blue->set_border(false); + _label_blue->set_background(false); + _slider_blue = new Slider(this, 0.0f, 255.0f); + + _color_preview = new Bitmap(this); + _color_preview->set_label("preview"); + _color_preview->set_border(true); + + color_changed(); +} + +ColorPicker::~ColorPicker() +{ +} + +void ColorPicker::set_color(const math::Color & color) +{ + _color.assign(color); + color_changed(); +} + +void ColorPicker::set_color(const float r, const float g, const float b) +{ + _color.assign(r, g, b); + color_changed(); +} + +void ColorPicker::color_changed() +{ + _slider_red->set_value(_color.red() * 255.0f); + _slider_green->set_value(_color.green() * 255.0f); + _slider_blue->set_value(_color.blue() * 255.0f); + _color_preview->set_color(_color); +} + +void ColorPicker::resize() +{ + const float margin = UI::margin; + const float w = font()->width() * 3.0f; + const float h = (height() - margin * 4.0f) / 3.0f; + + const float r = math::min(width(), height()) - 2.0f * margin; + + // resize color preview + _color_preview->set_size(r,r); + _color_preview->set_location(width() - r - margin, height() - r - margin); + + // resize red channel label + _label_red->set_size(w, h); + _label_red->set_location(margin, margin); + // resize red channel slider + _slider_red->set_location(_label_red->right(), _label_red->top()); + _slider_red->set_size(_color_preview->left() - _label_red->right() - 2.0f * margin, h); + + _label_green->set_size(w, h); + _label_green->set_location(margin, 2.0f * margin + h); + // resize green channel slider + _slider_green->set_location(_label_green->right(), _label_green->top()); + _slider_green->set_size(_color_preview->left() - _label_green->right() - 2.0f * margin, h); + + _label_blue->set_size(w, h); + _label_blue->set_location(margin, 3.0f * margin + 2.0f * h); + // resize blue channel slider + _slider_blue->set_location(_label_blue->right(), _label_blue->top()); + _slider_blue->set_size(_color_preview->left() - _label_blue->right() - 2.0f * margin, h); +} + +bool ColorPicker::on_emit(Widget *sender, const Event event, void *data) +{ + if (event == ui::Widget::EventSliderChanged) + { + if (sender == _slider_red) + { + _color[0] = _slider_red->value() / 255.0f; + _color_preview->set_color(_color); + return true; + } + else if (sender == _slider_green) + { + _color[1] = _slider_green->value() / 255.0f; + _color_preview->set_color(_color); + return true; + } + else if (sender == _slider_blue) + { + _color[2] = _slider_blue->value() / 255.0f; + _color_preview->set_color(_color); + return true; + } + } + + // unhandled event + return false; +} + +} diff --git a/src/ui/colorpicker.h b/src/ui/colorpicker.h new file mode 100644 index 0000000..e2c0cb5 --- /dev/null +++ b/src/ui/colorpicker.h @@ -0,0 +1,71 @@ +/* + ui/colorpicker.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_COLORPICKER_H__ +#define __INCLUDED_UI_COLORPICKER_H__ + +#include "ui/widget.h" + +namespace ui +{ + +class Bitmap; +class Label; +class Slider; + +class ColorPicker : public Widget +{ +public: + ColorPicker(Widget *parent); + ~ColorPicker(); + + /** + * @brief current selected color + * */ + inline const math::Color color() const { + return _color; + } + + /** + * @brief set selected color + * */ + void set_color(const math::Color & color); + + /** + * @brief set selected color + * */ + void set_color(const float r, const float g, const float b); + +protected: + /// resize event handler + virtual void resize(); + + /** + * @brief emit event handler + * */ + virtual bool on_emit(ui::Widget *sender, const ui::Widget::Event event, void *data); + + +private: + void color_changed(); + + Label *_label_red; + Slider *_slider_red; + + Label *_label_green; + Slider *_slider_green; + + Label *_label_blue; + Slider *_slider_blue; + + Bitmap *_color_preview; + + math::Color _color; +}; + +} + +#endif // __INCLUDED_UI_COLORPICKER_H__ diff --git a/src/ui/definitions.h b/src/ui/definitions.h index 02698f4..19cdf82 100644 --- a/src/ui/definitions.h +++ b/src/ui/definitions.h @@ -26,8 +26,6 @@ enum Alignment { AlignCenter = AlignHCenter | AlignVCenter }; -const float pointer_size = 48.0f; - typedef std::deque Text; } diff --git a/src/ui/inputbox.cc b/src/ui/inputbox.cc index 89e3243..a7565e7 100644 --- a/src/ui/inputbox.cc +++ b/src/ui/inputbox.cc @@ -4,6 +4,7 @@ the terms of the GNU General Public License version 2 */ +#include "ui/definitions.h" #include "ui/inputbox.h" #include "ui/paint.h" #include "auxiliary/functions.h" @@ -15,13 +16,14 @@ namespace ui InputBox::InputBox(Widget *parent) : Widget(parent) { - input_text.clear(); - input_pos = 0; - input_max = 512; + _text.clear(); + _pos = 0; + _max = 512; set_label("input"); set_background(false); set_border(false); + set_alignment(AlignLeft | AlignTop); } InputBox::~InputBox() @@ -30,58 +32,75 @@ InputBox::~InputBox() void InputBox::clear() { - input_text.clear(); - input_pos = 0; + _text.clear(); + _pos = 0; } void InputBox::set_text(std::string const &text) { - input_text.assign(text); - input_pos = input_text.size(); + _text.assign(text); + _pos = _text.size(); } void InputBox::set_text(const char *text) { if (text) - input_text.assign(text); + _text.assign(text); else - input_text.clear(); - input_pos = input_text.size(); + _text.clear(); + _pos = _text.size(); } void InputBox::set_prompt(const std::string &prompt) { - input_prompt.assign(prompt); + _prompt.assign(prompt); } void InputBox::set_prompt(const char *prompt) { if (!prompt) - input_prompt.clear(); + _prompt.clear(); else - input_prompt.assign(prompt); + _prompt.assign(prompt); } void InputBox::set_max(const size_t max) { - input_max = max; + _max = max; +} + +void InputBox::set_alignment(const unsigned int alignment) +{ + _alignment = alignment; } void InputBox::draw() { + size_t text_width = (size_t) floorf(width() / font()->width()); - size_t prompt_width = aux::text_length(input_prompt); + size_t prompt_width = aux::text_length(_prompt); math::Vector2f v(global_location()); Paint::set_color(palette()->text()); + + // Horizontal alignment + // FIXME horizontal alignment is not supported + + // Vertical alignment + if (alignment() & ui::AlignVCenter) { + v.get_y() += (height() - font()->height()) * 0.5f; + + } else if (alignment() & ui::AlignBottom) { + v.get_y() += height() - font()->height(); + } // draw the prompt if (prompt_width) { - Paint::draw_text(v, font(), input_prompt); + Paint::draw_text(v, font(), _prompt); v[0] += prompt_width * font()->width(); } Paint::set_color(palette()->text()); // draw the part before the cursor - std::string firstpart(input_text.substr(0, input_pos)); + std::string firstpart(_text.substr(0, _pos)); size_t draw_width = 0; const char *c = firstpart.c_str(); @@ -111,13 +130,13 @@ void InputBox::draw() // draw the part behind the cursor v[0] += draw_width * font()->width(); - if (input_pos < input_text.size()) { - if (input_pos > 1 && aux::is_color_code(input_text.c_str() + input_pos - 1)) { - Paint::set_system_color(input_text[input_pos]); + if (_pos < _text.size()) { + if (_pos > 1 && aux::is_color_code(_text.c_str() + _pos - 1)) { + Paint::set_system_color(_text[_pos]); } // limit to width std::string secondpart; - c = &input_text.c_str()[input_pos]; + c = &_text.c_str()[_pos]; while (*c && (draw_width <= (text_width - prompt_width - 1))) { if (aux::is_color_code(c)) { c++; @@ -144,58 +163,58 @@ void InputBox::draw() void InputBox::complete() { - core::CommandBuffer::complete(input_text, input_pos); + core::CommandBuffer::complete(_text, _pos); } bool InputBox::on_keypress(const int key, const unsigned int modifier) { switch (key) { case SDLK_HOME: - input_pos = 0; + _pos = 0; return true; break; case SDLK_END: - input_pos = input_text.size(); + _pos = _text.size(); return true; break; case SDLK_LEFT: - if (input_pos > 0) - input_pos--; + if (_pos > 0) + _pos--; return true; break; case SDLK_RIGHT: - if (input_pos < input_text.size()) - input_pos++; + if (_pos < _text.size()) + _pos++; return true; break; case SDLK_DELETE: - if (input_text.size() && input_pos < input_text.size()) { - input_text.erase(input_pos, 1); + if (_text.size() && _pos < _text.size()) { + _text.erase(_pos, 1); } return true; break; case SDLK_BACKSPACE: - if (input_text.size() && input_pos) { - input_text.erase(input_pos - 1, 1); - input_pos--; + if (_text.size() && _pos) { + _text.erase(_pos - 1, 1); + _pos--; } return true; break; default: if ((key >= 32) && (key < 175)) { - if (input_text.size() < input_max) { + if (_text.size() < _max) { // TODO bell sound - if (input_pos == input_text.size()) - input_text += (char)key; + if (_pos == _text.size()) + _text += (char)key; else - input_text.insert(input_pos, 1, (char)key); - input_pos++; + _text.insert(_pos, 1, (char)key); + _pos++; } return true; } @@ -204,11 +223,23 @@ bool InputBox::on_keypress(const int key, const unsigned int modifier) return false; } + bool InputBox::on_keyrelease(const int key, const unsigned int modifier) { return false; } +bool InputBox::on_mousepress(const unsigned int button) +{ + if (button == SDL_BUTTON_LEFT) + { + set_focus(); + return true; + } + + return false; +} + } diff --git a/src/ui/inputbox.h b/src/ui/inputbox.h index 5da9bc5..20dd9b5 100644 --- a/src/ui/inputbox.h +++ b/src/ui/inputbox.h @@ -18,6 +18,16 @@ class InputBox : public Widget public: InputBox(Widget *parent); ~InputBox(); + + /// text alignment + inline unsigned int alignment() const { + return _alignment; + } + + /// return the text displayed by the label + inline const std::string &text() const { + return _text; + } /// set the text displayed by the label void set_text(const std::string &text); @@ -31,14 +41,12 @@ public: /// set the prompt void set_prompt(const char *prompt); - /// set the maximal input width + /// set the maximal input length void set_max(const size_t max); - - /// return the text displayed by the label - inline const std::string &text() const { - return input_text; - } + /// set the text alignment + void set_alignment(const unsigned int alignment); + /// clear the text void clear(); @@ -46,21 +54,34 @@ public: void complete(); protected: - /// draw the widget + /** + * @brief draw the windget + * */ virtual void draw(); - /// called when the widget receives a key press + /** + * @brief key press event handler + * */ virtual bool on_keypress(const int key, const unsigned int modifier); - /// called when the widget receives a key release + /** + * @brief key release event handler + * */ virtual bool on_keyrelease(const int key, const unsigned int modifier); + + /** + * @brief mouse button press event handler + * */ + virtual bool on_mousepress(const unsigned int button); private: - std::string input_text; - std::string input_prompt; - size_t input_pos; - size_t input_max; + std::string _text; + std::string _prompt; + size_t _pos; + size_t _max; + + unsigned int _alignment; }; } diff --git a/src/ui/modelview.cc b/src/ui/modelview.cc old mode 100755 new mode 100644 diff --git a/src/ui/modelview.h b/src/ui/modelview.h old mode 100755 new mode 100644 diff --git a/src/ui/scrollbar.cc b/src/ui/scrollbar.cc index 38410f4..9469b6a 100644 --- a/src/ui/scrollbar.cc +++ b/src/ui/scrollbar.cc @@ -5,6 +5,7 @@ */ #include "math/functions.h" +#include "ui/button.h" #include "ui/paint.h" #include "ui/scrollbar.h" diff --git a/src/ui/scrollbar.h b/src/ui/scrollbar.h index c8eccf9..d2a8bbb 100644 --- a/src/ui/scrollbar.h +++ b/src/ui/scrollbar.h @@ -8,14 +8,16 @@ #define __INCLUDED_UI_SCROLLBAR_H__ #include -#include "ui/button.h" + #include "ui/widget.h" namespace ui { + +class Button; /** - * @brief a scrollbar widget + * @brief a scrollbar widget with a vertical layout. */ class ScrollBar : public Widget { @@ -23,7 +25,7 @@ public: ScrollBar(Widget *parent, const float minimum = 0.0f, const float maximum = 1.0f); ~ScrollBar(); - + /** * @brief the current slider value */ diff --git a/src/ui/slider.cc b/src/ui/slider.cc index ee29f05..1fcaada 100644 --- a/src/ui/slider.cc +++ b/src/ui/slider.cc @@ -135,10 +135,11 @@ 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; + slider_dragging = true; } return true; } diff --git a/src/ui/slider.h b/src/ui/slider.h index 2f71c39..df28b6f 100644 --- a/src/ui/slider.h +++ b/src/ui/slider.h @@ -15,7 +15,7 @@ namespace ui { /** - * @brief a slider widget + * @brief a slider widget with a horizontal orientation */ class Slider : public Widget { diff --git a/src/ui/ui.cc b/src/ui/ui.cc index 1502419..0877519 100644 --- a/src/ui/ui.cc +++ b/src/ui/ui.cc @@ -29,8 +29,10 @@ bool UI::ui_debug = false; math::Vector2f UI::elementsize(256, 32); -float UI::spacing = 16.0f; -float UI::margin = 8.0f; +float UI::padding = 24.0f; +float UI::margin = 16.0f; + +float UI::pointer_size = 48.0f; UI *global_ui = 0; @@ -121,8 +123,9 @@ void UI::load_settings() float w = elementsize.width(); float h = elementsize.height(); - float m = spacing; - float s = spacing; + float m = margin; + float s = padding; + float p = pointer_size; while (ini.getline()) { @@ -160,8 +163,11 @@ void UI::load_settings() } else if (ini.got_key_float("margin", m)) { margin = m; continue; - } else if (ini.got_key_float("spacing", s)) { - spacing = s; + } else if (ini.got_key_float("pointer", p)) { + pointer_size = p; + continue; + } else if (ini.got_key_float("padding", s)) { + padding = s; continue; } else { ini.unknown_key(); diff --git a/src/ui/ui.h b/src/ui/ui.h index 4b5d2da..aaf4acc 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -98,15 +98,17 @@ public: * */ static math::Vector2f elementsize; /** - * global spacing between ui elements, used by resize() functions + * global padding between ui elements, used by resize() functions * */ - static float spacing; + static float padding; /** * global margin for frames and widgets, used by resize() functions * see @Widget::resize(); * */ static float margin; + static float pointer_size; + protected: /* -- event handlers --------------------------------------- */ -- cgit v1.2.3