1#define IMGUI_DEFINE_MATH_OPERATORS
10#include "absl/strings/str_format.h"
21#include "imgui/imgui.h"
22#include "imgui/imgui_internal.h"
49 return panel_ptr->IsEnabled();
64 const std::string& category) {
65 if (category ==
"Dungeon")
67 if (category ==
"Overworld")
69 if (category ==
"Graphics")
71 if (category ==
"Palette")
73 if (category ==
"Sprite")
75 if (category ==
"Music")
77 if (category ==
"Message")
79 if (category ==
"Screen")
81 if (category ==
"Emulator")
83 if (category ==
"Assembly")
85 if (category ==
"Settings")
87 if (category ==
"Memory")
89 if (category ==
"Agent")
99 const std::string& category) {
103 if (category ==
"Dungeon") {
105 return {0.95f, 0.75f, 0.20f, 1.0f, 0.95f, 0.75f, 0.20f};
107 if (category ==
"Overworld") {
109 return {0.30f, 0.85f, 0.45f, 1.0f, 0.30f, 0.85f, 0.45f};
111 if (category ==
"Graphics") {
113 return {0.40f, 0.70f, 0.95f, 1.0f, 0.40f, 0.70f, 0.95f};
115 if (category ==
"Palette") {
117 return {0.90f, 0.40f, 0.70f, 1.0f, 0.90f, 0.40f, 0.70f};
119 if (category ==
"Sprite") {
121 return {0.30f, 0.85f, 0.85f, 1.0f, 0.30f, 0.85f, 0.85f};
123 if (category ==
"Music") {
125 return {0.70f, 0.40f, 0.90f, 1.0f, 0.70f, 0.40f, 0.90f};
127 if (category ==
"Message") {
129 return {0.95f, 0.90f, 0.40f, 1.0f, 0.95f, 0.90f, 0.40f};
131 if (category ==
"Screen") {
133 return {0.90f, 0.92f, 0.95f, 1.0f, 0.90f, 0.92f, 0.95f};
135 if (category ==
"Emulator") {
137 return {0.90f, 0.35f, 0.40f, 1.0f, 0.90f, 0.35f, 0.40f};
139 if (category ==
"Assembly") {
141 return {0.40f, 0.90f, 0.50f, 1.0f, 0.40f, 0.90f, 0.50f};
143 if (category ==
"Settings") {
145 return {0.60f, 0.70f, 0.80f, 1.0f, 0.60f, 0.70f, 0.80f};
147 if (category ==
"Memory") {
149 return {0.95f, 0.60f, 0.25f, 1.0f, 0.95f, 0.60f, 0.25f};
151 if (category ==
"Agent") {
153 return {0.60f, 0.40f, 0.95f, 1.0f, 0.60f, 0.40f, 0.95f};
157 return {0.50f, 0.60f, 0.80f, 1.0f, 0.50f, 0.60f, 0.80f};
163 if (viewport_width <= 0.0f) {
166 bounds.max_width = std::max(520.0f, fallback);
170 const float min_width = std::max(220.0f, viewport_width * 0.18f);
171 const float max_width = std::max(min_width + 20.0f, viewport_width * 0.62f);
174 bounds.max_width = max_width;
179 float viewport_width)
const {
182 return default_width;
190 float viewport_width,
201 const float clamped = std::clamp(width, bounds.min_width, bounds.max_width);
223 const float fallback = GetDefaultPanelBrowserCategoryWidth();
224 const float clamped = std::max(180.0f, width > 0.0f ? width : fallback);
236 const std::string& prefixed_id) {
242 const std::string& prefixed_id)
const {
254 size_t session_id)
const {
259std::unordered_map<std::string, std::string>*
266const std::unordered_map<std::string, std::string>*
273std::unordered_map<std::string, std::string>*
280const std::unordered_map<std::string, std::string>*
282 size_t session_id)
const {
289 size_t session_id,
const std::string& prefixed_window_id,
290 const std::string& base_window_id,
const std::string& category,
291 bool visible)
const {
294 prefixed_window_id, base_window_id, category, visible, session_id));
299 const std::string& resource_type)
const {
300 if (resource_type ==
"room") {
303 if (resource_type ==
"song") {
306 if (resource_type ==
"sheet") {
309 if (resource_type ==
"map") {
317 if (!resource_panel) {
326 const std::string& panel_id) {
332 const std::string resource_type = type_it->second;
335 panels_it->second.remove(panel_id);
336 if (panels_it->second.empty()) {
344 const std::list<std::string>& panel_ids)
const {
345 for (
const auto& panel_id : panel_ids) {
351 return panel_ids.empty() ? std::string{} : panel_ids.front();
369 std::string panel_id =
372 bool already_registered = (
cards_.find(panel_id) !=
cards_.end());
375 "Panel '%s' already registered, skipping duplicate",
379 if (!already_registered) {
391 cards_[panel_id] = panel_info;
394 "Registered card %s -> %s for session %zu",
395 canonical_info.
card_id.c_str(), panel_id.c_str(), session_id);
409 size_t session_id,
const std::string& card_id,
410 const std::string& display_name,
const std::string& icon,
411 const std::string& category,
const std::string& shortcut_hint,
int priority,
412 std::function<
void()> on_show, std::function<
void()> on_hide,
413 bool visible_by_default) {
428 if (visible_by_default) {
434 const std::string& base_card_id) {
437 if (prefixed_id.empty()) {
441 auto it =
cards_.find(prefixed_id);
443 LOG_INFO(
"WorkspaceWindowManager",
"Unregistered card: %s",
444 prefixed_id.c_str());
455 std::remove(card_list.begin(), card_list.end(), prefixed_id),
459 mapping.erase(canonical_base_id);
461 for (
auto& [mapped_session, reverse_mapping] :
463 reverse_mapping.erase(prefixed_id);
470 session_card_list.erase(std::remove(session_card_list.begin(),
471 session_card_list.end(), prefixed_id),
472 session_card_list.end());
479 const std::string& prefix) {
481 std::string prefixed_id;
482 size_t session_id = 0;
485 std::vector<RemovalInfo> to_remove;
488 for (
const auto& [card_id, card_info] :
cards_) {
490 if (card_id.find(prefix) == 0) {
492 info.prefixed_id = card_id;
493 for (
const auto& [session_id, reverse_mapping] :
495 auto reverse_it = reverse_mapping.find(card_id);
496 if (reverse_it != reverse_mapping.end()) {
497 info.session_id = session_id;
498 info.base_id = reverse_it->second;
502 to_remove.push_back(std::move(info));
507 for (
const auto& info : to_remove) {
508 if (!info.base_id.empty()) {
513 cards_.erase(info.prefixed_id);
516 LOG_INFO(
"WorkspaceWindowManager",
"Unregistered card with prefix '%s': %s",
517 prefix.c_str(), info.prefixed_id.c_str());
522 card_list.erase(std::remove_if(card_list.begin(), card_list.end(),
523 [&prefix](
const std::string&
id) {
524 return id.find(prefix) == 0;
544 LOG_INFO(
"WorkspaceWindowManager",
"Cleared all cards");
552 std::unique_ptr<WindowContent> panel) {
555 "Attempted to register null WindowContent");
560 if (resource_panel) {
564 std::string panel_id = panel->GetId();
569 "WindowContent '%s' already registered, skipping registry add",
584 LOG_INFO(
"WorkspaceWindowManager",
"Registered registry WindowContent: %s",
601 std::unique_ptr<WindowContent> panel) {
604 "Attempted to register null WindowContent");
609 if (resource_panel) {
619 bool visible_by_default = panel->IsVisibleByDefault();
627 std::string instance_id;
628 bool descriptor_preexisting =
false;
630 if (
const auto* session_mapping =
632 if (
auto mapping_it = session_mapping->find(panel_id);
633 mapping_it != session_mapping->end() &&
634 cards_.contains(mapping_it->second)) {
635 instance_id = mapping_it->second;
636 descriptor_preexisting =
true;
640 descriptor_preexisting =
cards_.contains(panel_id);
642 if (instance_id.empty()) {
647 if (instance_id.empty()) {
655 if (!descriptor_preexisting) {
656 if (
auto descriptor_it =
cards_.find(instance_id);
657 descriptor_it !=
cards_.end()) {
658 descriptor_it->second.enabled_condition = [
this, instance_id]() {
661 instance_it->second->IsEnabled();
671 existing->second->OnClose();
674 existing->second = std::move(panel);
676 if (visible_by_default) {
679 LOG_INFO(
"WorkspaceWindowManager",
"Replaced WindowContent: %s",
680 instance_id.c_str());
685 if (visible_by_default) {
694 LOG_INFO(
"WorkspaceWindowManager",
"Registered WindowContent: %s (%s)",
703 const std::string& resource_type) {
708 auto& panel_list = it->second;
712 while (panel_list.size() >= limit) {
714 if (panel_to_evict.empty()) {
719 panel_list.remove(panel_to_evict);
730 std::string type = type_it->second;
735 list.remove(panel_id);
736 list.push_back(panel_id);
740 const std::string& panel_id) {
742 std::string base_panel_id;
743 std::string instance_id;
750 for (
const auto& [session_id, reverse_mapping] :
752 if (
auto reverse_it = reverse_mapping.find(panel_id);
753 reverse_it != reverse_mapping.end()) {
754 owner_session = session_id;
755 base_panel_id = reverse_it->second;
756 instance_id = panel_id;
762 if (instance_id.empty()) {
764 if (
const auto* active_mapping =
766 if (
auto mapping_it = active_mapping->find(requested_base_id);
767 mapping_it != active_mapping->end()) {
768 base_panel_id = requested_base_id;
769 instance_id = mapping_it->second;
776 if (instance_id.empty()) {
777 for (
const auto& [session_id, reverse_mapping] :
779 if (
auto reverse_it = reverse_mapping.find(panel_id);
780 reverse_it != reverse_mapping.end()) {
781 owner_session = session_id;
782 base_panel_id = reverse_it->second;
783 instance_id = panel_id;
788 if (instance_id.empty()) {
792 if (instance_id.empty()) {
793 instance_id = panel_id;
800 it->second->OnClose();
805 LOG_INFO(
"WorkspaceWindowManager",
"Unregistered WindowContent: %s",
806 instance_id.c_str());
814 const std::string& panel_id) {
819 size_t session_id,
const std::string& panel_id) {
821 if (!session_mapping) {
826 if (base_panel_id.empty()) {
829 auto mapping_it = session_mapping->find(base_panel_id);
830 if (mapping_it == session_mapping->end()) {
837 const std::string& prefixed_panel_id,
const std::string& base_panel_id) {
840 return prefixed_it->second.get();
844 return base_it->second.get();
850 const std::string& prefixed_panel_id,
851 const std::string& base_panel_id)
const {
854 return prefixed_it->second.get();
858 return base_it->second.get();
877 bool animations_enabled = animator.IsEnabled();
880 const auto resolve_switch_speed = [&](
float snappy,
float standard,
882 switch (animator.motion_profile()) {
892 const float category_transition_speed =
893 resolve_switch_speed(8.5f, 6.0f, 4.5f);
894 const float panel_fade_speed = resolve_switch_speed(11.0f, 8.0f, 6.0f);
897 float global_alpha = 1.0f;
898 if (animations_enabled) {
899 global_alpha = animator.Animate(
"global",
"category_transition", 1.0f,
900 category_transition_speed);
903 for (
const auto& prefixed_panel_id : session_it->second) {
904 auto descriptor_it =
cards_.find(prefixed_panel_id);
905 if (descriptor_it ==
cards_.end()) {
910 std::string base_panel_id =
912 if (base_panel_id.empty()) {
913 base_panel_id = prefixed_panel_id;
926 bool should_draw =
false;
937 float target_alpha = should_draw ? 1.0f : 0.0f;
940 float current_alpha = 1.0f;
941 if (animations_enabled) {
942 current_alpha = animator.Animate(prefixed_panel_id,
"panel_alpha",
943 target_alpha, panel_fade_speed);
944 current_alpha *= global_alpha;
946 current_alpha = target_alpha;
950 if (current_alpha < 0.01f) {
959 std::string display_name = descriptor.
display_name.empty()
982 if (preferred_width > 0.0f || preferred_height > 0.0f) {
984 preferred_width > 0.0f ? preferred_width : 400.0f,
985 preferred_height > 0.0f ? preferred_height : 300.0f);
998 std::optional<gui::StyleVarGuard> alpha_guard;
999 if (current_alpha < 1.0f) {
1000 alpha_guard.emplace(ImGuiStyleVar_Alpha, current_alpha);
1003 animator.ApplyPanelTransitionPre(prefixed_panel_id);
1004 if (window.
Begin(visibility_flag)) {
1008 animator.ApplyPanelTransitionPost(prefixed_panel_id);
1010 alpha_guard.reset();
1013 if (visibility_flag && !*visibility_flag) {
1020 const std::string& to_category) {
1021 if (from_category == to_category) {
1025 LOG_INFO(
"WorkspaceWindowManager",
"Switching from category '%s' to '%s'",
1026 from_category.c_str(), to_category.c_str());
1048 const auto incoming =
1050 for (
const auto& descriptor : incoming) {
1051 if (descriptor.visibility_flag && *descriptor.visibility_flag) {
1067 const std::string& base_card_id) {
1070 if (prefixed_id.empty()) {
1076 const bool was_visible =
1077 (descriptor->visibility_flag && *descriptor->visibility_flag);
1078 if (descriptor->visibility_flag) {
1079 *descriptor->visibility_flag =
true;
1081 if (descriptor->on_show) {
1082 descriptor->on_show();
1092 descriptor->category,
true);
1099 const std::string& base_card_id) {
1102 if (prefixed_id.empty()) {
1108 const bool was_visible =
1109 (descriptor->visibility_flag && *descriptor->visibility_flag);
1110 if (descriptor->visibility_flag) {
1111 *descriptor->visibility_flag =
false;
1113 if (descriptor->on_hide) {
1114 descriptor->on_hide();
1124 descriptor->category,
false);
1131 const std::string& base_card_id) {
1134 if (prefixed_id.empty()) {
1139 if (descriptor && descriptor->visibility_flag) {
1140 bool new_state = !(*descriptor->visibility_flag);
1141 *descriptor->visibility_flag = new_state;
1143 if (new_state && descriptor->on_show) {
1144 descriptor->on_show();
1145 }
else if (!new_state && descriptor->on_hide) {
1146 descriptor->on_hide();
1158 descriptor->category, new_state);
1165 size_t session_id,
const std::string& base_card_id)
const {
1168 if (prefixed_id.empty()) {
1173 if (descriptor && descriptor->visibility_flag) {
1174 return *descriptor->visibility_flag;
1180 size_t session_id,
const std::string& base_card_id) {
1183 if (prefixed_id.empty()) {
1189 return descriptor->visibility_flag;
1200 for (
const auto& prefixed_card_id : *session_windows) {
1202 if (descriptor->visibility_flag) {
1203 *descriptor->visibility_flag =
true;
1205 if (descriptor->on_show) {
1206 descriptor->on_show();
1215 for (
const auto& prefixed_card_id : *session_windows) {
1217 if (descriptor->visibility_flag) {
1218 *descriptor->visibility_flag =
false;
1220 if (descriptor->on_hide) {
1221 descriptor->on_hide();
1229 size_t session_id,
const std::string& category) {
1231 for (
const auto& prefixed_card_id : *session_windows) {
1233 if (descriptor->category != category) {
1236 if (descriptor->visibility_flag) {
1237 *descriptor->visibility_flag =
true;
1239 if (descriptor->on_show) {
1240 descriptor->on_show();
1248 size_t session_id,
const std::string& category) {
1250 for (
const auto& prefixed_card_id : *session_windows) {
1252 if (descriptor->category != category) {
1255 if (descriptor->visibility_flag) {
1256 *descriptor->visibility_flag =
false;
1258 if (descriptor->on_hide) {
1259 descriptor->on_hide();
1267 const std::string& base_card_id) {
1270 if (prefixed_id.empty()) {
1279 std::string category = target->category;
1293 size_t session_id)
const {
1294 std::vector<std::string> result;
1296 result.reserve(session_windows->size());
1297 for (
const auto& prefixed_window_id : *session_windows) {
1298 const std::string base_window_id =
1300 result.push_back(base_window_id.empty() ? prefixed_window_id
1308 size_t session_id,
const std::string& category)
const {
1309 std::vector<WindowDescriptor> result;
1312 for (
const auto& prefixed_window_id : *session_windows) {
1313 if (
const auto* descriptor =
1315 if (descriptor->category == category) {
1317 const std::string base_window_id =
1319 if (!base_window_id.empty()) {
1320 window.
card_id = base_window_id;
1322 result.push_back(std::move(window));
1329 std::sort(result.begin(), result.end(),
1331 return a.priority < b.priority;
1338 size_t session_id)
const {
1339 std::vector<std::string> categories;
1342 for (
const auto& prefixed_window_id : *session_windows) {
1343 if (
const auto* descriptor =
1345 if (std::find(categories.begin(), categories.end(),
1346 descriptor->category) == categories.end()) {
1347 categories.push_back(descriptor->category);
1356 size_t session_id,
const std::string& base_card_id)
const {
1359 if (prefixed_id.empty()) {
1367 std::vector<std::string> categories;
1369 if (std::find(categories.begin(), categories.end(), card_info.category) ==
1371 categories.push_back(card_info.category);
1382 size_t session_id)
const {
1383 std::vector<std::string> visible_panels;
1386 if (!window_mapping) {
1387 return visible_panels;
1390 for (
const auto& [base_id, prefixed_id] : *window_mapping) {
1392 if (descriptor->visibility_flag && *descriptor->visibility_flag) {
1393 visible_panels.push_back(base_id);
1398 return visible_panels;
1406 const std::string& description) {
1412 for (
const auto& [card_id, card_info] :
cards_) {
1413 if (card_info.visibility_flag && *card_info.visibility_flag) {
1420 LOG_INFO(
"WorkspaceWindowManager",
"Saved preset: %s (%zu cards)",
1431 for (
auto& [card_id, card_info] :
cards_) {
1432 if (card_info.visibility_flag) {
1433 *card_info.visibility_flag =
false;
1438 for (
const auto& card_id : it->second.visible_cards) {
1439 auto card_it =
cards_.find(card_id);
1440 if (card_it !=
cards_.end() && card_it->second.visibility_flag) {
1441 *card_it->second.visibility_flag =
true;
1442 if (card_it->second.on_show) {
1443 card_it->second.on_show();
1448 LOG_INFO(
"WorkspaceWindowManager",
"Loaded preset: %s", name.c_str());
1457std::vector<WorkspaceWindowManager::WorkspacePreset>
1459 std::vector<WorkspacePreset> result;
1460 for (
const auto& [name, preset] :
presets_) {
1461 result.push_back(preset);
1483 LOG_INFO(
"WorkspaceWindowManager",
"Reset to defaults for session %zu",
1491 if (category.empty()) {
1493 "No category found for editor type %d, skipping reset",
1494 static_cast<int>(editor_type));
1505 for (
const auto& card_id : default_panels) {
1507 LOG_INFO(
"WorkspaceWindowManager",
"Showing default card: %s",
1513 "Reset %s editor to defaults (%zu cards visible)", category.c_str(),
1514 default_panels.size());
1522 size_t session_id,
const std::string& base_id)
const {
1527 const std::string& base_id,
1531 return canonical_base_id;
1534 return absl::StrFormat(
"s%zu.%s", session_id, canonical_base_id);
1536 return canonical_base_id;
static std::string GetEditorCategory(EditorType type)
Interface for editor classes.
static std::vector< std::string > GetDefaultPanels(EditorType type)
Get default visible panels for an editor.
Base class for windows that edit specific ROM resources.
virtual std::string GetResourceType() const =0
The resource type name.
Base interface for all logical window content components.
virtual std::string GetWorkflowDescription() const
Optional workflow description for menus/command palette.
virtual std::string GetDisabledTooltip() const
Get tooltip text when panel is disabled.
virtual int GetWorkflowPriority() const
Optional workflow ordering priority (lower sorts first).
virtual std::string GetDisplayName() const =0
Human-readable name shown in menus and title bars.
virtual WindowLifecycle GetWindowLifecycle() const
Get the lifecycle category for this window.
virtual std::string GetEditorCategory() const =0
Editor category this panel belongs to.
virtual int GetPriority() const
Get display priority for menu ordering.
virtual void OnClose()
Called when panel is hidden.
virtual WindowScope GetScope() const
Get the registration scope for this window.
virtual std::string GetIcon() const =0
Material Design icon for this panel.
virtual float GetPreferredHeight() const
Get preferred height for this panel (optional)
virtual float GetPreferredWidth() const
Get preferred width for this panel (optional)
virtual WindowContextScope GetContextScope() const
Optional context binding for this window (room/selection/etc)
virtual std::string GetWorkflowLabel() const
Optional workflow label for menus/command palette.
void DrawWithLazyInit(bool *p_open)
Execute lazy initialization if needed, then call Draw()
virtual std::string GetId() const =0
Unique identifier for this panel.
virtual std::string GetWorkflowGroup() const
Optional workflow group for hack-centric actions.
virtual std::string GetShortcutHint() const
Get keyboard shortcut hint for display.
void ResetSidePanelWidth(bool notify=true)
void RegisterPanel(size_t session_id, const WindowDescriptor &base_info)
bool IsWindowPinnedImpl(size_t session_id, const std::string &base_card_id) const
void SavePreset(const std::string &name, const std::string &description="")
std::vector< std::string > GetWindowsInSessionImpl(size_t session_id) const
void SetActiveSidePanelWidth(float width, float viewport_width=0.0f, bool notify=true)
void HideAllWindowsInCategory(size_t session_id, const std::string &category)
bool CloseWindowImpl(size_t session_id, const std::string &base_card_id)
size_t GetResourceWindowLimit(const std::string &resource_type) const
std::unordered_map< size_t, std::unordered_map< std::string, std::string > > & session_reverse_card_mapping_
static SidePanelWidthBounds GetSidePanelWidthBounds(float viewport_width)
void DeletePreset(const std::string &name)
std::vector< WorkspacePreset > GetPresets() const
void ResetToDefaults(size_t session_id)
void UnregisterWindowContent(const std::string &window_id)
Unregister and destroy a WindowContent instance.
std::unordered_map< std::string, std::string > * FindSessionWindowMapping(size_t session_id)
std::string SelectResourceWindowForEviction(const std::list< std::string > &panel_ids) const
bool * GetVisibilityFlag(size_t session_id, const std::string &base_card_id)
void UntrackResourceWindow(const std::string &panel_id)
std::string ResolveBaseWindowId(const std::string &panel_id) const
std::unordered_map< std::string, WindowDescriptor > & cards_
WindowBrowserState browser_state_
std::string GetPrefixedWindowId(size_t session_id, const std::string &base_id) const
bool LoadPreset(const std::string &name)
static float GetSidePanelWidthForViewport(float viewport_width)
std::vector< std::string > * FindSessionWindowIds(size_t session_id)
const WindowDescriptor * GetWindowDescriptorImpl(size_t session_id, const std::string &base_card_id) const
void RememberPinnedStateForRemovedWindow(size_t session_id, const std::string &base_card_id, const std::string &prefixed_id)
std::string GetBaseIdForPrefixedId(size_t session_id, const std::string &prefixed_id) const
static CategoryTheme GetCategoryTheme(const std::string &category)
std::unordered_map< std::string, std::string > & panel_resource_types_
std::vector< WindowDescriptor > GetWindowsInCategoryImpl(size_t session_id, const std::string &category) const
std::unordered_map< std::string, bool > & centralized_visibility_
std::unordered_map< size_t, std::unordered_map< std::string, std::string > > & session_card_mapping_
void MarkPanelUsed(const std::string &panel_id)
Mark a panel as recently used (for LRU)
void TrackPanelForSession(size_t session_id, const std::string &base_id, const std::string &panel_id)
std::unordered_map< std::string, std::list< std::string > > & resource_panels_
WindowSessionState session_state_
void TrackResourceWindow(const std::string &panel_id, ResourceWindowContent *resource_panel)
std::vector< std::string > GetAllCategories() const
void SetActiveCategory(const std::string &category, bool notify=true)
void RegisterRegistryWindowContent(std::unique_ptr< WindowContent > window)
Register a ContentRegistry-managed WindowContent instance.
static std::string GetCategoryIcon(const std::string &category)
void UnregisterPanel(size_t session_id, const std::string &base_card_id)
void ShowOnlyWindow(size_t session_id, const std::string &base_window_id)
void RegisterWindowContent(std::unique_ptr< WindowContent > window)
Register a WindowContent instance for central drawing.
std::function< Editor *(const std::string &) editor_resolver_)
static constexpr const char * kDashboardCategory
std::unordered_map< std::string, WorkspacePreset > presets_
void EnforceResourceLimits(const std::string &resource_type)
Enforce limits on resource panels (LRU eviction)
WindowDescriptor * FindDescriptorByPrefixedId(const std::string &prefixed_id)
void SetPanelBrowserCategoryWidth(float width, bool notify=true)
bool IsWindowVisibleImpl(size_t session_id, const std::string &base_card_id) const
void DrawAllVisiblePanels()
Draw all visible WindowContent instances (central drawing)
std::unordered_map< std::string, std::unique_ptr< WindowContent > > & panel_instances_
std::unordered_set< std::string > & registry_panel_ids_
std::vector< std::string > GetVisibleWindowIdsImpl(size_t session_id) const
void SetWindowPinnedImpl(size_t session_id, const std::string &base_card_id, bool pinned)
bool ToggleWindowImpl(size_t session_id, const std::string &base_card_id)
std::unordered_map< size_t, std::vector< std::string > > & session_cards_
void EnforceResourceWindowLimits(const std::string &resource_type)
std::unordered_map< std::string, std::string > * FindSessionReverseWindowMapping(size_t session_id)
float GetActiveSidePanelWidth(float viewport_width) const
std::string MakeWindowId(size_t session_id, const std::string &base_id) const
bool ShouldPrefixPanels() const
void OnEditorSwitch(const std::string &from_category, const std::string &to_category)
Handle editor/category switching for panel visibility.
void HideAllWindowsInSession(size_t session_id)
std::unordered_map< std::string, bool > & pinned_panels_
void RegisterSession(size_t session_id)
void ShowAllWindowsInSession(size_t session_id)
WindowContent * GetWindowContent(const std::string &window_id)
Get a WindowContent instance by ID.
void RegisterRegistryWindowContentsForSession(size_t session_id)
Register descriptors for all registry window contents in a session.
std::unordered_map< size_t, std::unordered_map< WindowContextScope, std::string, WindowContextScopeHash > > & session_context_keys_
WindowContent * FindPanelInstance(const std::string &prefixed_panel_id, const std::string &base_panel_id)
WindowRegistryState registry_state_
void UnregisterPanelsWithPrefix(const std::string &prefix)
void PublishWindowVisibilityChanged(size_t session_id, const std::string &prefixed_window_id, const std::string &base_window_id, const std::string &category, bool visible) const
void RegisterPanelDescriptorForSession(size_t session_id, const WindowContent &panel)
bool OpenWindowImpl(size_t session_id, const std::string &base_card_id)
void ShowAllWindowsInCategory(size_t session_id, const std::string &category)
std::unordered_set< std::string > & global_panel_ids_
void ClearAnimationsForPanel(const std::string &panel_id)
void BeginPanelTransition(const std::string &panel_id, TransitionType type)
static bool IsTouchDevice()
Draggable, dockable panel for editor sub-windows.
void SetPinChangedCallback(std::function< void(bool)> callback)
void SetPinned(bool pinned)
void SetStableId(const std::string &stable_id)
void SetPinnable(bool pinnable)
void SetPosition(Position pos)
bool Begin(bool *p_open=nullptr)
void SetDefaultSize(float width, float height)
#define ICON_MD_VIDEOGAME_ASSET
#define ICON_MD_MUSIC_NOTE
#define ICON_MD_SMART_TOY
#define LOG_ERROR(category, format,...)
#define LOG_WARN(category, format,...)
#define LOG_INFO(category, format,...)
::yaze::EventBus * event_bus()
Get the current EventBus instance.
void SetCurrentEditor(Editor *editor)
Set the currently active editor.
constexpr size_t kMaxTotalResourcePanels
Maximum total resource panels across all types.
constexpr size_t kMaxSongPanels
Maximum open song panels (music editor)
constexpr size_t kMaxSheetPanels
Maximum open graphics sheet panels.
constexpr size_t kMaxRoomPanels
Maximum open room panels (dungeon editor)
constexpr size_t kMaxMapPanels
Maximum open map panels (overworld editor)
WindowDescriptor BuildDescriptorFromPanel(const WindowContent &panel)
WindowScope
Defines whether a window is session-scoped or global.
static PanelVisibilityChangedEvent Create(const std::string &id, const std::string &base_id, const std::string &cat, bool vis, size_t session=0)
Metadata for a dockable editor window (formerly PanelInfo)
std::function< void()> on_show
std::string shortcut_hint
std::string workflow_group
std::function< void()> on_hide
WindowContextScope context_scope
std::string disabled_tooltip
std::string workflow_description
std::string workflow_label
std::function< bool()> enabled_condition
WindowLifecycle window_lifecycle
Get the expressive theme color for a category.
std::function< void(float width)> on_window_browser_width_changed
std::string active_category
float window_browser_category_width
std::function< void(float width)> on_sidebar_width_changed
std::unordered_map< std::string, WindowDescriptor > descriptors
std::unordered_map< size_t, std::vector< std::string > > session_windows
std::unordered_map< size_t, std::unordered_map< std::string, std::string > > session_reverse_window_mapping
std::unordered_map< size_t, std::unordered_map< std::string, std::string > > session_window_mapping
std::vector< std::string > visible_cards