From 28f4b67bdccadbb61af1ea514501a930bef1658b Mon Sep 17 00:00:00 2001 From: networkException Date: Thu, 16 Jun 2022 20:29:25 +0200 Subject: [PATCH] ThemeEditor: Allow temporarily overriding the system theme This patch introduces two new buttons to apply the current theme being edited to the whole system and to reset to the previously selected on disk system theme. --- .../Applications/ThemeEditor/MainWidget.cpp | 87 ++++++++++++++++++- .../Applications/ThemeEditor/MainWidget.h | 6 ++ .../Applications/ThemeEditor/ThemeEditor.gml | 39 +++++++-- 3 files changed, 126 insertions(+), 6 deletions(-) diff --git a/Userland/Applications/ThemeEditor/MainWidget.cpp b/Userland/Applications/ThemeEditor/MainWidget.cpp index f62618010e4..034e3bc16bc 100644 --- a/Userland/Applications/ThemeEditor/MainWidget.cpp +++ b/Userland/Applications/ThemeEditor/MainWidget.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Andreas Kling - * Copyright (c) 2021, Jakob-Niklas See + * Copyright (c) 2021-2022, Jakob-Niklas See * Copyright (c) 2021-2022, Sam Atkins * Copyright (c) 2021, Antonio Di Stefano * Copyright (c) 2022, Filiph Sandström @@ -15,6 +15,10 @@ #include #include #include +// FIXME: LibIPC Decoder and Encoder are sensitive to include order here +// clang-format off +#include +// clang-format on #include #include #include @@ -196,6 +200,8 @@ MainWidget::MainWidget() add_property_tab(window_tab); add_property_tab(widgets_tab); add_property_tab(syntax_highlighting_tab); + + build_override_controls(); } ErrorOr MainWidget::initialize_menubar(GUI::Window& window) @@ -367,6 +373,84 @@ void MainWidget::save_to_file(Core::File& file) } } +ErrorOr MainWidget::encode() +{ + auto buffer = TRY(Core::AnonymousBuffer::create_with_size(sizeof(Gfx::SystemTheme))); + auto* data = buffer.data(); + +#define __ENUMERATE_ALIGNMENT_ROLE(role) \ + data->alignment[(int)Gfx::AlignmentRole::role] = m_current_palette.alignment(Gfx::AlignmentRole::role); + ENUMERATE_ALIGNMENT_ROLES(__ENUMERATE_ALIGNMENT_ROLE) +#undef __ENUMERATE_ALIGNMENT_ROLE + +#define __ENUMERATE_COLOR_ROLE(role) \ + data->color[(int)Gfx::ColorRole::role] = m_current_palette.color(Gfx::ColorRole::role).value(); + ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE) +#undef __ENUMERATE_COLOR_ROLE + +#define __ENUMERATE_FLAG_ROLE(role) \ + data->flag[(int)Gfx::FlagRole::role] = m_current_palette.flag(Gfx::FlagRole::role); + ENUMERATE_FLAG_ROLES(__ENUMERATE_FLAG_ROLE) +#undef __ENUMERATE_FLAG_ROLE + +#define __ENUMERATE_METRIC_ROLE(role) \ + data->metric[(int)Gfx::MetricRole::role] = m_current_palette.metric(Gfx::MetricRole::role); + ENUMERATE_METRIC_ROLES(__ENUMERATE_METRIC_ROLE) +#undef __ENUMERATE_METRIC_ROLE + +#define ENCODE_PATH(role, allow_empty) \ + do { \ + auto path = m_current_palette.path(Gfx::PathRole::role); \ + char const* characters; \ + if (path.is_empty()) { \ + switch (Gfx::PathRole::role) { \ + case Gfx::PathRole::TitleButtonIcons: \ + characters = "/res/icons/16x16/"; \ + break; \ + default: \ + characters = allow_empty ? "" : "/res/"; \ + } \ + } \ + characters = path.characters(); \ + memcpy(data->path[(int)Gfx::PathRole::role], characters, min(strlen(characters) + 1, sizeof(data->path[(int)Gfx::PathRole::role]))); \ + data->path[(int)Gfx::PathRole::role][sizeof(data->path[(int)Gfx::PathRole::role]) - 1] = '\0'; \ + } while (0) + + ENCODE_PATH(TitleButtonIcons, false); + ENCODE_PATH(ActiveWindowShadow, true); + ENCODE_PATH(InactiveWindowShadow, true); + ENCODE_PATH(TaskbarShadow, true); + ENCODE_PATH(MenuShadow, true); + ENCODE_PATH(TooltipShadow, true); + + return buffer; +} + +void MainWidget::build_override_controls() +{ + auto* theme_override_controls = find_descendant_of_type_named("theme_override_controls"); + + m_theme_override_apply = theme_override_controls->find_child_of_type_named("apply"); + m_theme_override_reset = theme_override_controls->find_child_of_type_named("reset"); + + m_theme_override_apply->on_click = [&](auto) { + auto encoded = encode(); + if (encoded.is_error()) + return; + GUI::ConnectionToWindowServer::the().async_set_system_theme_override(encoded.value()); + }; + + m_theme_override_reset->on_click = [&](auto) { + GUI::ConnectionToWindowServer::the().async_clear_system_theme_override(); + }; + + GUI::Application::the()->on_theme_change = [&]() { + auto override_active = GUI::ConnectionToWindowServer::the().is_system_theme_overridden(); + m_theme_override_apply->set_enabled(!override_active && window()->is_modified()); + m_theme_override_reset->set_enabled(override_active); + }; +} + void MainWidget::add_property_tab(PropertyTab const& property_tab) { auto& scrollable_container = m_property_tabs->add_tab(property_tab.title); @@ -513,6 +597,7 @@ void MainWidget::set_palette(Gfx::Palette palette) { m_current_palette = move(palette); m_preview_widget->set_preview_palette(m_current_palette); + m_theme_override_apply->set_enabled(true); window()->set_modified(true); } diff --git a/Userland/Applications/ThemeEditor/MainWidget.h b/Userland/Applications/ThemeEditor/MainWidget.h index c93ae3d4906..a54a36578d3 100644 --- a/Userland/Applications/ThemeEditor/MainWidget.h +++ b/Userland/Applications/ThemeEditor/MainWidget.h @@ -91,8 +91,11 @@ private: MainWidget(); void save_to_file(Core::File&); + ErrorOr encode(); void set_path(String); + void build_override_controls(); + void add_property_tab(PropertyTab const&); void set_alignment(Gfx::AlignmentRole, Gfx::TextAlignment); void set_color(Gfx::ColorRole, Gfx::Color); @@ -112,6 +115,9 @@ private: RefPtr m_property_tabs; RefPtr m_save_action; + RefPtr m_theme_override_apply; + RefPtr m_theme_override_reset; + Optional m_path; Gfx::Palette m_current_palette; Time m_last_modified_time { Time::now_monotonic() }; diff --git a/Userland/Applications/ThemeEditor/ThemeEditor.gml b/Userland/Applications/ThemeEditor/ThemeEditor.gml index 36d6f48bab0..01fec60badb 100644 --- a/Userland/Applications/ThemeEditor/ThemeEditor.gml +++ b/Userland/Applications/ThemeEditor/ThemeEditor.gml @@ -1,13 +1,42 @@ @GUI::Widget { - layout: @GUI::HorizontalBoxLayout {} + layout: @GUI::VerticalBoxLayout {} fill_with_background_color: true - @GUI::Frame { + @GUI::Widget { layout: @GUI::HorizontalBoxLayout {} - name: "preview_frame" + + @GUI::Frame { + layout: @GUI::HorizontalBoxLayout {} + name: "preview_frame" + } + + @GUI::TabWidget { + name: "property_tabs" + } } - @GUI::TabWidget { - name: "property_tabs" + @GUI::Widget { + name: "theme_override_controls" + layout: @GUI::HorizontalBoxLayout { + margins: [ 0, 4 ] + } + + fixed_height: 30 + + @GUI::Layout::Spacer {} + + @GUI::Button { + name: "reset" + text: "Reset to Previous System Theme" + enabled: false + fixed_width: 190 + } + + @GUI::Button { + name: "apply" + text: "Apply as System Theme" + enabled: false + fixed_width: 140 + } } }