yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
status_bar.cc
Go to the documentation of this file.
2
3#include <algorithm>
4
5#include "absl/strings/str_format.h"
14#include "rom/rom.h"
15#include "imgui/imgui.h"
16
17namespace yaze {
18namespace editor {
19
20float StatusBar::GetHeight() const {
21 if (!enabled_) {
22 return 0.0f;
23 }
26 }
27 return kStatusBarHeight;
28}
29
31 context_ = context;
32 if (context_) {
33 // Subscribe to UI status updates
35 [this](const StatusUpdateEvent& e) { HandleStatusUpdate(e); });
36
37 // Subscribe to selection changes from any editor
39 [this](const SelectionChangedEvent& e) {
40 if (e.IsEmpty()) {
42 } else {
43 SetSelection(static_cast<int>(e.Count()));
44 }
45 });
46
47 // Subscribe to zoom changes from any canvas
49 [this](const ZoomChangedEvent& e) { SetZoom(e.new_zoom); });
50 }
51}
52
54 switch (event.type) {
56 SetCursorPosition(event.x, event.y, event.text.empty() ? nullptr : event.text.c_str());
57 break;
59 SetSelection(event.count, event.width, event.height);
60 break;
62 SetZoom(event.zoom);
63 break;
65 SetEditorMode(event.text);
66 break;
69 break;
70 default:
71 break;
72 }
73}
74
75void StatusBar::SetSessionInfo(size_t session_id, size_t total_sessions) {
76 session_id_ = session_id;
77 total_sessions_ = total_sessions;
78}
79
80void StatusBar::SetCursorPosition(int x, int y, const char* label) {
81 has_cursor_ = true;
82 cursor_x_ = x;
83 cursor_y_ = y;
84 cursor_label_ = label ? label : "Pos";
85}
86
90
91void StatusBar::SetSelection(int count, int width, int height) {
92 has_selection_ = true;
93 selection_count_ = count;
94 selection_width_ = width;
95 selection_height_ = height;
96}
97
99 has_selection_ = false;
100}
101
102void StatusBar::SetZoom(float level) {
103 has_zoom_ = true;
104 zoom_level_ = level;
105}
106
108 has_zoom_ = false;
109}
110
111void StatusBar::SetEditorMode(const std::string& mode) {
112 has_mode_ = true;
113 editor_mode_ = mode;
114}
115
117 has_mode_ = false;
118 editor_mode_.clear();
119}
120
121void StatusBar::SetCustomSegment(const std::string& key,
122 const std::string& value) {
123 custom_segments_[key] = value;
124}
125
126void StatusBar::ClearCustomSegment(const std::string& key) {
127 custom_segments_.erase(key);
128}
129
137
138void StatusBar::SetAgentInfo(const std::string& provider,
139 const std::string& model, bool active) {
140 has_agent_ = true;
141 agent_provider_ = provider;
142 agent_model_ = model;
143 agent_active_ = active;
144}
145
147 has_agent_ = false;
148 agent_provider_.clear();
149 agent_model_.clear();
150 agent_active_ = false;
151}
152
154 if (!enabled_) {
155 return;
156 }
157
158 const ImGuiViewport* viewport = ImGui::GetMainViewport();
159
160 // Position at very bottom of viewport, above the safe area (home indicator).
161 // The dockspace is already reduced by GetBottomLayoutOffset() in controller.cc.
162 const float bar_height = GetHeight();
163 const float bottom_safe = gui::LayoutHelpers::GetSafeAreaInsets().bottom;
164 const float bar_y =
165 viewport->WorkPos.y + viewport->WorkSize.y - bar_height - bottom_safe;
166 const bool touch_mode = gui::LayoutHelpers::IsTouchDevice();
167 const ImVec2 panel_padding = touch_mode ? ImVec2(14.0f, 7.0f)
168 : ImVec2(8.0f, 4.0f);
169 const ImVec2 panel_spacing = touch_mode ? ImVec2(12.0f, 0.0f)
170 : ImVec2(8.0f, 0.0f);
171
172 // Status bar background - slightly elevated surface
173 ImVec4 bar_bg = gui::GetSurfaceContainerVec4();
174 ImVec4 bar_border = gui::GetOutlineVec4();
175
176 ImGuiWindowFlags extra_flags =
177 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
178 ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNavFocus |
179 ImGuiWindowFlags_NoBringToFrontOnFocus;
180
181 gui::FixedPanel bar(
182 "##StatusBar",
183 ImVec2(viewport->WorkPos.x, bar_y),
184 ImVec2(viewport->WorkSize.x, bar_height),
185 {.bg = bar_bg,
186 .border = bar_border,
187 .padding = panel_padding,
188 .spacing = panel_spacing,
189 .border_size = 1.0f},
190 extra_flags);
191
192 if (bar) {
193 // Left section: ROM info, Session, Dirty status
195
196 if (total_sessions_ > 1) {
199 }
200
201 // Middle section: Editor context (cursor, selection)
202 if (has_cursor_) {
205 }
206
207 if (has_selection_) {
210 }
211
212 // Custom segments
214
215 // Right section: Zoom, Mode (right-aligned)
216 float right_section_width = 0.0f;
217 std::string agent_label;
218 if (has_agent_) {
219 agent_label = agent_model_.empty() ? agent_provider_ : agent_model_;
220 if (agent_label.empty()) {
221 agent_label = "Agent";
222 }
223 const size_t max_len = 20;
224 if (agent_label.size() > max_len) {
225 agent_label = agent_label.substr(0, max_len - 3) + "...";
226 }
227 std::string label = std::string(ICON_MD_SMART_TOY " ") + agent_label;
228 right_section_width +=
229 ImGui::CalcTextSize(label.c_str()).x +
230 ImGui::GetStyle().FramePadding.x * 2.0f + 10.0f;
231 }
232 if (has_zoom_) {
233 right_section_width += ImGui::CalcTextSize("100%").x + 20.0f;
234 }
235 if (has_mode_) {
236 right_section_width += ImGui::CalcTextSize(editor_mode_.c_str()).x + 30.0f;
237 }
238
239 if (right_section_width > 0.0f) {
240 float available = ImGui::GetContentRegionAvail().x;
241 if (available > right_section_width + 20.0f) {
242 ImGui::SameLine(ImGui::GetWindowWidth() - right_section_width - 16.0f);
243
244 if (has_agent_) {
246 if (has_zoom_ || has_mode_) {
248 }
249 }
250
251 if (has_zoom_) {
253 if (has_mode_) {
255 }
256 }
257
258 if (has_mode_) {
260 }
261 }
262 }
263 }
264}
265
267 std::string label = agent_model_.empty() ? agent_provider_ : agent_model_;
268 if (label.empty()) {
269 label = "Agent";
270 }
271 const size_t max_len = 20;
272 if (label.size() > max_len) {
273 label = label.substr(0, max_len - 3) + "...";
274 }
275 std::string button_label = std::string(ICON_MD_SMART_TOY " ") + label;
276
277 ImVec4 text_color = agent_active_ ? gui::GetPrimaryVec4()
279 gui::StyleColorGuard agent_colors({
280 {ImGuiCol_Text, text_color},
281 {ImGuiCol_Button, gui::GetSurfaceContainerHighVec4()},
282 {ImGuiCol_ButtonHovered, gui::GetSurfaceContainerHighestVec4()},
283 });
284 if (gui::ThemedButton(button_label.c_str())) {
287 }
288 }
289
290 if (ImGui::IsItemHovered()) {
291 ImGui::BeginTooltip();
292 ImGui::Text("%s Agent", ICON_MD_SMART_TOY);
293 ImGui::TextDisabled("Provider: %s",
294 agent_provider_.empty() ? "mock"
295 : agent_provider_.c_str());
296 ImGui::TextDisabled("Model: %s",
297 agent_model_.empty() ? "not set"
298 : agent_model_.c_str());
299 ImGui::TextDisabled("Toggle chat panel");
300 ImGui::EndTooltip();
301 }
302}
303
305 const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
306
307 if (rom_ && rom_->is_loaded()) {
308 // ROM name
309 gui::ColoredTextF(ImGui::GetStyleColorVec4(ImGuiCol_Text),
310 "%s %s", ICON_MD_DESCRIPTION,
311 rom_->short_name().c_str());
312
313 // Dirty indicator
314 if (rom_->dirty()) {
315 ImGui::SameLine();
317 gui::ConvertColorToImVec4(theme.warning));
318
319 if (ImGui::IsItemHovered()) {
320 ImGui::SetTooltip("Unsaved changes");
321 }
322 }
323 } else {
325 "%s No ROM loaded", ICON_MD_DESCRIPTION);
326 }
327}
328
331 "%s S%zu/%zu", ICON_MD_LAYERS,
333
334 if (ImGui::IsItemHovered()) {
335 ImGui::SetTooltip("Session %zu of %zu", session_id_ + 1, total_sessions_);
336 }
337}
338
343
345 gui::StyleColorGuard selection_color(ImGuiCol_Text,
347
348 if (selection_width_ > 0 && selection_height_ > 0) {
349 ImGui::Text("%s %d (%dx%d)", ICON_MD_SELECT_ALL, selection_count_,
351 } else if (selection_count_ > 0) {
352 ImGui::Text("%s %d selected", ICON_MD_SELECT_ALL, selection_count_);
353 }
354}
355
357 int zoom_percent = static_cast<int>(zoom_level_ * 100.0f);
359 "%s %d%%", ICON_MD_ZOOM_IN, zoom_percent);
360
361 if (ImGui::IsItemHovered()) {
362 ImGui::SetTooltip("Zoom: %d%%", zoom_percent);
363 }
364}
365
369
371 for (const auto& [key, value] : custom_segments_) {
374 "%s: %s", key.c_str(), value.c_str());
375 }
376}
377
379 ImGui::SameLine();
381 ImGui::SameLine();
382}
383
384} // namespace editor
385} // namespace yaze
HandlerId Subscribe(std::function< void(const T &)> handler)
Definition event_bus.h:22
bool dirty() const
Definition rom.h:133
auto short_name() const
Definition rom.h:147
bool is_loaded() const
Definition rom.h:132
Instance-based runtime context replacing ContentRegistry::Context.
static constexpr float kStatusBarHeight
Definition status_bar.h:166
void HandleStatusUpdate(const StatusUpdateEvent &event)
Definition status_bar.cc:53
GlobalEditorContext * context_
Definition status_bar.h:182
float GetHeight() const
Get the height of the status bar.
Definition status_bar.cc:20
void SetSessionInfo(size_t session_id, size_t total_sessions)
Set session information.
Definition status_bar.cc:75
static constexpr float kStatusBarTouchHeight
Definition status_bar.h:167
std::string agent_provider_
Definition status_bar.h:216
void ClearCursorPosition()
Clear cursor position (no cursor in editor)
Definition status_bar.cc:87
std::function< void()> agent_toggle_callback_
Definition status_bar.h:218
void SetSelection(int count, int width=0, int height=0)
Set selection information.
Definition status_bar.cc:91
void ClearZoom()
Clear zoom display.
void SetCustomSegment(const std::string &key, const std::string &value)
Set a custom segment with key-value pair.
void SetZoom(float level)
Set current zoom level.
std::string cursor_label_
Definition status_bar.h:194
std::unordered_map< std::string, std::string > custom_segments_
Definition status_bar.h:211
void ClearSelection()
Clear selection info.
Definition status_bar.cc:98
void ClearEditorMode()
Clear editor mode display.
void Initialize(GlobalEditorContext *context)
Definition status_bar.cc:30
void SetCursorPosition(int x, int y, const char *label="Pos")
Set cursor/mouse position in editor coordinates.
Definition status_bar.cc:80
void SetEditorMode(const std::string &mode)
Set the current editor mode or tool.
void Draw()
Draw the status bar.
void ClearAllContext()
Clear all context (cursor, selection, zoom, mode, custom)
void ClearCustomSegment(const std::string &key)
Remove a custom segment.
void SetAgentInfo(const std::string &provider, const std::string &model, bool active)
RAII for fixed-position panels (activity bar, side panel, status bar).
static SafeAreaInsets GetSafeAreaInsets()
RAII guard for ImGui style colors.
Definition style_guard.h:27
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
#define ICON_MD_LAYERS
Definition icons.h:1068
#define ICON_MD_DESCRIPTION
Definition icons.h:539
#define ICON_MD_ZOOM_IN
Definition icons.h:2194
#define ICON_MD_SELECT_ALL
Definition icons.h:1680
#define ICON_MD_FIBER_MANUAL_RECORD
Definition icons.h:739
#define ICON_MD_SMART_TOY
Definition icons.h:1781
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:134
void ColoredText(const char *text, const ImVec4 &color)
ImVec4 GetSurfaceContainerHighestVec4()
bool ThemedButton(const char *label, const ImVec2 &size, const char *panel_id, const char *anim_id)
Draw a standard text button with theme colors.
ImVec4 GetPrimaryVec4()
ImVec4 GetTextSecondaryVec4()
void ColoredTextF(const ImVec4 &color, const char *fmt,...)
ImVec4 GetSurfaceContainerHighVec4()
ImVec4 GetOutlineVec4()
ImVec4 GetSurfaceContainerVec4()
Published when selection changes in any editor.
Published when zoom level changes in any canvas/editor.