diff options
author | dec05eba <dec05eba@protonmail.com> | 2024-08-22 21:44:06 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2024-08-23 18:53:19 +0200 |
commit | 54c60d9a18d103011a12939c5029dd35a8e9e200 (patch) | |
tree | fefba1d63a13df6c135a6b1f5e8640b12a9c0ff5 /src/gui | |
parent | ba007c2b69dca6813c86115b2c1834de45c886be (diff) |
Start on file chooser, page stack
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/Button.cpp | 4 | ||||
-rw-r--r-- | src/gui/ComboBox.cpp | 4 | ||||
-rw-r--r-- | src/gui/FileChooser.cpp | 174 | ||||
-rw-r--r-- | src/gui/GsrPage.cpp | 126 | ||||
-rw-r--r-- | src/gui/List.cpp | 63 | ||||
-rw-r--r-- | src/gui/PageStack.cpp | 58 | ||||
-rw-r--r-- | src/gui/RadioButton.cpp | 4 | ||||
-rw-r--r-- | src/gui/ScrollablePage.cpp | 44 | ||||
-rw-r--r-- | src/gui/SettingsPage.cpp | 82 |
9 files changed, 410 insertions, 149 deletions
diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp index e36d07b..20a771e 100644 --- a/src/gui/Button.cpp +++ b/src/gui/Button.cpp @@ -70,4 +70,8 @@ namespace gsr { void Button::set_border_scale(float scale) { border_scale = scale; } + + const std::string& Button::get_text() const { + return text.get_string(); + } }
\ No newline at end of file diff --git a/src/gui/ComboBox.cpp b/src/gui/ComboBox.cpp index f23a323..b344c4e 100644 --- a/src/gui/ComboBox.cpp +++ b/src/gui/ComboBox.cpp @@ -146,14 +146,14 @@ namespace gsr { dirty = true; } - void ComboBox::set_selected_item(const std::string &id, bool trigger_event) { + void ComboBox::set_selected_item(const std::string &id, bool trigger_event, bool trigger_event_even_if_selection_not_changed) { for(size_t i = 0; i < items.size(); ++i) { auto &item = items[i]; if(item.id == id) { const size_t prev_selected_item = selected_item; selected_item = i; - if(trigger_event && selected_item != prev_selected_item && on_selection_changed) + if(trigger_event && (trigger_event_even_if_selection_not_changed || selected_item != prev_selected_item) && on_selection_changed) on_selection_changed(item.text.get_string(), item.id); break; diff --git a/src/gui/FileChooser.cpp b/src/gui/FileChooser.cpp new file mode 100644 index 0000000..8cc5d74 --- /dev/null +++ b/src/gui/FileChooser.cpp @@ -0,0 +1,174 @@ +#include "../../include/gui/FileChooser.hpp" +#include "../../include/gui/Utils.hpp" +#include "../../include/Theme.hpp" +#include <mglpp/graphics/Rectangle.hpp> +#include <mglpp/graphics/Sprite.hpp> +#include <mglpp/window/Window.hpp> +#include <mglpp/window/Event.hpp> +#include <mglpp/system/FloatRect.hpp> +#include <dirent.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> + +namespace gsr { + static const float current_directory_padding_top_scale = 0.004629f; + static const float current_directory_padding_bottom_scale = 0.004629f; + static const float current_directory_padding_left_scale = 0.004629f; + static const float current_directory_padding_right_scale = 0.004629f; + static const float spacing_between_current_directory_and_content = 0.015f; + static const int num_columns = 6; + static const float content_padding_top_scale = 0.015f; + static const float content_padding_bottom_scale = 0.015f; + static const float content_padding_left_scale = 0.015f; + static const float content_padding_right_scale = 0.015f; + + FileChooser::FileChooser(const char *start_directory, mgl::vec2f content_size) : + content_size(content_size), current_directory_text(start_directory, get_theme().body_font) + { + set_current_directory(start_directory); + } + + bool FileChooser::on_event(mgl::Event &event, mgl::Window&, mgl::vec2f offset) { + if(!visible) + return true; + + if(event.type == mgl::Event::MouseButtonPressed && event.mouse_button.button == mgl::Mouse::Left) { + if(double_click_timer.get_elapsed_time_seconds() <= get_theme().double_click_timeout_seconds) { + ++times_clicked_within_timer; + } else { + times_clicked_within_timer = 1; + } + double_click_timer.restart(); + + selected_item = mouse_over_item; + + if(selected_item != -1 && times_clicked_within_timer > 0 && times_clicked_within_timer % 2 == 0) { + char new_directory[PATH_MAX]; + snprintf(new_directory, sizeof(new_directory), "%s/%s", current_directory_text.get_string().c_str(), folders[selected_item].get_string().c_str()); + set_current_directory(new_directory); + } + } + return true; + } + + void FileChooser::draw(mgl::Window &window, mgl::vec2f offset) { + mouse_over_item = -1; + + if(!visible) + return; + + const mgl::vec2f draw_pos = position + offset; + const mgl::vec2f current_directory_padding( + current_directory_padding_left_scale * get_theme().window_height + current_directory_padding_right_scale * get_theme().window_height, + current_directory_padding_top_scale * get_theme().window_height + current_directory_padding_bottom_scale * get_theme().window_height + ); + + mgl::Rectangle current_directory_background(mgl::vec2f(content_size.x, current_directory_text.get_bounds().size.y + current_directory_padding.y).floor()); + current_directory_background.set_color(mgl::Color(0, 0, 0, 120)); + current_directory_background.set_position(draw_pos.floor()); + window.draw(current_directory_background); + + current_directory_text.set_color(get_theme().text_color); + current_directory_text.set_position((draw_pos + mgl::vec2f(current_directory_padding.x, current_directory_background.get_size().y * 0.5f - current_directory_text.get_bounds().size.y * 0.5f)).floor()); + window.draw(current_directory_text); + + mgl::Rectangle content_background(content_size.floor()); + content_background.set_color(mgl::Color(0, 0, 0, 120)); + content_background.set_position((draw_pos + mgl::vec2f(0.0f, current_directory_background.get_size().y + spacing_between_current_directory_and_content * get_theme().window_height)).floor()); + window.draw(content_background); + + const mgl::vec2f mouse_pos = window.get_mouse_position().to_vec2f(); + + const int content_padding_top = content_padding_top_scale * get_theme().window_height; + const int content_padding_bottom = content_padding_bottom_scale * get_theme().window_height; + const int content_padding_left = content_padding_left_scale * get_theme().window_height; + const int content_padding_right = content_padding_right_scale * get_theme().window_height; + + const float folder_width = (int)((content_size.x - (content_padding_left + content_padding_right) * num_columns) / num_columns); + const float width_per_item_after = content_padding_right + folder_width + content_padding_left; + mgl::vec2f folder_pos = content_background.get_position() + mgl::vec2f(content_padding_left, content_padding_top); + for(int i = 0; i < (int)folders.size(); ++i) { + auto &folder_text = folders[i]; + + mgl::Sprite folder_sprite(&get_theme().folder_texture); + folder_sprite.set_position(folder_pos.floor()); + folder_sprite.set_width((int)folder_width); + + const mgl::vec2f item_pos = folder_pos - mgl::vec2f(content_padding_left, content_padding_top); + const mgl::vec2f item_size = folder_sprite.get_size() + mgl::vec2f(content_padding_left + content_padding_right, content_padding_top + content_padding_bottom); + if(i == selected_item) { + mgl::Rectangle selected_item_background(item_size.floor()); + selected_item_background.set_position(item_pos.floor()); + selected_item_background.set_color(get_theme().tint_color); + window.draw(selected_item_background); + } + if(!has_parent_with_selected_child_widget() && mouse_over_item == -1 && mgl::FloatRect(item_pos, item_size).contains(mouse_pos)) { + // mgl::Rectangle selected_item_background(item_size.floor()); + // selected_item_background.set_position(item_pos.floor()); + // selected_item_background.set_color(mgl::Color(20, 20, 20, 150)); + // window.draw(selected_item_background); + const float border_scale = 0.0015f; + draw_rectangle_outline(window, item_pos.floor(), item_size.floor(), get_theme().tint_color, border_scale * get_theme().window_height); + mouse_over_item = i; + } + + window.draw(folder_sprite); + + // TODO: Dont allow text to go further left/right than item_pos (on the left side) and item_pos + item_size (on the right side). + folder_text.set_position(folder_sprite.get_position() + mgl::vec2f(folder_sprite.get_size().x * 0.5f - folder_text.get_bounds().size.x * 0.5f, folder_sprite.get_size().y)); + window.draw(folder_text); + + folder_pos.x += width_per_item_after; + if(folder_pos.x + folder_width > content_background.get_position().x + content_size.x) { + folder_pos.x = content_background.get_position().x + content_padding_left; + folder_pos.y += content_padding_bottom + folder_sprite.get_size().y + content_padding_top; + } + } + } + + mgl::vec2f FileChooser::get_size() { + if(!visible) + return {0.0f, 0.0f}; + + const mgl::vec2f current_directory_padding( + current_directory_padding_left_scale * get_theme().window_height + current_directory_padding_right_scale * get_theme().window_height, + current_directory_padding_top_scale * get_theme().window_height + current_directory_padding_bottom_scale * get_theme().window_height + ); + return {content_size.x, current_directory_text.get_bounds().size.y + current_directory_padding.y + spacing_between_current_directory_and_content * get_theme().window_height + content_size.y}; + } + + static bool is_dir(struct dirent *dir, const char *parent_directory) { + if(dir->d_type == DT_DIR) + return true; + + char filepath[PATH_MAX]; + snprintf(filepath, sizeof(filepath), "%s/%s", parent_directory, dir->d_name); + + struct stat st; + return stat(filepath, &st) != -1 && S_ISDIR(st.st_mode); + } + + void FileChooser::set_current_directory(const char *directory) { + folders.clear(); + selected_item = -1; + mouse_over_item = -1; + current_directory_text.set_string(directory); + + DIR *d = opendir(directory); + if(!d) { + fprintf(stderr, "gsr-overlay error: failed to open directory: %s, error: %s\n", directory, strerror(errno)); + return; + } + + struct dirent *dir = NULL; + while((dir = readdir(d)) != NULL) { + /* Ignore hidden files */ + if(dir->d_name[0] == '.' || !is_dir(dir, directory)) + continue; + folders.push_back(mgl::Text(dir->d_name, get_theme().body_font)); + } + + closedir(d); + } +}
\ No newline at end of file diff --git a/src/gui/GsrPage.cpp b/src/gui/GsrPage.cpp new file mode 100644 index 0000000..db49ced --- /dev/null +++ b/src/gui/GsrPage.cpp @@ -0,0 +1,126 @@ +#include "../../include/gui/GsrPage.hpp" +#include "../../include/Theme.hpp" + +#include <mglpp/graphics/Rectangle.hpp> +#include <mglpp/graphics/Sprite.hpp> +#include <mglpp/window/Window.hpp> + +namespace gsr { + GsrPage::GsrPage() : + scrollable_body(mgl::vec2f(0.0f, 0.0f)), + back_button(&get_theme().title_font, "Back", + mgl::vec2f(get_theme().window_width / 10, get_theme().window_height / 15).floor(), get_theme().scrollable_page_bg_color), + label_text("Settings", get_theme().title_font) + { + //set_position(content_page_position); + const float margin = 0.02f; + set_margins(margin, margin, margin, margin); + back_button.set_border_scale(0.003f); + } + + bool GsrPage::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f) { + if(!visible) + return true; + + if(!scrollable_body.on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + return false; + + if(!back_button.on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + return false; + + return true; + } + + void GsrPage::draw(mgl::Window &window, mgl::vec2f offset) { + if(!visible) + return; + + const int margin_top = margin_top_scale * get_theme().window_height; + const int margin_left = margin_left_scale * get_theme().window_height; + + const mgl::vec2f window_size = mgl::vec2f(get_theme().window_width, get_theme().window_height).floor(); + const mgl::vec2f content_page_size = get_size(); + const mgl::vec2f content_page_position = mgl::vec2f(window_size * 0.5f - content_page_size * 0.5f).floor(); + offset = content_page_position + mgl::vec2f(margin_left, get_border_size() + margin_top).floor(); + + mgl::Rectangle background(content_page_size); + background.set_position(content_page_position); + background.set_color(get_theme().scrollable_page_bg_color); + window.draw(background); + + mgl::Rectangle border(mgl::vec2f(content_page_size.x, get_border_size()).floor()); + border.set_position(content_page_position); + border.set_color(get_theme().tint_color); + window.draw(border); + + scrollable_body.set_position(offset); + scrollable_body.draw(window, mgl::vec2f(0.0f, 0.0f)); + + draw_page_label(window, content_page_position); + + back_button.set_position(content_page_position + mgl::vec2f(content_page_size.x + get_horizontal_spacing(), 0.0f).floor()); + back_button.draw(window, mgl::vec2f(0.0f, 0.0f)); + } + + void GsrPage::draw_page_label(mgl::Window &window, mgl::vec2f body_pos) { + const mgl::vec2f window_size = mgl::vec2f(get_theme().window_width, get_theme().window_height).floor(); + + mgl::Rectangle background(mgl::vec2f(window_size.x / 10, window_size.x / 10).floor()); + background.set_position(body_pos.floor() - mgl::vec2f(background.get_size().x + get_horizontal_spacing(), 0.0f).floor()); + background.set_color(mgl::Color(0, 0, 0, 255)); + window.draw(background); + + const int text_margin = background.get_size().y * 0.085; + label_text.set_position((background.get_position() + mgl::vec2f(background.get_size().x * 0.5f - label_text.get_bounds().size.x * 0.5f, text_margin)).floor()); + window.draw(label_text); + + mgl::Sprite icon(&get_theme().settings_texture); + icon.set_height((int)(background.get_size().y * 0.5f)); + icon.set_position((background.get_position() + background.get_size() * 0.5f - icon.get_size() * 0.5f).floor()); + window.draw(icon); + } + + mgl::vec2f GsrPage::get_size() { + if(!visible) + return {0.0f, 0.0f}; + + 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(); + return content_page_size; + } + + mgl::vec2f GsrPage::get_inner_size() { + if(!visible) + return {0.0f, 0.0f}; + + const int margin_top = margin_top_scale * get_theme().window_height; + const int margin_bottom = margin_bottom_scale * get_theme().window_height; + const int margin_left = margin_left_scale * get_theme().window_height; + const int margin_right = margin_right_scale * get_theme().window_height; + return get_size() - mgl::vec2f(margin_left + margin_right, margin_top + margin_bottom + get_border_size()); + } + + void GsrPage::add_widget(std::unique_ptr<Widget> widget) { + scrollable_body.add_widget(std::move(widget)); + } + + void GsrPage::set_margins(float top, float bottom, float left, float right) { + margin_top_scale = top; + margin_bottom_scale = bottom; + margin_left_scale = left; + margin_right_scale = right; + scrollable_body.set_size(get_inner_size()); + } + + void GsrPage::set_on_back_button_click(std::function<void()> on_click_handler) { + back_button.on_click = std::move(on_click_handler); + } + + float GsrPage::get_border_size() const { + return 0.004f * get_theme().window_height; + } + + float GsrPage::get_horizontal_spacing() const { + return get_theme().window_width / 50; + } +}
\ No newline at end of file diff --git a/src/gui/List.cpp b/src/gui/List.cpp index acdb695..849329f 100644 --- a/src/gui/List.cpp +++ b/src/gui/List.cpp @@ -14,55 +14,25 @@ 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))) { - inside_event_handler = false; + if(!selected_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) { + return widgets.for_each_reverse([selected_widget, &event, &window](std::unique_ptr<Widget> &widget) { // 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))) { - inside_event_handler = false; + if(widget.get() != selected_widget) { + if(!widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f))) return false; - } } - } - - inside_event_handler = false; - return true; - } - - // TODO: Maybe call this from main on all widgets instead of from draw - void List::update() { - //widgets.insert(widgets.back(), std::make_move_iterator(add_queue.begin()), std::make_move_iterator(add_queue.end())); - std::move(add_queue.begin(), add_queue.end(), std::back_inserter(widgets)); - add_queue.clear(); - - for(Widget *widget_to_remove : remove_queue) { - remove_widget_immediate(widget_to_remove); - } - remove_queue.clear(); - } - - void List::remove_widget_immediate(Widget *widget) { - for(auto it = widgets.begin(), end = widgets.end(); it != end; ++it) { - if(it->get() == widget) { - widgets.erase(it); - return; - } - } + return true; + }); } void List::draw(mgl::Window &window, mgl::vec2f offset) { - update(); - if(!visible) return; @@ -140,28 +110,15 @@ namespace gsr { void List::add_widget(std::unique_ptr<Widget> widget) { widget->parent_widget = this; - if(inside_event_handler) - add_queue.push_back(std::move(widget)); - else - widgets.push_back(std::move(widget)); + widgets.push_back(std::move(widget)); } void List::remove_widget(Widget *widget) { - for(auto it = add_queue.begin(), end = add_queue.end(); it != end; ++it) { - if(it->get() == widget) { - add_queue.erase(it); - return; - } - } - - if(inside_event_handler) - remove_queue.push_back(widget); - else - remove_widget_immediate(widget); + widgets.remove(widget); } - const std::vector<std::unique_ptr<Widget>>& List::get_child_widgets() const { - return widgets; + void List::for_each_child_widget(std::function<bool(std::unique_ptr<Widget> &widget)> callback) { + widgets.for_each(callback); } Widget* List::get_child_widget_by_index(size_t index) const { diff --git a/src/gui/PageStack.cpp b/src/gui/PageStack.cpp new file mode 100644 index 0000000..94196cd --- /dev/null +++ b/src/gui/PageStack.cpp @@ -0,0 +1,58 @@ +#include "../../include/gui/PageStack.hpp" + +namespace gsr { + PageStack::PageStack() {} + + bool PageStack::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) { + if(!visible) + return true; + + offset = position + offset; + std::unique_ptr<Page> *top_page = widget_stack.back(); + if(top_page) { + if(!(*top_page)->on_event(event, window, offset)) + return false; + } + + return true; + } + + void PageStack::draw(mgl::Window &window, mgl::vec2f offset) { + if(!visible) + return; + + offset = position + offset; + std::unique_ptr<Page> *top_page = widget_stack.back(); + if(top_page) + (*top_page)->draw(window, offset); + } + + mgl::vec2f PageStack::get_size() { + return {0.0f, 0.0f}; + } + + void PageStack::push(std::unique_ptr<Page> widget) { + widget->on_navigate_to_page(); + widget_stack.push_back(std::move(widget)); + } + + void PageStack::pop() { + std::unique_ptr<Page> *top_page = widget_stack.back(); + if(top_page) { + (*top_page)->on_navigate_away_from_page(); + widget_stack.pop_back(); + } + } + + Page* PageStack::top() { + std::unique_ptr<Page> *top_page = widget_stack.back(); + if(top_page) + return top_page->get(); + else + return nullptr; + } + + bool PageStack::empty() const { + return widget_stack.empty(); + } +}
\ No newline at end of file diff --git a/src/gui/RadioButton.cpp b/src/gui/RadioButton.cpp index 87428bf..66f3b69 100644 --- a/src/gui/RadioButton.cpp +++ b/src/gui/RadioButton.cpp @@ -121,14 +121,14 @@ namespace gsr { dirty = true; } - void RadioButton::set_selected_item(const std::string &id, bool trigger_event) { + void RadioButton::set_selected_item(const std::string &id, bool trigger_event, bool trigger_event_even_if_selection_not_changed) { for(size_t i = 0; i < items.size(); ++i) { auto &item = items[i]; if(item.id == id) { const size_t prev_selected_item = selected_item; selected_item = i; - if(trigger_event && selected_item != prev_selected_item && on_selection_changed) + if(trigger_event && (trigger_event_even_if_selection_not_changed || selected_item != prev_selected_item) && on_selection_changed) on_selection_changed(item.text.get_string(), item.id); break; diff --git a/src/gui/ScrollablePage.cpp b/src/gui/ScrollablePage.cpp index a0977ce..a2b6c8f 100644 --- a/src/gui/ScrollablePage.cpp +++ b/src/gui/ScrollablePage.cpp @@ -1,7 +1,5 @@ #include "../../include/gui/ScrollablePage.hpp" -#include "../../include/Theme.hpp" -#include <mglpp/graphics/Rectangle.hpp> #include <mglpp/window/Window.hpp> namespace gsr { @@ -11,11 +9,8 @@ namespace gsr { if(!visible) return true; - const int margin_top = margin_top_scale * get_theme().window_height; - const int margin_left = margin_left_scale * get_theme().window_height; - const mgl::vec2f draw_pos = position + offset; - offset = draw_pos + mgl::vec2f(margin_left, get_border_size() + margin_top).floor(); + offset = draw_pos; Widget *selected_widget = selected_child_widget; if(selected_widget) { @@ -38,21 +33,8 @@ namespace gsr { if(!visible) return; - const int margin_top = margin_top_scale * get_theme().window_height; - const int margin_left = margin_left_scale * get_theme().window_height; - const mgl::vec2f draw_pos = position + offset; - offset = draw_pos + mgl::vec2f(margin_left, get_border_size() + margin_top).floor(); - - mgl::Rectangle background(size.floor()); - background.set_position(draw_pos); - background.set_color(get_theme().scrollable_page_bg_color); - window.draw(background); - - mgl::Rectangle border(mgl::vec2f(size.x, get_border_size()).floor()); - border.set_position(draw_pos); - border.set_color(get_theme().tint_color); - window.draw(border); + offset = draw_pos; mgl_scissor prev_scissor; mgl_window_get_scissor(window.internal_window(), &prev_scissor); @@ -84,25 +66,11 @@ namespace gsr { return size; } - mgl::vec2f ScrollablePage::get_inner_size() { - if(!visible) - return {0.0f, 0.0f}; - - const int margin_top = margin_top_scale * get_theme().window_height; - const int margin_bottom = margin_bottom_scale * get_theme().window_height; - const int margin_left = margin_left_scale * get_theme().window_height; - const int margin_right = margin_right_scale * get_theme().window_height; - return size - mgl::vec2f(margin_left + margin_right, margin_top + margin_bottom + get_border_size()); - } - - void ScrollablePage::set_margins(float top, float bottom, float left, float right) { - margin_top_scale = top; - margin_bottom_scale = bottom; - margin_left_scale = left; - margin_right_scale = right; + void ScrollablePage::set_size(mgl::vec2f size) { + this->size = size; } - float ScrollablePage::get_border_size() const { - return 0.004f * get_theme().window_height; + void ScrollablePage::add_widget(std::unique_ptr<Widget> widget) { + widgets.push_back(std::move(widget)); } }
\ No newline at end of file diff --git a/src/gui/SettingsPage.cpp b/src/gui/SettingsPage.cpp index 9bf6a12..d6022ab 100644 --- a/src/gui/SettingsPage.cpp +++ b/src/gui/SettingsPage.cpp @@ -1,6 +1,8 @@ #include "../../include/gui/SettingsPage.hpp" -#include "../../include/gui/ScrollablePage.hpp" +#include "../../include/gui/GsrPage.hpp" #include "../../include/gui/Label.hpp" +#include "../../include/gui/PageStack.hpp" +#include "../../include/gui/FileChooser.hpp" #include "../../include/Theme.hpp" #include "../../include/GsrInfo.hpp" @@ -10,20 +12,17 @@ #include <mglpp/window/Window.hpp> namespace gsr { - SettingsPage::SettingsPage(Type type, const GsrInfo &gsr_info, const std::vector<AudioDevice> &audio_devices, std::optional<Config> &config) : + SettingsPage::SettingsPage(Type type, const GsrInfo &gsr_info, const std::vector<AudioDevice> &audio_devices, std::optional<Config> &config, PageStack *page_stack) : StaticPage(mgl::vec2f(get_theme().window_width, get_theme().window_height).floor()), type(type), config(config), + page_stack(page_stack), 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<ScrollablePage>(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); + auto content_page = std::make_unique<GsrPage>(); + content_page->set_on_back_button_click([page_stack]() { + page_stack->pop(); + }); content_page_ptr = content_page.get(); add_widget(std::move(content_page)); @@ -31,40 +30,6 @@ namespace gsr { add_page_specific_widgets(); } - std::unique_ptr<Button> SettingsPage::create_back_button() { - const mgl::vec2i window_size(get_theme().window_width, get_theme().window_height); - auto back_button = std::make_unique<Button>(&get_theme().title_font, "Back", mgl::vec2f(window_size.x / 10, window_size.y / 15).floor(), get_theme().scrollable_page_bg_color); - back_button->set_position(content_page_ptr->get_position().floor() + mgl::vec2f(content_page_ptr->get_size().x + window_size.x / 50, 0.0f).floor()); - back_button->set_border_scale(0.003f); - back_button->on_click = [this]() { - if(on_back_button_handler) - on_back_button_handler(); - }; - return back_button; - } - - std::unique_ptr<CustomRendererWidget> SettingsPage::create_settings_icon() { - const mgl::vec2i window_size(get_theme().window_width, get_theme().window_height); - auto settings_icon_widget = std::make_unique<CustomRendererWidget>(mgl::vec2f(window_size.x / 10, window_size.x / 10).floor()); - settings_icon_widget->set_position(content_page_ptr->get_position().floor() - mgl::vec2f(settings_icon_widget->get_size().x + window_size.x / 50, 0.0f).floor()); - settings_icon_widget->draw_handler = [&](mgl::Window &window, mgl::vec2f pos, mgl::vec2f size) { - mgl::Rectangle background(size); - background.set_position(pos); - background.set_color(mgl::Color(0, 0, 0, 255)); - window.draw(background); - - const int text_margin = size.y * 0.085; - settings_title_text.set_position((pos + mgl::vec2f(size.x * 0.5f - settings_title_text.get_bounds().size.x * 0.5f, text_margin)).floor()); - window.draw(settings_title_text); - - mgl::Sprite icon(&get_theme().settings_texture); - icon.set_height((int)(size.y * 0.5f)); - icon.set_position((pos + size * 0.5f - icon.get_size() * 0.5f).floor()); - window.draw(icon); - }; - return settings_icon_widget; - } - std::unique_ptr<RadioButton> SettingsPage::create_view_radio_button() { auto view_radio_button = std::make_unique<RadioButton>(&get_theme().body_font); view_radio_button->add_item("Simple view", "simple"); @@ -363,8 +328,6 @@ namespace gsr { } void SettingsPage::add_widgets(const GsrInfo &gsr_info, const std::vector<AudioDevice> &audio_devices) { - add_widget(create_back_button()); - add_widget(create_settings_icon()); content_page_ptr->add_widget(create_settings(gsr_info, audio_devices)); record_area_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) { @@ -400,9 +363,20 @@ namespace gsr { std::unique_ptr<List> SettingsPage::create_save_directory(const char *label) { auto save_directory_list = std::make_unique<List>(List::Orientation::VERTICAL); save_directory_list->add_widget(std::make_unique<Label>(&get_theme().body_font, label, get_theme().text_color)); - auto save_directory_entry = std::make_unique<Entry>(&get_theme().body_font, "/home/dec05eba/Videos", get_theme().body_font.get_character_size() * 20); - save_directory_entry_ptr = save_directory_entry.get(); - save_directory_list->add_widget(std::move(save_directory_entry)); + auto save_directory_button = std::make_unique<Button>(&get_theme().body_font, "/home/dec05eba/Videos", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120)); + save_directory_button->on_click = [this]() { + auto select_directory_page = std::make_unique<GsrPage>(); + select_directory_page->set_on_back_button_click([this]() { + page_stack->pop(); + }); + + auto file_chooser = std::make_unique<gsr::FileChooser>("/home/dec05eba", select_directory_page->get_size()); + select_directory_page->add_widget(std::move(file_chooser)); + + page_stack->push(std::move(select_directory_page)); + }; + save_directory_button_ptr = save_directory_button.get(); + save_directory_list->add_widget(std::move(save_directory_button)); return save_directory_list; } @@ -658,12 +632,12 @@ namespace gsr { static void save_audio_tracks(std::vector<std::string> &audio_tracks, List *audio_devices_list_ptr) { audio_tracks.clear(); - const std::vector<std::unique_ptr<Widget>> &audio_devices_list = audio_devices_list_ptr->get_child_widgets(); - for(const std::unique_ptr<Widget> &child_widget : audio_devices_list) { + audio_devices_list_ptr->for_each_child_widget([&audio_tracks](std::unique_ptr<Widget> &child_widget) { List *audio_device_line = static_cast<List*>(child_widget.get()); ComboBox *audio_device_box = static_cast<ComboBox*>(audio_device_line->get_child_widget_by_index(0)); audio_tracks.push_back(audio_device_box->get_selected_id()); - } + return true; + }); } void SettingsPage::save_common(RecordOptions &record_options) { @@ -705,7 +679,7 @@ namespace gsr { config->replay_config.show_replay_started_notifications = show_replay_started_notification_checkbox_ptr->is_checked(); config->replay_config.show_replay_stopped_notifications = show_replay_stopped_notification_checkbox_ptr->is_checked(); config->replay_config.show_replay_saved_notifications = show_replay_saved_notification_checkbox_ptr->is_checked(); - config->replay_config.save_directory = save_directory_entry_ptr->get_text(); + config->replay_config.save_directory = save_directory_button_ptr->get_text(); config->replay_config.container = container_box_ptr->get_selected_id(); config->replay_config.replay_time = atoi(replay_time_entry_ptr->get_text().c_str()); @@ -719,7 +693,7 @@ namespace gsr { save_common(config->record_config.record_options); config->record_config.show_recording_started_notifications = show_recording_started_notification_checkbox_ptr->is_checked(); config->record_config.show_video_saved_notifications = show_video_saved_notification_checkbox_ptr->is_checked(); - config->record_config.save_directory = save_directory_entry_ptr->get_text(); + config->record_config.save_directory = save_directory_button_ptr->get_text(); config->record_config.container = container_box_ptr->get_selected_id(); } |