HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
theme_book.hpp
1// Copyright Take Vos 2020-2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "theme.hpp"
8#include "../settings/settings.hpp"
9#include "../macros.hpp"
10#include <limits>
11#include <vector>
12#include <memory>
13#include <filesystem>
14
15hi_export_module(hikogui.GUI : theme_book);
16
17hi_export namespace hi::inline v1 {
18
23public:
26 observer<std::string> selected_theme = "default";
27
28 ~theme_book() = default;
29 theme_book(theme_book const&) = delete;
30 theme_book(theme_book&&) = delete;
31 theme_book& operator=(theme_book const&) = delete;
32 theme_book& operator=(theme_book&&) = delete;
33 theme_book() noexcept = default;
34
35 static theme_book& global() noexcept;
36
37 void register_directory(std::filesystem::path path) noexcept
38 {
39 _theme_directories.push_back(path);
40 }
41
42 void reload() noexcept
43 {
44 themes.clear();
45
46 for (auto const& theme_directory : _theme_directories) {
47 auto const theme_directory_glob = theme_directory / "**" / "*.theme.json";
48 for (auto const& theme_path : glob(theme_directory_glob)) {
49 auto t = trace<"theme_scan">{};
50
51 try {
52 themes.push_back(std::make_unique<theme>(theme_path));
53 } catch (std::exception const& e) {
54 hi_log_error("Failed parsing theme at {}. \"{}\"", theme_path.string(), e.what());
55 }
56 }
57 }
58
59 if (ssize(themes) == 0) {
60 hi_log_fatal("Did not load any themes.");
61 }
62 }
63
64 [[nodiscard]] std::vector<std::string> names() const noexcept
65 {
67
68 for (auto const& t : themes) {
69 names.push_back(t->name);
70 }
71
72 std::sort(names.begin(), names.end());
73 auto const new_end = std::unique(names.begin(), names.end());
74 names.erase(new_end, names.cend());
75 return names;
76 }
77
84 [[nodiscard]] theme const& find(std::string_view name, theme_mode mode) const noexcept
85 {
86 theme *default_theme = nullptr;
87 theme *default_theme_and_mode = nullptr;
88 theme *matching_theme = nullptr;
89 theme *matching_theme_and_mode = nullptr;
90
91 for (auto const& t : themes) {
92 if (t->name == name and t->mode == mode) {
93 matching_theme_and_mode = t.get();
94 } else if (t->name == name) {
95 matching_theme = t.get();
96 } else if (t->name == "default" and t->mode == mode) {
97 default_theme_and_mode = t.get();
98 } else if (t->name == "default") {
99 default_theme = t.get();
100 }
101 }
102
103 if (matching_theme_and_mode) {
104 return *matching_theme_and_mode;
105 } else if (matching_theme) {
106 return *matching_theme;
107 } else if (default_theme_and_mode) {
108 return *default_theme_and_mode;
109 } else if (default_theme) {
110 return *default_theme;
111 } else if (ssize(themes) > 0) {
112 return *themes[0].get();
113 } else {
114 hi_no_default();
115 }
116 }
117
118private:
119 std::vector<std::filesystem::path> _theme_directories;
121};
122
123namespace detail {
124inline std::unique_ptr<theme_book> theme_book_global;
125}
126
127[[nodiscard]] inline theme_book& theme_book::global() noexcept
128{
129 if (not detail::theme_book_global) {
130 detail::theme_book_global = std::make_unique<theme_book>();
131 }
132 return *detail::theme_book_global;
133}
134
135inline void register_theme_directory(std::filesystem::path const &path) noexcept
136{
137 return theme_book::global().register_directory(path);
138}
139
140inline void reload_themes() noexcept
141{
142 return theme_book::global().reload();
143}
144
145template<std::ranges::range R>
146inline void register_theme_directories(R &&r) noexcept
147{
148 for (auto &path: r) {
149 register_theme_directory(path);
150 }
151 reload_themes();
152}
153
154[[nodiscard]] inline theme const& find_theme(std::string_view name, theme_mode mode) noexcept
155{
156 return theme_book::global().find(name, mode);
157}
158
159[[nodiscard]] inline std::vector<std::string> theme_names() noexcept
160{
161 return theme_book::global().names();
162}
163
164[[nodiscard]] inline theme const &get_selected_theme() noexcept
165{
166 return find_theme(*theme_book::global().selected_theme, os_settings::theme_mode());
167}
168
169} // namespace hi::inline v1
STL namespace.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition theme.hpp:24
theme_book keeps track of multiple themes.
Definition theme_book.hpp:22
theme const & find(std::string_view name, theme_mode mode) const noexcept
Find a theme matching the name and mode.
Definition theme_book.hpp:84
Definition trace.hpp:43
T begin(T... args)
T end(T... args)
T erase(T... args)
T push_back(T... args)
T sort(T... args)
T unique(T... args)
T what(T... args)