yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
theme_manager.h
Go to the documentation of this file.
1#ifndef YAZE_APP_GUI_THEME_MANAGER_H
2#define YAZE_APP_GUI_THEME_MANAGER_H
3
4#include <functional>
5#include <map>
6#include <optional>
7#include <set>
8#include <string>
9#include <utility>
10#include <vector>
11
12#include "absl/status/status.h"
13#include "absl/status/statusor.h"
14#include "app/gui/core/color.h"
15#include "imgui/imgui.h"
16
17namespace yaze {
18namespace gui {
19
24enum class DensityPreset {
25 kCompact, // 0.75x - Dense UI, more content visible
26 kNormal, // 1.0x - Default balanced spacing
27 kComfortable // 1.25x - Spacious, easier to click
28};
29
34struct Theme {
35 std::string name;
36 std::string description;
37 std::string author;
38
39 // Primary colors
49
50 // Text colors
54
55 // Window colors
60
61 // Interactive elements
68
69 // Navigation and selection
80
81 // Borders and separators
87
88 // Scrollbars and controls
93
94 // Special elements
100
101 // Complete ImGui color support
123
124 // Additional ImGui colors for complete coverage
131
132 // Enhanced theme system - semantic colors
133 Color text_highlight; // For selected text, highlighted items
134 Color link_hover; // For hover state of links
135 Color code_background; // For code blocks, monospace text backgrounds
136 Color success_light; // Lighter variant of success color
137 Color warning_light; // Lighter variant of warning color
138 Color error_light; // Lighter variant of error color
139 Color info_light; // Lighter variant of info color
140
141 // UI state colors
142 Color active_selection; // For active/selected UI elements
143 Color hover_highlight; // General hover state
144 Color focus_border; // For focused input elements
145 Color disabled_overlay; // Semi-transparent overlay for disabled elements
146
147 // Editor-specific colors
148 Color editor_background; // Main editor canvas background
149 Color editor_grid; // Grid lines in editors
150 Color editor_cursor; // Cursor/selection in editors
151 Color editor_selection; // Selected area in editors
152
153 // Unified selection and interaction colors (replacing hardcoded values)
154 Color selection_primary; // Primary selection (typically gold/yellow)
155 Color selection_secondary; // Secondary selection (typically cyan/blue)
156 Color selection_hover; // Hover highlight color
157 Color selection_pulsing; // Pulsing animation color
158 Color selection_handle; // Corner handles for resizing/moving
159 Color drag_preview; // Ghost preview when dragging
160 Color drag_preview_outline; // Outline for drag preview
161
162 // Common entity colors
170
171 // Nested struct for dungeon editor colors
200
201 // Nested struct for chat/agent colors
240
241 // Style parameters
242 float window_rounding = 0.0f;
243 float frame_rounding = 5.0f;
244 float scrollbar_rounding = 5.0f;
245 float grab_rounding = 3.0f;
246 float tab_rounding = 0.0f;
247 float window_border_size = 0.0f;
248 float frame_border_size = 0.0f;
249
250 // Animation and effects
251 bool enable_animations = true;
252 float animation_speed = 1.0f;
254
255 // Theme-aware sizing system (relative to font size)
256 // compact_factor: 0.8 = very compact, 1.0 = normal, 1.2 = spacious
257 float compact_factor = 1.0f;
259
260 // Semantic sizing multipliers (applied on top of compact_factor)
261 float widget_height_multiplier = 1.0f; // Standard widget height
262 float spacing_multiplier = 1.0f; // Padding/margins between elements
263 float toolbar_height_multiplier = 0.8f; // Compact toolbars
264 float panel_padding_multiplier = 1.0f; // Panel interior padding
265 float input_width_multiplier = 1.0f; // Standard input field width
266 float button_padding_multiplier = 1.0f; // Button interior padding
267 float table_row_height_multiplier = 1.0f; // Table row height
268 float canvas_toolbar_multiplier = 0.75f; // Canvas overlay toolbars
269
270 // Helper methods
271 void ApplyToImGui() const;
272 // Writes only the density-derived padding/spacing scalars. ApplyToImGui
273 // calls it; ApplyClassicYazeTheme calls it separately because ColorsYaze()
274 // hardcodes those scalars at the Normal scale.
275 void ApplyDensitySizingToImGui() const;
277};
278
284 public:
285 static ThemeManager& Get();
286
287 // Theme management
288 absl::Status LoadTheme(const std::string& theme_name);
289 absl::Status SaveTheme(const Theme& theme, const std::string& filename);
290 absl::Status LoadThemeFromFile(const std::string& filepath);
291 // Non-const: records the chosen filepath in theme_file_paths_ on success so
292 // subsequent GetCurrentThemeFilePath calls round-trip for themes created or
293 // renamed via the save dialog (not just ones that were loaded from disk).
294 absl::Status SaveThemeToFile(const Theme& theme, const std::string& filepath);
295
296 // Dynamic theme discovery - replaces hardcoded theme lists with automatic
297 // discovery This works across development builds, macOS app bundles, and
298 // other deployment scenarios
299 std::vector<std::string> DiscoverAvailableThemeFiles() const;
300 absl::Status LoadAllAvailableThemes();
301 absl::Status RefreshAvailableThemes(); // Public method to refresh at runtime
302
303 // Built-in themes
305 std::vector<std::string> GetAvailableThemes() const;
306 const Theme* GetTheme(const std::string& name) const;
307 const Theme& GetCurrentTheme() const { return current_theme_; }
308 const std::string& GetCurrentThemeName() const { return current_theme_name_; }
309
310 // Filesystem path the current theme was loaded from (or last saved to via
311 // SaveThemeToFile). Returns empty string for Classic YAZE (no file) or when
312 // no file association exists; "Save Over Current" uses this to decide
313 // whether the overwrite action is available.
314 std::string GetCurrentThemeFilePath() const;
315
316 // Theme application
317 void ApplyTheme(const std::string& theme_name);
318 void ApplyTheme(const Theme& theme);
319 // Re-apply `theme` as the canonical version of the theme it names. Unlike
320 // ApplyTheme(const Theme&), which paints whatever struct it is handed (the
321 // theme editor's in-progress edits go through that), this routes Classic
322 // YAZE back to ApplyClassicYazeTheme() because BuildClassicYazeTheme's
323 // struct cannot reproduce ColorsYaze(). Use it on restore/re-apply paths:
324 // EndPreview, live-preview cancel, and the Display Density combo.
325 void ReapplyTheme(const Theme& theme);
326 // Apply the original ColorsYaze() function. `density` overrides the density
327 // carried over from the outgoing theme — ApplyTheme(const Theme&) passes the
328 // incoming struct's preset so the Display Density combo still works while
329 // Classic YAZE is active.
331 std::optional<DensityPreset> density = std::nullopt);
332
333 // Theme-changed callback. Fired after any successful theme application with
334 // the current theme name. Keeps persistence decoupled from ThemeManager —
335 // the editor wires this to UserSettings so the selection survives restart.
336 using ThemeChangedCallback = std::function<void(const std::string&)>;
338 on_theme_changed_ = std::move(callback);
339 }
340
341 // Theme preview (for hover preview in selector)
342 void StartPreview(const std::string& theme_name);
343 void EndPreview();
344 bool IsPreviewActive() const;
345
346 // Smooth theme transitions
347 void UpdateTransition();
348 bool IsTransitioning() const { return transitioning_; }
349
350 // Theme creation and editing
351 Theme CreateCustomTheme(const std::string& name);
352 void ShowThemeEditor(bool* p_open);
353 void ShowThemeSelector(bool* p_open);
354 void ShowSimpleThemeEditor(bool* p_open);
355
356 // Accent color derivation - generate harmonious theme from single color
357 Theme GenerateThemeFromAccent(const Color& accent, bool dark_mode = true);
358 void ApplyAccentColor(const Color& accent, bool dark_mode = true);
359
360 // Integration with welcome screen
364
365 // Export current theme as JSON string for Web/WASM sync
366 std::string ExportCurrentThemeJson() const;
367
368 // Convenient theme color access interface
369 Color GetThemeColor(const std::string& color_name) const;
370 ImVec4 GetThemeColorVec4(const std::string& color_name) const;
371
372 // Material Design color accessors
391
392 private:
394
395 std::map<std::string, Theme> themes_;
396 // Display name → filesystem path captured at LoadThemeFromFile time. Lets
397 // GetCurrentThemeFilePath return a path that survives display names with
398 // spaces/apostrophes (e.g., "Majora's Moon" → majoras_moon.theme).
399 std::map<std::string, std::string> theme_file_paths_;
401 std::string current_theme_name_ = "Classic YAZE";
402
403 // Preview state for hover preview in theme selector
404 bool preview_active_ = false;
407
408 // True while InitializeBuiltInThemes is constructing the singleton. Guards
409 // ApplyClassicYazeTheme from calling AgentUI::RefreshTheme, which would
410 // recursively re-enter ThemeManager::Get() and abort on __cxa_guard_acquire.
412
413 // Smooth transition state (lerps ImGui colors per-frame)
414 bool transitioning_ = false;
416 ImVec4 transition_from_[ImGuiCol_COUNT] = {};
417 ImVec4 transition_to_[ImGuiCol_COUNT] = {};
418
419 // Fires on_theme_changed_ with current_theme_name_. Safe to call when no
420 // callback is set (becomes a no-op).
421 void NotifyThemeChanged();
422
424
426 // `declared_keys`, when non-null, receives every recognised key the file
427 // actually contained. ApplySmartDefaults needs that to tell "the author
428 // omitted this field" from "the author chose black": a default-constructed
429 // Color is opaque black, so the two are identical by value.
430 absl::Status ParseThemeFile(const std::string& content, Theme& theme,
431 std::set<std::string>* declared_keys = nullptr);
432 // Fill missing properties from primary colors. Fields named in
433 // `declared_keys` are left exactly as the file set them.
434 void ApplySmartDefaults(Theme& theme,
435 const std::set<std::string>& declared_keys = {});
436 Color ParseColorFromString(const std::string& color_str) const;
437 std::string SerializeTheme(const Theme& theme) const;
438
439 // Helper methods for path resolution
440 std::vector<std::string> GetThemeSearchPaths() const;
441 std::string GetThemesDirectory() const;
442 std::string GetUserThemesDirectory() const; // Returns ~/.yaze/themes/
443};
444
445// Global convenience functions for easy theme color access
446// Material Design color accessors - global convenience functions
447inline Color GetThemeColor(const std::string& color_name) {
448 return ThemeManager::Get().GetThemeColor(color_name);
449}
450
451inline ImVec4 GetThemeColorVec4(const std::string& color_name) {
452 return ThemeManager::Get().GetThemeColorVec4(color_name);
453}
454
455// Material Design color accessors
457 return ThemeManager::Get().GetPrimary();
458}
467}
469 return ThemeManager::Get().GetSurface();
470}
485}
491}
493 return ThemeManager::Get().GetOutline();
494}
501inline Color GetShadow() {
502 return ThemeManager::Get().GetShadow();
503}
504
505// ImVec4 versions for direct ImGui usage
506inline ImVec4 GetPrimaryVec4() {
508}
509inline ImVec4 GetPrimaryHoverVec4() {
511}
512inline ImVec4 GetPrimaryActiveVec4() {
514}
515inline ImVec4 GetSurfaceVec4() {
517}
530inline ImVec4 GetOnSurfaceVec4() {
532}
536inline ImVec4 GetOnPrimaryVec4() {
538}
539inline ImVec4 GetOutlineVec4() {
541}
542inline ImVec4 GetTextSecondaryVec4() {
544}
545inline ImVec4 GetTextDisabledVec4() {
547}
548inline ImVec4 GetTextPrimaryVec4() {
550 ThemeManager::Get().GetCurrentTheme().text_primary);
551}
552inline ImVec4 GetSuccessVec4() {
553 return ConvertColorToImVec4(ThemeManager::Get().GetCurrentTheme().success);
554}
555inline ImVec4 GetWarningVec4() {
556 return ConvertColorToImVec4(ThemeManager::Get().GetCurrentTheme().warning);
557}
558inline ImVec4 GetErrorVec4() {
559 return ConvertColorToImVec4(ThemeManager::Get().GetCurrentTheme().error);
560}
561inline ImVec4 GetShadowVec4() {
563}
564} // namespace gui
565
566} // namespace yaze
567
568#endif // YAZE_APP_GUI_THEME_MANAGER_H
Manages themes, loading, saving, and switching.
Color GetSurfaceContainerHigh() const
absl::Status ParseThemeFile(const std::string &content, Theme &theme, std::set< std::string > *declared_keys=nullptr)
Color ParseColorFromString(const std::string &color_str) const
Color GetSurfaceVariant() const
std::string preview_original_name_
Color GetTextSecondary() const
void ShowThemeEditor(bool *p_open)
Color GetWelcomeScreenBackground() const
ImVec4 GetThemeColorVec4(const std::string &color_name) const
void ReapplyTheme(const Theme &theme)
void StartPreview(const std::string &theme_name)
ThemeChangedCallback on_theme_changed_
absl::Status SaveTheme(const Theme &theme, const std::string &filename)
std::string GetCurrentThemeFilePath() const
std::function< void(const std::string &)> ThemeChangedCallback
std::map< std::string, Theme > themes_
absl::Status LoadTheme(const std::string &theme_name)
const Theme & GetCurrentTheme() const
Color GetPrimaryHover() const
absl::Status LoadThemeFromFile(const std::string &filepath)
std::map< std::string, std::string > theme_file_paths_
void ApplyTheme(const std::string &theme_name)
std::string GetThemesDirectory() const
std::string current_theme_name_
ImVec4 transition_to_[ImGuiCol_COUNT]
Color GetWelcomeScreenAccent() const
void ApplyAccentColor(const Color &accent, bool dark_mode=true)
std::vector< std::string > DiscoverAvailableThemeFiles() const
std::string GetUserThemesDirectory() const
Theme CreateCustomTheme(const std::string &name)
absl::Status LoadAllAvailableThemes()
Color GetSurfaceContainer() const
Color GetOnSurfaceVariant() const
std::vector< std::string > GetThemeSearchPaths() const
void SetOnThemeChangedCallback(ThemeChangedCallback callback)
static ThemeManager & Get()
Color GetThemeColor(const std::string &color_name) const
void ApplyClassicYazeTheme(std::optional< DensityPreset > density=std::nullopt)
const std::string & GetCurrentThemeName() const
void ShowThemeSelector(bool *p_open)
Theme GenerateThemeFromAccent(const Color &accent, bool dark_mode=true)
const Theme * GetTheme(const std::string &name) const
std::string SerializeTheme(const Theme &theme) const
absl::Status RefreshAvailableThemes()
Color GetTextDisabled() const
std::string ExportCurrentThemeJson() const
absl::Status SaveThemeToFile(const Theme &theme, const std::string &filepath)
void ApplySmartDefaults(Theme &theme, const std::set< std::string > &declared_keys={})
Color GetSurfaceContainerHighest() const
Color GetWelcomeScreenBorder() const
void ShowSimpleThemeEditor(bool *p_open)
Color GetPrimaryActive() const
ImVec4 transition_from_[ImGuiCol_COUNT]
std::vector< std::string > GetAvailableThemes() const
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:134
ImVec4 GetErrorVec4()
ImVec4 GetSurfaceContainerHighestVec4()
Color GetPrimaryHover()
Color GetOnPrimary()
ImVec4 GetThemeColorVec4(const std::string &color_name)
Color GetOnSurfaceVariant()
ImVec4 GetOnPrimaryVec4()
Color GetTextDisabled()
ImVec4 GetPrimaryActiveVec4()
Color GetSurfaceContainerHighest()
Color GetOnSurface()
ImVec4 GetPrimaryVec4()
ImVec4 GetTextPrimaryVec4()
Color GetSecondary()
Color GetSurfaceContainer()
ImVec4 GetSurfaceVariantVec4()
ImVec4 GetSurfaceVec4()
DensityPreset
Typography and spacing density presets.
ImVec4 GetTextDisabledVec4()
Color GetTextSecondary()
Color GetOutline()
Color GetShadow()
ImVec4 GetTextSecondaryVec4()
ImVec4 GetShadowVec4()
ImVec4 GetSurfaceContainerHighVec4()
ImVec4 GetSuccessVec4()
ImVec4 GetPrimaryHoverVec4()
Color GetPrimaryActive()
Color GetPrimary()
Color GetSurface()
ImVec4 GetOutlineVec4()
Color GetThemeColor(const std::string &color_name)
Color GetSurfaceContainerHigh()
ImVec4 GetOnSurfaceVariantVec4()
ImVec4 GetOnSurfaceVec4()
ImVec4 GetSurfaceContainerVec4()
Color GetSurfaceVariant()
ImVec4 GetWarningVec4()
Comprehensive theme structure for YAZE.
Color tab_dimmed_selected_overline
std::string description
std::string name
Color scrollbar_grab_hovered
Color scrollbar_grab_active
Color nav_windowing_highlight
float panel_padding_multiplier
float widget_height_multiplier
struct yaze::gui::Theme::DungeonColors dungeon
struct yaze::gui::Theme::AgentTheme agent
void ApplyDensitySizingToImGui() const
void ApplyToImGui() const
float button_padding_multiplier
float table_row_height_multiplier
float toolbar_height_multiplier
DensityPreset density_preset
void ApplyDensityPreset(DensityPreset preset)
std::string author
float canvas_toolbar_multiplier