From 2869ef7cec7de6bc744cdba9e753dbd0df4ab65b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 2 Aug 2024 23:38:23 +0200 Subject: Add widgets for settings page, add list to auto position widgets --- src/gui/ComboBox.cpp | 7 +++- src/gui/DropdownButton.cpp | 13 ++++++- src/gui/List.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++++++ src/gui/Page.cpp | 1 + src/gui/ScrollablePage.cpp | 22 +++++++----- src/gui/StaticPage.cpp | 22 +++++++----- src/gui/Widget.cpp | 14 ++++++++ 7 files changed, 144 insertions(+), 20 deletions(-) create mode 100644 src/gui/List.cpp (limited to 'src/gui') diff --git a/src/gui/ComboBox.cpp b/src/gui/ComboBox.cpp index 81c804f..03e66bd 100644 --- a/src/gui/ComboBox.cpp +++ b/src/gui/ComboBox.cpp @@ -33,6 +33,7 @@ namespace gsr { if(mgl::FloatRect(pos - mgl::vec2f(padding_left, padding_top), item_size).contains(mouse_pos)) { selected_item = i; show_dropdown = false; + remove_widget_as_selected_in_parent(); return false; } pos.y += text_bounds.size.y + padding_top + padding_bottom; @@ -42,9 +43,13 @@ namespace gsr { if(mgl::FloatRect(draw_pos, item_size).contains(mouse_pos)) { show_dropdown = !show_dropdown; if(show_dropdown) - move_to_top = true; + set_widget_as_selected_in_parent(); + else + remove_widget_as_selected_in_parent(); + return false; } else { show_dropdown = false; + remove_widget_as_selected_in_parent(); } } return true; diff --git a/src/gui/DropdownButton.cpp b/src/gui/DropdownButton.cpp index bfda834..b20dbb4 100644 --- a/src/gui/DropdownButton.cpp +++ b/src/gui/DropdownButton.cpp @@ -37,9 +37,20 @@ namespace gsr { } } else if(event.type == mgl::Event::MouseButtonPressed) { const bool clicked_inside = mouse_inside; + + if(show_dropdown && clicked_inside && mouse_inside_item == -1) { + show_dropdown = false; + remove_widget_as_selected_in_parent(); + return false; + } + show_dropdown = clicked_inside; + if(show_dropdown) - move_to_top = true; + set_widget_as_selected_in_parent(); + else + remove_widget_as_selected_in_parent(); + if(mouse_inside_item >= 0 && mouse_inside_item < (int)items.size()) { if(on_click) on_click(items[mouse_inside_item].id); diff --git a/src/gui/List.cpp b/src/gui/List.cpp new file mode 100644 index 0000000..10be76f --- /dev/null +++ b/src/gui/List.cpp @@ -0,0 +1,85 @@ +#include "../../include/gui/List.hpp" + +namespace gsr { + // TODO: Make this modifiable, multiple by window size. + // TODO: Add homogeneous option, using a specified max size of this list. + static const mgl::vec2f spacing(30.0f, 10.0f); + + List::List(Orientation orientation) : orientation(orientation) {} + + bool List::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f) { + if(selected_child_widget) { + if(!selected_child_widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + return false; + } + + // Process widgets by visibility (backwards) + for(auto it = widgets.rbegin(), end = widgets.rend(); it != end; ++it) { + // Ignore offset because widgets are positioned with offset in ::draw, this solution is simpler + if(it->get() != selected_child_widget) { + if(!(*it)->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + return false; + } + } + + return true; + } + + void List::draw(mgl::Window &window, mgl::vec2f offset) { + mgl::vec2f draw_pos = position + offset; + + // TODO: Do same vertical/horizontal alignment for items + switch(orientation) { + case Orientation::VERTICAL: { + for(auto &widget : widgets) { + widget->set_position(draw_pos); + if(widget.get() != selected_child_widget) + widget->draw(window, mgl::vec2f(0.0f, 0.0f)); + draw_pos.y += widget->get_size().y + spacing.y; + } + break; + } + case Orientation::HORIZONTAL: { + for(auto &widget : widgets) { + widget->set_position(draw_pos); + if(widget.get() != selected_child_widget) + widget->draw(window, mgl::vec2f(0.0f, 0.0f)); + draw_pos.x += widget->get_size().x + spacing.x; + } + break; + } + } + + if(selected_child_widget) + selected_child_widget->draw(window, mgl::vec2f(0.0f, 0.0f)); + } + + void List::add_widget(std::unique_ptr widget) { + widget->parent_widget = this; + widgets.push_back(std::move(widget)); + } + + // TODO: Cache result + mgl::vec2f List::get_size() { + mgl::vec2f size; + switch(orientation) { + case Orientation::VERTICAL: { + for(auto &widget : widgets) { + const auto widget_size = widget->get_size(); + size.x = std::max(size.x, widget_size.x); + size.y += widget_size.y + spacing.y; + } + break; + } + case Orientation::HORIZONTAL: { + for(auto &widget : widgets) { + const auto widget_size = widget->get_size(); + size.x += widget_size.x + spacing.x; + size.y = std::max(size.y, widget_size.y); + } + break; + } + } + return size; + } +} \ No newline at end of file diff --git a/src/gui/Page.cpp b/src/gui/Page.cpp index 19e3f2c..7d43c00 100644 --- a/src/gui/Page.cpp +++ b/src/gui/Page.cpp @@ -2,6 +2,7 @@ namespace gsr { void Page::add_widget(std::unique_ptr widget) { + widget->parent_widget = this; widgets.push_back(std::move(widget)); } } \ No newline at end of file diff --git a/src/gui/ScrollablePage.cpp b/src/gui/ScrollablePage.cpp index 7394ec3..de036b9 100644 --- a/src/gui/ScrollablePage.cpp +++ b/src/gui/ScrollablePage.cpp @@ -11,10 +11,17 @@ namespace gsr { const mgl::vec2f draw_pos = position + offset; offset = draw_pos + mgl::vec2f(0.0f, get_border_size(window)).floor(); + if(selected_child_widget) { + if(!selected_child_widget->on_event(event, window, offset)) + return false; + } + // Process widgets by visibility (backwards) for(auto it = widgets.rbegin(), end = widgets.rend(); it != end; ++it) { - if(!(*it)->on_event(event, window, offset)) - return false; + if(it->get() != selected_child_widget) { + if(!(*it)->on_event(event, window, offset)) + return false; + } } return true; @@ -44,15 +51,12 @@ namespace gsr { window.draw(border); for(auto &widget : widgets) { - if(widget->move_to_top) { - widget->move_to_top = false; - std::swap(widget, widgets.back()); - } + if(widget.get() != selected_child_widget) + widget->draw(window, offset); } - for(auto &widget : widgets) { - widget->draw(window, offset); - } + if(selected_child_widget) + selected_child_widget->draw(window, offset); mgl_window_set_scissor(window.internal_window(), &prev_scissor); } diff --git a/src/gui/StaticPage.cpp b/src/gui/StaticPage.cpp index a5b89cd..1194d0f 100644 --- a/src/gui/StaticPage.cpp +++ b/src/gui/StaticPage.cpp @@ -9,10 +9,17 @@ namespace gsr { const mgl::vec2f draw_pos = position + offset; offset = draw_pos; + if(selected_child_widget) { + if(!selected_child_widget->on_event(event, window, offset)) + return false; + } + // Process widgets by visibility (backwards) for(auto it = widgets.rbegin(), end = widgets.rend(); it != end; ++it) { - if(!(*it)->on_event(event, window, offset)) - return false; + if(it->get() != selected_child_widget) { + if(!(*it)->on_event(event, window, offset)) + return false; + } } return true; @@ -32,15 +39,12 @@ namespace gsr { mgl_window_set_scissor(window.internal_window(), &new_scissor); for(auto &widget : widgets) { - if(widget->move_to_top) { - widget->move_to_top = false; - std::swap(widget, widgets.back()); - } + if(widget.get() != selected_child_widget) + widget->draw(window, offset); } - for(auto &widget : widgets) { - widget->draw(window, offset); - } + if(selected_child_widget) + selected_child_widget->draw(window, offset); mgl_window_set_scissor(window.internal_window(), &prev_scissor); } diff --git a/src/gui/Widget.cpp b/src/gui/Widget.cpp index 1dc4d98..3e966e5 100644 --- a/src/gui/Widget.cpp +++ b/src/gui/Widget.cpp @@ -16,4 +16,18 @@ namespace gsr { mgl::vec2f Widget::get_position() const { return position; } + + void Widget::set_widget_as_selected_in_parent() { + if(parent_widget) { + parent_widget->selected_child_widget = this; + parent_widget->set_widget_as_selected_in_parent(); + } + } + + void Widget::remove_widget_as_selected_in_parent() { + if(parent_widget && parent_widget->selected_child_widget == this) { + parent_widget->selected_child_widget = nullptr; + parent_widget->remove_widget_as_selected_in_parent(); + } + } } \ No newline at end of file -- cgit v1.2.3