yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
widget_id_registry.h
Go to the documentation of this file.
1#ifndef YAZE_APP_GUI_AUTOMATION_WIDGET_ID_REGISTRY_H_
2#define YAZE_APP_GUI_AUTOMATION_WIDGET_ID_REGISTRY_H_
3
4#include <cstdint>
5#include <optional>
6#include <string>
7#include <unordered_map>
8#include <vector>
9
10#include "absl/strings/string_view.h"
11#include "absl/synchronization/mutex.h"
12#include "absl/time/time.h"
13#include "imgui/imgui.h"
14
15namespace yaze {
16namespace gui {
17
38 public:
39 explicit WidgetIdScope(const std::string& name);
41
42 // Get the full hierarchical path at this scope level
43 std::string GetFullPath() const;
44
45 // Get the full path with a widget suffix
46 std::string GetWidgetPath(const std::string& widget_type,
47 const std::string& widget_name) const;
48
49 private:
50 std::string name_;
51 static thread_local std::vector<std::string> id_stack_;
52};
53
69 public:
70 struct WidgetBounds {
71 float min_x = 0.0f;
72 float min_y = 0.0f;
73 float max_x = 0.0f;
74 float max_y = 0.0f;
75 bool valid = false;
76 };
77
79 std::optional<std::string> label;
80 std::optional<std::string> window_name;
81 std::optional<bool> visible;
82 std::optional<bool> enabled;
83 std::optional<WidgetBounds> bounds;
84 };
85
86 struct WidgetInfo {
87 std::string full_path; // e.g. "Overworld/Canvas/canvas:Map"
88 std::string type; // e.g. "button", "input", "canvas", "table"
89 ImGuiID imgui_id; // ImGui's internal ID
90 std::string description; // Optional human-readable description
91 std::string label; // Sanitized display label (without IDs/icons)
92 std::string window_name; // Window this widget was last seen in
93 bool visible = true; // Visibility in the most recent frame
94 bool enabled = true; // Enabled state in the most recent frame
95 WidgetBounds bounds; // Bounding box in screen space
97 absl::Time last_seen_time;
100 };
101
102 static WidgetIdRegistry& Instance();
103
104 // Frame lifecycle - call once per ImGui frame
105 void BeginFrame();
106 void EndFrame();
107
108 // Register a widget for discovery
109 // Should be called after widget is created (when ImGui::GetItemID() is valid)
110 void RegisterWidget(const std::string& full_path, const std::string& type,
111 ImGuiID imgui_id, const std::string& description = "",
112 const WidgetMetadata& metadata = WidgetMetadata());
113
114 // Query widgets for test automation.
115 // FindWidgets matches each full path against a glob: '*' matches any run of
116 // characters, '/' included; '?' matches exactly one UTF-8 character; a
117 // pattern without wildcards is an exact match. Results are sorted by path.
118 std::vector<std::string> FindWidgets(const std::string& pattern) const;
119 ImGuiID GetWidgetId(const std::string& full_path) const;
120 std::optional<WidgetInfo> GetWidgetInfo(const std::string& full_path) const;
121
122 // Get a thread-safe snapshot of all registered widgets.
123 std::unordered_map<std::string, WidgetInfo> GetAllWidgets() const;
124
125 // Clear all registered widgets (useful between frames for dynamic UIs)
126 void Clear();
127
128 // Export catalog for z3ed agent describe
129 // Format: "yaml" or "json"
130 std::string ExportCatalog(const std::string& format = "yaml") const;
131 void ExportCatalogToFile(const std::string& output_file,
132 const std::string& format = "yaml") const;
133
134 // Helper utilities for consistent naming
135 static std::string NormalizeLabel(absl::string_view label);
136 static std::string NormalizePathSegment(absl::string_view segment);
137
138 private:
139 WidgetIdRegistry() = default;
140 void TrimStaleEntries();
141 bool ShouldPrune(const WidgetInfo& info) const;
142
143 mutable absl::Mutex mutex_;
144 std::unordered_map<std::string, WidgetInfo> widgets_ ABSL_GUARDED_BY(mutex_);
145 int current_frame_ ABSL_GUARDED_BY(mutex_) = -1;
146 absl::Time frame_time_ ABSL_GUARDED_BY(mutex_);
147 int stale_frame_limit_ = 600; // frames before pruning a widget
148};
149
150} // namespace gui
151} // namespace yaze
152
153#endif // YAZE_APP_GUI_AUTOMATION_WIDGET_ID_REGISTRY_H_
Centralized registry for discoverable GUI widgets.
std::optional< WidgetInfo > GetWidgetInfo(const std::string &full_path) const
absl::Time frame_time_ ABSL_GUARDED_BY(mutex_)
void ExportCatalogToFile(const std::string &output_file, const std::string &format="yaml") const
static std::string NormalizePathSegment(absl::string_view segment)
std::string ExportCatalog(const std::string &format="yaml") const
bool ShouldPrune(const WidgetInfo &info) const
int current_frame_ ABSL_GUARDED_BY(mutex_)
ImGuiID GetWidgetId(const std::string &full_path) const
static std::string NormalizeLabel(absl::string_view label)
void RegisterWidget(const std::string &full_path, const std::string &type, ImGuiID imgui_id, const std::string &description="", const WidgetMetadata &metadata=WidgetMetadata())
std::unordered_map< std::string, WidgetInfo > widgets_ ABSL_GUARDED_BY(mutex_)
std::unordered_map< std::string, WidgetInfo > GetAllWidgets() const
static WidgetIdRegistry & Instance()
std::vector< std::string > FindWidgets(const std::string &pattern) const
RAII helper for managing hierarchical ImGui ID scopes.
WidgetIdScope(const std::string &name)
std::string GetFullPath() const
static thread_local std::vector< std::string > id_stack_
std::string GetWidgetPath(const std::string &widget_type, const std::string &widget_name) const