Files
ts-qt/modern-qt/utility/theme/theme.hh
2025-10-20 00:32:01 +08:00

127 lines
3.7 KiB
C++

#pragma once
#include <qwidget.h>
// #include "utility/theme/color-scheme.hh"
// #include "utility/wrapper/common.hh"
// #include "utility/wrapper/pimpl.hh"
// #include "utility/wrapper/property.hh"
#include "modern-qt/utility/theme/color-scheme.hh"
#include "modern-qt/utility/wrapper/common.hh"
#include "modern-qt/utility/wrapper/pimpl.hh"
#include "modern-qt/utility/wrapper/property.hh"
#include <memory>
namespace creeper::theme {
class ThemeManager;
template <class T>
concept color_scheme_setter_trait = requires(T t) {
{ t.set_color_scheme(ColorScheme {}) };
};
template <class T>
concept theme_manager_loader_trait =
requires(T t, ThemeManager& manager) { t.load_theme_manager(manager); };
struct ThemePack {
ColorScheme light, dark;
auto color_scheme(this auto&& self, ColorMode mode) noexcept {
return (mode == ColorMode::LIGHT) ? self.light : self.dark;
}
};
class ThemeManager {
// CREEPER_PIMPL_DEFINITION(ThemeManager)
public:
ThemeManager();
~ThemeManager();
ThemeManager(const ThemeManager&) = delete;
ThemeManager& operator=(const ThemeManager&) = delete;
private:
struct Impl;
std::unique_ptr<Impl> pimpl;
public:
explicit ThemeManager(const ThemePack& pack, ColorMode mode = ColorMode::LIGHT);
void apply_theme() const;
using Handler = std::function<void(const ThemeManager&)>;
/// Registers a theme change callback for the specified widget.
///
/// When ThemeManager::apply_theme() is called, the registered handler will be executed.
///
/// Args:
/// key: Pointer to the widget. Serves as the key in the handler map.
/// handler: The callback function to register.
///
/// Note:
/// When the widget is destroyed, ThemeManager::remove_handler() will be called automatically
/// to remove the associated handler.
void append_handler(const QObject* key, const Handler& handler);
auto append_handler(color_scheme_setter_trait auto& widget) { append_handler(&widget, widget); }
auto append_handler(const QObject* key, color_scheme_setter_trait auto& widget) {
const auto handler = [&widget](const ThemeManager& manager) {
const auto color_mode = manager.color_mode();
const auto theme_pack = manager.theme_pack();
widget.set_color_scheme(theme_pack.color_scheme(color_mode));
};
append_handler(key, std::move(handler));
}
auto append_begin_callback(const Handler&) noexcept -> void;
auto append_final_callback(const Handler&) noexcept -> void;
void remove_handler(const QObject* key);
void set_theme_pack(const ThemePack& pack);
void set_color_mode(const ColorMode& mode);
void toggle_color_mode();
ThemePack theme_pack() const;
ColorMode color_mode() const;
ColorScheme color_scheme() const;
};
}
namespace creeper::theme::pro {
using Token = common::Token<ThemeManager>;
struct ColorScheme : public theme::ColorScheme, Token {
using theme::ColorScheme::ColorScheme;
explicit ColorScheme(const theme::ColorScheme& p)
: theme::ColorScheme(p) { }
auto apply(color_scheme_setter_trait auto& self) const noexcept -> void {
self.set_color_scheme(*this);
}
};
struct ThemeManager : Token {
theme::ThemeManager& manager;
explicit ThemeManager(theme::ThemeManager& p)
: manager(p) { }
auto apply(theme_manager_loader_trait auto& self) const noexcept -> void {
self.load_theme_manager(manager);
}
};
template <typename T>
concept trait = std::derived_from<T, Token>;
CREEPER_DEFINE_CHECKER(trait);
}
namespace creeper {
using ColorMode = theme::ColorMode;
using ColorScheme = theme::ColorScheme;
using ThemePack = theme::ThemePack;
using ThemeManager = theme::ThemeManager;
}