diff --git a/Userland/Applications/DisplaySettings/CMakeLists.txt b/Userland/Applications/DisplaySettings/CMakeLists.txt index 84c88b9987..9ee81640e6 100644 --- a/Userland/Applications/DisplaySettings/CMakeLists.txt +++ b/Userland/Applications/DisplaySettings/CMakeLists.txt @@ -8,6 +8,7 @@ compile_gml(MonitorSettings.gml MonitorSettingsGML.h monitor_settings_window_gml compile_gml(BackgroundSettings.gml BackgroundSettingsGML.h background_settings_gml) compile_gml(DesktopSettings.gml DesktopSettingsGML.h desktop_settings_gml) compile_gml(FontSettings.gml FontSettingsGML.h font_settings_gml) +compile_gml(ThemesSettings.gml ThemesSettingsGML.h themes_settings_gml) set(SOURCES BackgroundSettingsGML.h @@ -19,6 +20,11 @@ set(SOURCES MonitorSettingsWidget.cpp MonitorSettingsGML.h MonitorWidget.cpp + ThemePreviewWidget.h + ThemePreviewWidget.cpp + ThemesSettingsWidget.h + ThemesSettingsWidget.cpp + ThemesSettingsGML.h main.cpp ) diff --git a/Userland/Applications/DisplaySettings/ThemePreviewWidget.cpp b/Userland/Applications/DisplaySettings/ThemePreviewWidget.cpp new file mode 100644 index 0000000000..aaba61d6bc --- /dev/null +++ b/Userland/Applications/DisplaySettings/ThemePreviewWidget.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ThemePreviewWidget.h" +#include +#include +#include +#include +#include + +namespace DisplaySettings { + +ThemePreviewWidget::ThemePreviewWidget(Gfx::Palette const& palette) + : GUI::AbstractThemePreview(palette) +{ + set_fixed_size(304, 201); +} + +void ThemePreviewWidget::set_theme(String path) +{ + set_theme_from_file(*Core::File::open(path, Core::OpenMode::ReadOnly).release_value_but_fixme_should_propagate_errors()); +} + +void ThemePreviewWidget::paint_preview(GUI::PaintEvent&) +{ + GUI::Painter painter(*this); + + auto active_window_rect = rect().shrunken(48, 100).translated(4, 26); + auto inactive_window_rect = active_window_rect.translated(-8, -32); + auto message_box = active_window_rect.shrunken(100, 60); + + paint_window("Inactive Window", inactive_window_rect, Gfx::WindowTheme::WindowState::Inactive, inactive_window_icon()); + paint_window("Active Window", active_window_rect, Gfx::WindowTheme::WindowState::Active, active_window_icon()); + paint_window("Alert", message_box, Gfx::WindowTheme::WindowState::Highlighted, active_window_icon(), 1); + + auto draw_centered_button = [&](auto window_rect, auto text, int button_width, int button_height) { + auto box_center = window_rect.center(); + Gfx::IntRect button_rect { box_center.x() - button_width / 2, box_center.y() - button_height / 2, button_width, button_height }; + Gfx::StylePainter::paint_button( + painter, button_rect, preview_palette(), Gfx::ButtonStyle::Normal, false, false, false, true, false, false); + painter.draw_text(button_rect, text, Gfx::TextAlignment::Center, preview_palette().color(foreground_role()), Gfx::TextElision::Right, Gfx::TextWrapping::DontWrap); + }; + + draw_centered_button(message_box, "Ok", 32, 16); +} + +} diff --git a/Userland/Applications/DisplaySettings/ThemePreviewWidget.h b/Userland/Applications/DisplaySettings/ThemePreviewWidget.h new file mode 100644 index 0000000000..370db19339 --- /dev/null +++ b/Userland/Applications/DisplaySettings/ThemePreviewWidget.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace DisplaySettings { + +class ThemePreviewWidget final : public GUI::AbstractThemePreview { + C_OBJECT(ThemePreviewWidget); + +public: + void set_theme(String path); + +private: + explicit ThemePreviewWidget(Gfx::Palette const& palette); + + void paint_preview(GUI::PaintEvent& event) override; +}; + +} diff --git a/Userland/Applications/DisplaySettings/ThemesSettings.gml b/Userland/Applications/DisplaySettings/ThemesSettings.gml new file mode 100644 index 0000000000..2556404e75 --- /dev/null +++ b/Userland/Applications/DisplaySettings/ThemesSettings.gml @@ -0,0 +1,32 @@ +@GUI::Widget { + fill_with_background_color: true + layout: @GUI::VerticalBoxLayout { + margins: [8] + } + + @GUI::Frame { + layout: @GUI::HorizontalBoxLayout {} + name: "preview_frame" + fixed_width: 304 + fixed_height: 201 + } + + @GUI::Widget { + fixed_height: 20 + } + + @GUI::Widget { + shrink_to_fit: true + layout: @GUI::HorizontalBoxLayout {} + + @GUI::Label { + text: "Theme:" + text_alignment: "CenterLeft" + fixed_width: 95 + } + + @GUI::ComboBox { + name: "themes_combo" + } + } +} diff --git a/Userland/Applications/DisplaySettings/ThemesSettingsWidget.cpp b/Userland/Applications/DisplaySettings/ThemesSettingsWidget.cpp new file mode 100644 index 0000000000..5d86a07cac --- /dev/null +++ b/Userland/Applications/DisplaySettings/ThemesSettingsWidget.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ThemesSettingsWidget.h" +#include +#include +#include +#include +#include +#include + +namespace DisplaySettings { + +ThemesSettingsWidget::ThemesSettingsWidget() +{ + load_from_gml(themes_settings_gml); + m_themes = Gfx::list_installed_system_themes(); + + auto current_theme_name = GUI::ConnectionToWindowServer::the().get_system_theme(); + + size_t current_theme_index; + m_theme_names.ensure_capacity(m_themes.size()); + for (auto& theme_meta : m_themes) { + m_theme_names.append(theme_meta.name); + if (current_theme_name == theme_meta.name) { + m_selected_theme = &theme_meta; + current_theme_index = m_theme_names.size() - 1; + } + } + VERIFY(m_selected_theme); + + m_theme_preview = find_descendant_of_type_named("preview_frame")->add(palette()); + m_themes_combo = *find_descendant_of_type_named("themes_combo"); + m_themes_combo->set_only_allow_values_from_model(true); + m_themes_combo->set_model(*GUI::ItemListModel::create(m_theme_names)); + m_themes_combo->on_change = [this](auto&, const GUI::ModelIndex& index) { + m_selected_theme = &m_themes.at(index.row()); + m_theme_preview->set_theme(m_selected_theme->path); + }; + m_themes_combo->set_selected_index(current_theme_index); +} + +void ThemesSettingsWidget::apply_settings() +{ + if (m_selected_theme) + VERIFY(GUI::ConnectionToWindowServer::the().set_system_theme(m_selected_theme->path, m_selected_theme->name)); +} + +} diff --git a/Userland/Applications/DisplaySettings/ThemesSettingsWidget.h b/Userland/Applications/DisplaySettings/ThemesSettingsWidget.h new file mode 100644 index 0000000000..520a754642 --- /dev/null +++ b/Userland/Applications/DisplaySettings/ThemesSettingsWidget.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include "ThemePreviewWidget.h" + +namespace DisplaySettings { + +class ThemesSettingsWidget final : public GUI::SettingsWindow::Tab { + C_OBJECT(ThemesSettingsWidget); + +public: + virtual void apply_settings() override; + +private: + Vector m_themes; + Vector m_theme_names; + + RefPtr m_themes_combo; + RefPtr m_theme_preview; + + Gfx::SystemThemeMetaData const* m_selected_theme { nullptr }; + + ThemesSettingsWidget(); +}; + +} diff --git a/Userland/Applications/DisplaySettings/main.cpp b/Userland/Applications/DisplaySettings/main.cpp index d968d75d93..b8b2fef93a 100644 --- a/Userland/Applications/DisplaySettings/main.cpp +++ b/Userland/Applications/DisplaySettings/main.cpp @@ -10,6 +10,7 @@ #include "DesktopSettingsWidget.h" #include "FontSettingsWidget.h" #include "MonitorSettingsWidget.h" +#include "ThemesSettingsWidget.h" #include #include #include @@ -28,6 +29,7 @@ ErrorOr serenity_main(Main::Arguments arguments) auto window = TRY(GUI::SettingsWindow::create("Display Settings")); (void)TRY(window->add_tab("Background")); + (void)TRY(window->add_tab("Themes")); (void)TRY(window->add_tab("Fonts")); (void)TRY(window->add_tab("Monitor")); (void)TRY(window->add_tab("Workspaces"));