diff --git a/libs/ui/include/psemek/ui/file_dialog.hpp b/libs/ui/include/psemek/ui/file_dialog.hpp new file mode 100644 index 00000000..242b327a --- /dev/null +++ b/libs/ui/include/psemek/ui/file_dialog.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace psemek::ui +{ + + enum class file_dialog_type + { + save, + load + }; + + struct file_dialog_options + { + struct element_factory & element_factory; + file_dialog_type type; + std::string caption; + std::filesystem::path path; + std::function on_visited = nullptr; + std::function on_selected = nullptr; + std::function on_canceled = nullptr; + std::shared_ptr extra_widget = nullptr; + }; + + std::shared_ptr make_file_dialog(file_dialog_options const & options); + +} diff --git a/libs/ui/resources/back.png b/libs/ui/resources/back.png new file mode 100644 index 00000000..e661f7dd Binary files /dev/null and b/libs/ui/resources/back.png differ diff --git a/libs/ui/resources/folder.png b/libs/ui/resources/folder.png new file mode 100644 index 00000000..bcd5e19f Binary files /dev/null and b/libs/ui/resources/folder.png differ diff --git a/libs/ui/source/file_dialog.cpp b/libs/ui/source/file_dialog.cpp new file mode 100644 index 00000000..6390196c --- /dev/null +++ b/libs/ui/source/file_dialog.cpp @@ -0,0 +1,302 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace psemek::ui +{ + + namespace + { + + struct frame_style_fix + : ui::single_container + { + struct shape const & shape() const override + { + return child()->shape(); + } + + void reshape(geom::box const & bbox) override + { + child()->reshape(bbox); + } + + geom::box size_constraints() const override + { + return child()->size_constraints(); + } + + geom::interval width_constraints(float height) const override + { + return child()->width_constraints(height); + } + + geom::interval height_constraints(float width) const override + { + return child()->height_constraints(width); + } + + void style_updated() const override + { + ui::single_container::style_updated(); + + auto style = merged_style(); + auto new_style = std::make_shared(); + new_style->bg_color = style->action_color; + + child()->set_own_style(new_style); + } + + void draw(painter &) const override + {} + }; + + struct file_dialog_image_provider + : image_provider + { + file_dialog_image_provider() + { + back_.load(gfx::read_png(io::memory_istream(resources::back_png.data))); + back_.linear_filter(); + + folder_.load(gfx::read_png(io::memory_istream(resources::folder_png.data))); + folder_.linear_filter(); + + { + gfx::pixmap_rgba empty({folder_.width(), folder_.height()}, gfx::color_rgba{0, 0, 0, 0}); + empty_.load(empty); + empty_.nearest_filter(); + } + } + + gfx::texture_view_2d get(std::string_view const & id) const override + { + if (id == "back") + return gfx::texture_view_2d{&back_}; + if (id == "folder") + return gfx::texture_view_2d{&folder_}; + if (id == "empty") + return gfx::texture_view_2d{&empty_}; + return {}; + } + + private: + gfx::texture_2d back_; + gfx::texture_2d folder_; + gfx::texture_2d empty_; + }; + + } + + std::shared_ptr make_file_dialog(file_dialog_options const & options) + { + auto window = options.element_factory.make_window(options.caption); + + auto main_layout = options.element_factory.make_grid_layout(); + main_layout->set_size(4, options.extra_widget ? 3 : 2); + main_layout->set_column_weight(0, 0.f); + if (options.extra_widget) + main_layout->set_column_weight(2, 0.f); + main_layout->set_row_weight(0, 0.f); + main_layout->set_row_weight(2, 0.f); + main_layout->set_row_weight(3, 0.f); + + auto image_provider = std::make_shared(); + + auto current_path = std::make_shared(); + auto selected_path = std::make_shared(); + + auto back_button = options.element_factory.make_button(image_provider->get("back")); + back_button->icon()->set_downscale(false); + + auto back_button_style = std::make_shared