diff --git a/Userland/Applications/ThemeEditor/ThemeEditor.gml b/Userland/Applications/ThemeEditor/ThemeEditor.gml index 91348e199d..4eca76e919 100644 --- a/Userland/Applications/ThemeEditor/ThemeEditor.gml +++ b/Userland/Applications/ThemeEditor/ThemeEditor.gml @@ -17,6 +17,7 @@ @GUI::ComboBox { name: "color_combo_box" model_only: true + fixed_width: 230 } @GUI::ColorInput { @@ -34,10 +35,37 @@ @GUI::ComboBox { name: "metric_combo_box" model_only: true + fixed_width: 230 } @GUI::SpinBox { name: "metric_input" } } + + @GUI::GroupBox { + layout: @GUI::HorizontalBoxLayout { + margins: [16, 8, 8, 8] + } + shrink_to_fit: true + title: "Paths" + + @GUI::ComboBox { + name: "path_combo_box" + model_only: true + fixed_width: 230 + } + + @GUI::TextBox { + name: "path_input" + mode: "Editable" + } + + @GUI::Button { + name: "path_picker_button" + fixed_width: 20 + text: "..." + tooltip: "Choose..." + } + } } diff --git a/Userland/Applications/ThemeEditor/main.cpp b/Userland/Applications/ThemeEditor/main.cpp index 8755dd774c..9ffd91336c 100644 --- a/Userland/Applications/ThemeEditor/main.cpp +++ b/Userland/Applications/ThemeEditor/main.cpp @@ -13,8 +13,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -60,6 +62,24 @@ public: } }; +class PathRoleModel final : public GUI::ItemListModel { +public: + explicit PathRoleModel(Vector const& data) + : ItemListModel(data) + { + } + + virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override + { + if (role == GUI::ModelRole::Display) + return Gfx::to_string(static_cast(m_data[(size_t)index.row()])); + if (role == GUI::ModelRole::Custom) + return m_data[(size_t)index.row()]; + + return ItemListModel::data(index, role); + } +}; + int main(int argc, char** argv) { if (pledge("stdio recvfd sendfd thread rpath cpath wpath unix", nullptr) < 0) { @@ -124,6 +144,11 @@ int main(int argc, char** argv) ENUMERATE_METRIC_ROLES(__ENUMERATE_METRIC_ROLE) #undef __ENUMERATE_METRIC_ROLE + Vector path_roles; +#define __ENUMERATE_PATH_ROLE(role) path_roles.append(Gfx::PathRole::role); + ENUMERATE_PATH_ROLES(__ENUMERATE_PATH_ROLE) +#undef __ENUMERATE_PATH_ROLE + auto& main_widget = window->set_main_widget(); main_widget.load_from_gml(theme_editor_gml); @@ -133,6 +158,9 @@ int main(int argc, char** argv) auto& color_input = *main_widget.find_descendant_of_type_named("color_input"); auto& metric_combo_box = *main_widget.find_descendant_of_type_named("metric_combo_box"); auto& metric_input = *main_widget.find_descendant_of_type_named("metric_input"); + auto& path_combo_box = *main_widget.find_descendant_of_type_named("path_combo_box"); + auto& path_input = *main_widget.find_descendant_of_type_named("path_input"); + auto& path_picker_button = *main_widget.find_descendant_of_type_named("path_picker_button"); color_combo_box.set_model(adopt_ref(*new ColorRoleModel(color_roles))); color_combo_box.on_change = [&](auto&, auto& index) { @@ -164,6 +192,32 @@ int main(int argc, char** argv) }; metric_input.set_value(startup_preview_palette.metric(Gfx::MetricRole::TitleButtonHeight), GUI::AllowCallback::No); + path_combo_box.set_model(adopt_ref(*new PathRoleModel(path_roles))); + path_combo_box.on_change = [&](auto&, auto& index) { + auto role = index.model()->data(index, GUI::ModelRole::Custom).to_path_role(); + path_input.set_text(preview_widget.preview_palette().path(role)); + }; + path_combo_box.set_selected_index((size_t)Gfx::PathRole::TitleButtonIcons - 1); + + path_input.on_change = [&] { + auto role = path_combo_box.model()->index(path_combo_box.selected_index()).data(GUI::ModelRole::Custom).to_path_role(); + auto preview_palette = preview_widget.preview_palette(); + preview_palette.set_path(role, path_input.text()); + preview_widget.set_preview_palette(preview_palette); + }; + path_input.set_text(startup_preview_palette.path(Gfx::PathRole::TitleButtonIcons)); + + path_picker_button.on_click = [&](auto) { + // FIXME: Open at the path_input location. Right now that's panicking the kernel though! :^( + auto role = path_combo_box.model()->index(path_combo_box.selected_index()).data(GUI::ModelRole::Custom).to_path_role(); + bool open_folder = (role == Gfx::PathRole::TitleButtonIcons); + auto window_title = String::formatted(open_folder ? "Select {} folder" : "Select {} file", path_combo_box.text()); + auto result = GUI::FilePicker::get_open_filepath(window, window_title, "/res/icons", open_folder); + if (!result.has_value()) + return; + path_input.set_text(*result); + }; + auto& file_menu = window->add_menu("&File"); auto update_window_title = [&] { @@ -179,6 +233,9 @@ int main(int argc, char** argv) auto selected_metric_role = metric_combo_box.model()->index(metric_combo_box.selected_index()).data(GUI::ModelRole::Custom).to_metric_role(); metric_input.set_value(preview_widget.preview_palette().metric(selected_metric_role), GUI::AllowCallback::No); + + auto selected_path_role = path_combo_box.model()->index(path_combo_box.selected_index()).data(GUI::ModelRole::Custom).to_path_role(); + path_input.set_text(preview_widget.preview_palette().path(selected_path_role)); }; auto save_to_result = [&](FileSystemAccessClient::Result const& result) { @@ -197,10 +254,9 @@ int main(int argc, char** argv) theme->write_num_entry("Metrics", to_string(role), preview_widget.preview_palette().metric(role)); } -#define __ENUMERATE_PATH_ROLE(role) \ - theme->write_entry("Paths", #role, preview_widget.preview_palette().path(Gfx::PathRole::role)); - ENUMERATE_PATH_ROLES(__ENUMERATE_PATH_ROLE) -#undef __ENUMERATE_PATH_ROLE + for (auto role : path_roles) { + theme->write_entry("Paths", to_string(role), preview_widget.preview_palette().path(role)); + } theme->sync(); }; @@ -233,7 +289,7 @@ int main(int argc, char** argv) update_window_title(); - window->resize(480, 460); + window->resize(480, 500); window->set_resizable(false); window->show(); window->set_icon(app_icon.bitmap_for_size(16));