From 4ea5ada9050d22fcb7eed67a72358bce11c9b3df Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 10 Aug 2024 00:45:36 +0200 Subject: Settings page save settings, refactor --- src/gui/ComboBox.cpp | 9 + src/gui/Entry.cpp | 12 +- src/gui/List.cpp | 57 +++-- src/gui/RadioButton.cpp | 9 + src/gui/SettingsPage.cpp | 628 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 696 insertions(+), 19 deletions(-) create mode 100644 src/gui/SettingsPage.cpp (limited to 'src/gui') diff --git a/src/gui/ComboBox.cpp b/src/gui/ComboBox.cpp index 373b06b..f23a323 100644 --- a/src/gui/ComboBox.cpp +++ b/src/gui/ComboBox.cpp @@ -161,6 +161,15 @@ namespace gsr { } } + const std::string& ComboBox::get_selected_id() const { + if(items.empty()) { + static std::string dummy; + return dummy; + } else { + return items[selected_item].id; + } + } + void ComboBox::update_if_dirty() { if(!dirty) return; diff --git a/src/gui/Entry.cpp b/src/gui/Entry.cpp index f337bcf..7978b38 100644 --- a/src/gui/Entry.cpp +++ b/src/gui/Entry.cpp @@ -18,7 +18,7 @@ namespace gsr { Entry::Entry(mgl::Font *font, const char *text, float max_width) : text("", *font), max_width(max_width) { this->text.set_color(get_theme().text_color); - set_string(text); + set_text(text); } bool Entry::on_event(mgl::Event &event, mgl::Window&, mgl::vec2f offset) { @@ -32,12 +32,12 @@ namespace gsr { std::string str = text.get_string(); const size_t prev_index = mgl::utf8_get_start_of_codepoint((const unsigned char*)str.c_str(), str.size(), str.size()); str.erase(prev_index, std::string::npos); - set_string(std::move(str)); + set_text(std::move(str)); } } else if(event.type == mgl::Event::TextEntered && selected && event.text.codepoint >= 32) { std::string str = text.get_string(); str.append(event.text.str, event.text.size); - set_string(std::move(str)); + set_text(std::move(str)); } return true; } @@ -80,7 +80,7 @@ namespace gsr { return { max_width, text.get_bounds().size.y + padding_top + padding_bottom }; } - void Entry::set_string(std::string str) { + void Entry::set_text(std::string str) { if(!validate_handler || validate_handler(str)) { text.set_string(std::move(str)); caret_offset_x = text.find_character_pos(99999).x - this->text.get_position().x; @@ -88,6 +88,10 @@ namespace gsr { } } + const std::string& Entry::get_text() const { + return text.get_string(); + } + static bool is_number(uint8_t c) { return c >= '0' && c <= '9'; } diff --git a/src/gui/List.cpp b/src/gui/List.cpp index 039842d..883a797 100644 --- a/src/gui/List.cpp +++ b/src/gui/List.cpp @@ -15,22 +15,28 @@ namespace gsr { if(!visible) return true; + inside_event_handler = true; // We want to store the selected child widget since it can change in the event loop below Widget *selected_widget = selected_child_widget; if(selected_widget) { - if(!selected_widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + if(!selected_widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) { + inside_event_handler = false; 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_widget) { - if(!(*it)->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + if(!(*it)->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) { + inside_event_handler = false; return false; + } } } + inside_event_handler = false; return true; } @@ -72,7 +78,8 @@ namespace gsr { const mgl::vec2f spacing = (spacing_scale * get_theme().window_height).floor(); switch(orientation) { case Orientation::VERTICAL: { - for(auto &widget : widgets) { + for(size_t i = 0; i < widgets.size(); ++i) { + auto &widget = widgets[i]; if(!widget->visible) continue; @@ -91,25 +98,28 @@ namespace gsr { if(widget.get() != selected_widget) widget->draw(window, mgl::vec2f(0.0f, 0.0f)); draw_pos.y += widget_size.y; - if(widget_size.y > 0.001f) + if(widget_size.y > 0.001f && i + 1 < widgets.size()) draw_pos.y += spacing.y; } break; } case Orientation::HORIZONTAL: { - for(auto &widget : widgets) { + for(size_t i = 0; i < widgets.size(); ++i) { + auto &widget = widgets[i]; if(!widget->visible) continue; const auto widget_size = widget->get_size(); if(content_alignment == Alignment::CENTER) offset.y = floor(size.y * 0.5f - widget_size.y * 0.5f); + else + offset.y = 0.0f; widget->set_position(draw_pos + offset); if(widget.get() != selected_widget) widget->draw(window, mgl::vec2f(0.0f, 0.0f)); draw_pos.x += widget_size.x; - if(widget_size.x > 0.001f) + if(widget_size.x > 0.001f && i + 1 < widgets.size()) draw_pos.x += spacing.x; } break; @@ -131,9 +141,10 @@ namespace gsr { void List::add_widget(std::unique_ptr widget) { widget->parent_widget = this; - // TODO: Maybe only do this if this is called inside an event handler - //widgets.push_back(std::move(widget)); - add_queue.push_back(std::move(widget)); + if(inside_event_handler) + add_queue.push_back(std::move(widget)); + else + widgets.push_back(std::move(widget)); } void List::remove_widget(Widget *widget) { @@ -143,8 +154,22 @@ namespace gsr { return; } } - // TODO: Maybe only do this if this is called inside an event handler - remove_queue.push_back(widget); + + if(inside_event_handler) + remove_queue.push_back(widget); + else + remove_widget_immediate(widget); + } + + const std::vector>& List::get_child_widgets() const { + return widgets; + } + + Widget* List::get_child_widget_by_index(size_t index) const { + if(index < widgets.size()) + return widgets[index].get(); + else + return nullptr; } // TODO: Cache result @@ -156,26 +181,28 @@ namespace gsr { const mgl::vec2f spacing = (spacing_scale * get_theme().window_height).floor(); switch(orientation) { case Orientation::VERTICAL: { - for(auto &widget : widgets) { + for(size_t i = 0; i < widgets.size(); ++i) { + auto &widget = widgets[i]; if(!widget->visible) continue; const auto widget_size = widget->get_size(); size.x = std::max(size.x, widget_size.x); size.y += widget_size.y; - if(widget_size.y > 0.001f) + if(widget_size.y > 0.001f && i + 1 < widgets.size()) size.y += spacing.y; } break; } case Orientation::HORIZONTAL: { - for(auto &widget : widgets) { + for(size_t i = 0; i < widgets.size(); ++i) { + auto &widget = widgets[i]; if(!widget->visible) continue; const auto widget_size = widget->get_size(); size.x += widget_size.x; - if(widget_size.x > 0.001f) + if(widget_size.x > 0.001f && i + 1 < widgets.size()) size.x += spacing.x; size.y = std::max(size.y, widget_size.y); } diff --git a/src/gui/RadioButton.cpp b/src/gui/RadioButton.cpp index eb1f900..87428bf 100644 --- a/src/gui/RadioButton.cpp +++ b/src/gui/RadioButton.cpp @@ -135,4 +135,13 @@ namespace gsr { } } } + + const std::string RadioButton::get_selected_id() const { + if(items.empty()) { + static std::string dummy; + return dummy; + } else { + return items[selected_item].id; + } + } } \ No newline at end of file diff --git a/src/gui/SettingsPage.cpp b/src/gui/SettingsPage.cpp new file mode 100644 index 0000000..277bc3b --- /dev/null +++ b/src/gui/SettingsPage.cpp @@ -0,0 +1,628 @@ +#include "../../include/gui/SettingsPage.hpp" +#include "../../include/gui/ScrollablePage.hpp" +#include "../../include/gui/Label.hpp" +#include "../../include/Theme.hpp" +#include "../../include/GsrInfo.hpp" + +#include +#include +#include +#include + +namespace gsr { + SettingsPage::SettingsPage(Type type, const GsrInfo &gsr_info, const std::vector &audio_devices, std::optional &config) : + StaticPage(mgl::vec2f(get_theme().window_width, get_theme().window_height).floor()), + type(type), + config(config), + settings_title_text("Settings", get_theme().title_font) + { + const mgl::vec2f window_size = mgl::vec2f(get_theme().window_width, get_theme().window_height).floor(); + const mgl::vec2f content_page_size = (window_size * mgl::vec2f(0.3333f, 0.7f)).floor(); + const mgl::vec2f content_page_position = mgl::vec2f(window_size * 0.5f - content_page_size * 0.5f).floor(); + const float settings_body_margin = 0.02f; + + auto content_page = std::make_unique(content_page_size); + content_page->set_position(content_page_position); + content_page->set_margins(settings_body_margin, settings_body_margin, settings_body_margin, settings_body_margin); + content_page_ptr = content_page.get(); + add_widget(std::move(content_page)); + + add_widgets(gsr_info, audio_devices); + add_page_specific_widgets(); + } + + std::unique_ptr