1#define IMGUI_DEFINE_MATH_OPERATORS
11#include "absl/strings/str_format.h"
22#include "imgui/imgui.h"
23#include "imgui/imgui_internal.h"
52 return panel_ptr->IsEnabled();
67 const std::string& category) {
68 if (category ==
"Dungeon")
70 if (category ==
"Overworld")
72 if (category ==
"Graphics")
74 if (category ==
"Palette")
76 if (category ==
"Sprite")
78 if (category ==
"Music")
80 if (category ==
"Message")
82 if (category ==
"Screen")
84 if (category ==
"Emulator")
86 if (category ==
"Assembly")
88 if (category ==
"Settings")
90 if (category ==
"Memory")
92 if (category ==
"Agent")
94 if (category ==
"Planning")
104 const std::string& category) {
108 if (category ==
"Dungeon") {
110 return {0.95f, 0.75f, 0.20f, 1.0f, 0.95f, 0.75f, 0.20f};
112 if (category ==
"Overworld") {
114 return {0.30f, 0.85f, 0.45f, 1.0f, 0.30f, 0.85f, 0.45f};
116 if (category ==
"Graphics") {
118 return {0.40f, 0.70f, 0.95f, 1.0f, 0.40f, 0.70f, 0.95f};
120 if (category ==
"Palette") {
122 return {0.90f, 0.40f, 0.70f, 1.0f, 0.90f, 0.40f, 0.70f};
124 if (category ==
"Sprite") {
126 return {0.30f, 0.85f, 0.85f, 1.0f, 0.30f, 0.85f, 0.85f};
128 if (category ==
"Music") {
130 return {0.70f, 0.40f, 0.90f, 1.0f, 0.70f, 0.40f, 0.90f};
132 if (category ==
"Message") {
134 return {0.95f, 0.90f, 0.40f, 1.0f, 0.95f, 0.90f, 0.40f};
136 if (category ==
"Screen") {
138 return {0.90f, 0.92f, 0.95f, 1.0f, 0.90f, 0.92f, 0.95f};
140 if (category ==
"Emulator") {
142 return {0.90f, 0.35f, 0.40f, 1.0f, 0.90f, 0.35f, 0.40f};
144 if (category ==
"Assembly") {
146 return {0.40f, 0.90f, 0.50f, 1.0f, 0.40f, 0.90f, 0.50f};
148 if (category ==
"Settings") {
150 return {0.60f, 0.70f, 0.80f, 1.0f, 0.60f, 0.70f, 0.80f};
152 if (category ==
"Memory") {
154 return {0.95f, 0.60f, 0.25f, 1.0f, 0.95f, 0.60f, 0.25f};
156 if (category ==
"Agent") {
158 return {0.60f, 0.40f, 0.95f, 1.0f, 0.60f, 0.40f, 0.95f};
160 if (category ==
"Planning") {
162 return {0.95f, 0.65f, 0.35f, 1.0f, 0.95f, 0.65f, 0.35f};
166 return {0.50f, 0.60f, 0.80f, 1.0f, 0.50f, 0.60f, 0.80f};
172 if (viewport_width <= 0.0f) {
175 bounds.max_width = std::max(520.0f, fallback);
179 const float min_width = std::max(220.0f, viewport_width * 0.18f);
180 const float max_width = std::max(min_width + 20.0f, viewport_width * 0.62f);
183 bounds.max_width = max_width;
188 float viewport_width)
const {
191 return default_width;
199 float viewport_width,
210 const float clamped = std::clamp(width, bounds.min_width, bounds.max_width);
232 const float fallback = GetDefaultPanelBrowserCategoryWidth();
233 const float clamped = std::max(180.0f, width > 0.0f ? width : fallback);
245 const std::string& prefixed_id) {
251 const std::string& prefixed_id)
const {
263 size_t session_id)
const {
268std::unordered_map<std::string, std::string>*
275const std::unordered_map<std::string, std::string>*
282std::unordered_map<std::string, std::string>*
289const std::unordered_map<std::string, std::string>*
291 size_t session_id)
const {
298 size_t session_id,
const std::string& prefixed_window_id,
299 const std::string& base_window_id,
const std::string& category,
300 bool visible)
const {
303 prefixed_window_id, base_window_id, category, visible, session_id));
308 const std::string& resource_type)
const {
309 if (resource_type ==
"room") {
312 if (resource_type ==
"song") {
315 if (resource_type ==
"sheet") {
318 if (resource_type ==
"map") {
326 if (!resource_panel) {
335 const std::string& panel_id) {
341 const std::string resource_type = type_it->second;
344 panels_it->second.remove(panel_id);
345 if (panels_it->second.empty()) {
353 const std::list<std::string>& panel_ids)
const {
354 for (
const auto& panel_id : panel_ids) {
360 return panel_ids.empty() ? std::string{} : panel_ids.front();
378 std::string panel_id =
381 bool already_registered = (
cards_.find(panel_id) !=
cards_.end());
384 "Panel '%s' already registered, skipping duplicate",
388 if (!already_registered) {
400 cards_[panel_id] = panel_info;
403 "Registered card %s -> %s for session %zu",
404 canonical_info.
card_id.c_str(), panel_id.c_str(), session_id);
418 size_t session_id,
const std::string& card_id,
419 const std::string& display_name,
const std::string& icon,
420 const std::string& category,
const std::string& shortcut_hint,
int priority,
421 std::function<
void()> on_show, std::function<
void()> on_hide,
422 bool visible_by_default) {
437 if (visible_by_default) {
443 const std::string& base_card_id) {
446 if (prefixed_id.empty()) {
452 auto it =
cards_.find(prefixed_id);
454 LOG_DEBUG(
"WorkspaceWindowManager",
"Unregistered card: %s",
455 prefixed_id.c_str());
466 std::remove(card_list.begin(), card_list.end(), prefixed_id),
470 mapping.erase(canonical_base_id);
472 for (
auto& [mapped_session, reverse_mapping] :
474 reverse_mapping.erase(prefixed_id);
481 session_card_list.erase(std::remove(session_card_list.begin(),
482 session_card_list.end(), prefixed_id),
483 session_card_list.end());
490 const std::string& prefix) {
492 std::string prefixed_id;
493 size_t session_id = 0;
496 std::vector<RemovalInfo> to_remove;
499 for (
const auto& [card_id, card_info] :
cards_) {
501 if (card_id.find(prefix) == 0) {
503 info.prefixed_id = card_id;
504 for (
const auto& [session_id, reverse_mapping] :
506 auto reverse_it = reverse_mapping.find(card_id);
507 if (reverse_it != reverse_mapping.end()) {
508 info.session_id = session_id;
509 info.base_id = reverse_it->second;
513 to_remove.push_back(std::move(info));
518 for (
const auto& info : to_remove) {
519 if (!info.base_id.empty()) {
525 cards_.erase(info.prefixed_id);
529 "Unregistered card with prefix '%s': %s", prefix.c_str(),
530 info.prefixed_id.c_str());
535 card_list.erase(std::remove_if(card_list.begin(), card_list.end(),
536 [&prefix](
const std::string&
id) {
537 return id.find(prefix) == 0;
557 LOG_INFO(
"WorkspaceWindowManager",
"Cleared all cards");
565 std::unique_ptr<WindowContent> panel) {
568 "Attempted to register null WindowContent");
573 if (resource_panel) {
577 std::string panel_id = panel->GetId();
582 "WindowContent '%s' already registered, skipping registry add",
597 LOG_DEBUG(
"WorkspaceWindowManager",
"Registered registry WindowContent: %s",
614 std::unique_ptr<WindowContent> panel) {
616 panel ? panel->GetPresentationPolicy()
622 std::unique_ptr<WindowContent> panel,
626 "Attempted to register null WindowContent");
631 if (resource_panel) {
638 WindowDescriptor descriptor = BuildDescriptorFromPanel(*panel, presentation);
641 bool visible_by_default = panel->IsVisibleByDefault();
649 std::string instance_id;
650 bool descriptor_preexisting =
false;
652 if (
const auto* session_mapping =
654 if (
auto mapping_it = session_mapping->find(panel_id);
655 mapping_it != session_mapping->end() &&
656 cards_.contains(mapping_it->second)) {
657 instance_id = mapping_it->second;
658 descriptor_preexisting =
true;
662 descriptor_preexisting =
cards_.contains(panel_id);
664 if (instance_id.empty()) {
669 if (instance_id.empty()) {
676 if (descriptor_preexisting && presentation.
declared) {
677 if (
auto descriptor_it =
cards_.find(instance_id);
678 descriptor_it !=
cards_.end() &&
679 !descriptor_it->second.presentation.declared) {
680 descriptor_it->second.presentation = presentation;
688 if (!descriptor_preexisting) {
689 if (
auto descriptor_it =
cards_.find(instance_id);
690 descriptor_it !=
cards_.end()) {
691 descriptor_it->second.enabled_condition = [
this, instance_id]() {
694 instance_it->second->IsEnabled();
704 existing->second->OnClose();
707 existing->second = std::move(panel);
709 if (visible_by_default) {
712 LOG_DEBUG(
"WorkspaceWindowManager",
"Replaced WindowContent: %s",
713 instance_id.c_str());
718 if (visible_by_default) {
727 LOG_DEBUG(
"WorkspaceWindowManager",
"Registered WindowContent: %s (%s)",
736 const std::string& resource_type) {
741 auto& panel_list = it->second;
745 while (panel_list.size() >= limit) {
747 if (panel_to_evict.empty()) {
752 panel_list.remove(panel_to_evict);
763 std::string type = type_it->second;
768 list.remove(panel_id);
769 list.push_back(panel_id);
773 const std::string& panel_id) {
775 std::string base_panel_id;
776 std::string instance_id;
783 for (
const auto& [session_id, reverse_mapping] :
785 if (
auto reverse_it = reverse_mapping.find(panel_id);
786 reverse_it != reverse_mapping.end()) {
787 owner_session = session_id;
788 base_panel_id = reverse_it->second;
789 instance_id = panel_id;
795 if (instance_id.empty()) {
797 if (
const auto* active_mapping =
799 if (
auto mapping_it = active_mapping->find(requested_base_id);
800 mapping_it != active_mapping->end()) {
801 base_panel_id = requested_base_id;
802 instance_id = mapping_it->second;
809 if (instance_id.empty()) {
810 for (
const auto& [session_id, reverse_mapping] :
812 if (
auto reverse_it = reverse_mapping.find(panel_id);
813 reverse_it != reverse_mapping.end()) {
814 owner_session = session_id;
815 base_panel_id = reverse_it->second;
816 instance_id = panel_id;
821 if (instance_id.empty()) {
825 if (instance_id.empty()) {
826 instance_id = panel_id;
833 it->second->OnClose();
838 LOG_DEBUG(
"WorkspaceWindowManager",
"Unregistered WindowContent: %s",
839 instance_id.c_str());
847 const std::string& panel_id) {
852 size_t session_id,
const std::string& panel_id) {
854 if (!session_mapping) {
859 if (base_panel_id.empty()) {
862 auto mapping_it = session_mapping->find(base_panel_id);
863 if (mapping_it == session_mapping->end()) {
870 const std::string& prefixed_panel_id,
const std::string& base_panel_id) {
873 return prefixed_it->second.get();
877 return base_it->second.get();
883 const std::string& prefixed_panel_id,
884 const std::string& base_panel_id)
const {
887 return prefixed_it->second.get();
891 return base_it->second.get();
910 bool animations_enabled = animator.IsEnabled();
913 const auto resolve_switch_speed = [&](
float snappy,
float standard,
915 switch (animator.motion_profile()) {
925 const float category_transition_speed =
926 resolve_switch_speed(8.5f, 6.0f, 4.5f);
927 const float panel_fade_speed = resolve_switch_speed(11.0f, 8.0f, 6.0f);
930 float global_alpha = 1.0f;
931 if (animations_enabled) {
932 global_alpha = animator.Animate(
"global",
"category_transition", 1.0f,
933 category_transition_speed);
936 for (
const auto& prefixed_panel_id : session_it->second) {
937 auto descriptor_it =
cards_.find(prefixed_panel_id);
938 if (descriptor_it ==
cards_.end()) {
943 std::string base_panel_id =
945 if (base_panel_id.empty()) {
946 base_panel_id = prefixed_panel_id;
959 bool should_draw =
false;
970 float target_alpha = should_draw ? 1.0f : 0.0f;
973 float current_alpha = 1.0f;
974 if (animations_enabled) {
975 current_alpha = animator.Animate(prefixed_panel_id,
"panel_alpha",
976 target_alpha, panel_fade_speed);
977 current_alpha *= global_alpha;
979 current_alpha = target_alpha;
983 if (current_alpha < 0.01f) {
992 std::string display_name = descriptor.
display_name.empty()
1008 const bool force_float =
1012 }
else if (touch_device) {
1025 if (preferred_width > 0.0f || preferred_height > 0.0f) {
1027 preferred_width > 0.0f ? preferred_width : 400.0f,
1028 preferred_height > 0.0f ? preferred_height : 300.0f);
1041 std::optional<gui::StyleVarGuard> alpha_guard;
1042 if (current_alpha < 1.0f) {
1043 alpha_guard.emplace(ImGuiStyleVar_Alpha, current_alpha);
1046 animator.ApplyPanelTransitionPre(prefixed_panel_id);
1047 if (window.
Begin(visibility_flag)) {
1051 animator.ApplyPanelTransitionPost(prefixed_panel_id);
1053 alpha_guard.reset();
1058 if (is_visible && visibility_flag && !*visibility_flag) {
1065 base_panel_id, descriptor.
category,
false);
1071 const std::string& to_category) {
1072 if (from_category == to_category) {
1076 LOG_INFO(
"WorkspaceWindowManager",
"Switching from category '%s' to '%s'",
1077 from_category.c_str(), to_category.c_str());
1099 const auto incoming =
1101 for (
const auto& descriptor : incoming) {
1102 if (descriptor.visibility_flag && *descriptor.visibility_flag) {
1118 size_t session_id,
const std::string& base_window_id) {
1120 if (descriptor ==
nullptr || !descriptor->IsAdmitted() ||
1121 !descriptor->presentation.allow_popout) {
1133 const std::string& base_card_id) {
1136 if (prefixed_id.empty()) {
1142 if (!descriptor->IsAdmitted()) {
1145 const bool was_visible =
1146 (descriptor->visibility_flag && *descriptor->visibility_flag);
1147 if (descriptor->visibility_flag) {
1148 *descriptor->visibility_flag =
true;
1150 if (descriptor->on_show) {
1151 descriptor->on_show();
1161 descriptor->category,
true);
1168 const std::string& base_card_id) {
1171 if (prefixed_id.empty()) {
1179 const bool was_visible =
1180 (descriptor->visibility_flag && *descriptor->visibility_flag);
1181 if (descriptor->visibility_flag) {
1182 *descriptor->visibility_flag =
false;
1184 if (descriptor->on_hide) {
1185 descriptor->on_hide();
1195 descriptor->category,
false);
1202 const std::string& base_card_id) {
1205 if (prefixed_id.empty()) {
1210 if (descriptor && descriptor->visibility_flag) {
1211 bool new_state = !(*descriptor->visibility_flag);
1212 *descriptor->visibility_flag = new_state;
1216 if (new_state && descriptor->on_show) {
1217 descriptor->on_show();
1218 }
else if (!new_state && descriptor->on_hide) {
1219 descriptor->on_hide();
1231 descriptor->category, new_state);
1238 size_t session_id,
const std::string& base_card_id)
const {
1241 if (prefixed_id.empty()) {
1246 if (descriptor && descriptor->visibility_flag) {
1247 return *descriptor->visibility_flag;
1253 size_t session_id,
const std::string& base_card_id) {
1256 if (prefixed_id.empty()) {
1262 return descriptor->visibility_flag;
1273 for (
const auto& prefixed_card_id : *session_windows) {
1275 if (!descriptor->IsListedInWindowBrowser()) {
1278 if (descriptor->visibility_flag) {
1279 *descriptor->visibility_flag =
true;
1281 if (descriptor->on_show) {
1282 descriptor->on_show();
1291 for (
const auto& prefixed_card_id : *session_windows) {
1293 if (descriptor->visibility_flag) {
1295 *descriptor->visibility_flag =
false;
1297 if (descriptor->on_hide) {
1298 descriptor->on_hide();
1306 size_t session_id,
const std::string& category) {
1308 for (
const auto& prefixed_card_id : *session_windows) {
1310 if (descriptor->category != category) {
1313 if (!descriptor->IsListedInWindowBrowser()) {
1316 if (descriptor->visibility_flag) {
1317 *descriptor->visibility_flag =
true;
1319 if (descriptor->on_show) {
1320 descriptor->on_show();
1328 size_t session_id,
const std::string& category) {
1330 for (
const auto& prefixed_card_id : *session_windows) {
1332 if (descriptor->category != category) {
1335 if (descriptor->visibility_flag) {
1337 *descriptor->visibility_flag =
false;
1339 if (descriptor->on_hide) {
1340 descriptor->on_hide();
1348 const std::string& base_card_id) {
1351 if (prefixed_id.empty()) {
1360 std::string category = target->category;
1374 size_t session_id)
const {
1375 std::vector<std::string> result;
1377 result.reserve(session_windows->size());
1378 for (
const auto& prefixed_window_id : *session_windows) {
1379 const std::string base_window_id =
1381 result.push_back(base_window_id.empty() ? prefixed_window_id
1389 size_t session_id,
const std::string& category)
const {
1390 std::vector<WindowDescriptor> result;
1393 for (
const auto& prefixed_window_id : *session_windows) {
1394 if (
const auto* descriptor =
1396 if (descriptor->category == category) {
1398 const std::string base_window_id =
1400 if (!base_window_id.empty()) {
1401 window.
card_id = base_window_id;
1403 result.push_back(std::move(window));
1410 std::sort(result.begin(), result.end(),
1412 return a.priority < b.priority;
1419 size_t session_id)
const {
1420 std::vector<std::string> categories;
1423 for (
const auto& prefixed_window_id : *session_windows) {
1424 if (
const auto* descriptor =
1426 if (std::find(categories.begin(), categories.end(),
1427 descriptor->category) == categories.end()) {
1428 categories.push_back(descriptor->category);
1437 size_t session_id,
const std::string& base_card_id)
const {
1440 if (prefixed_id.empty()) {
1448 std::vector<std::string> categories;
1450 if (std::find(categories.begin(), categories.end(), card_info.category) ==
1452 categories.push_back(card_info.category);
1463 size_t session_id)
const {
1464 std::vector<std::string> visible_panels;
1467 if (!window_mapping) {
1468 return visible_panels;
1471 for (
const auto& [base_id, prefixed_id] : *window_mapping) {
1473 if (descriptor->visibility_flag && *descriptor->visibility_flag) {
1474 visible_panels.push_back(base_id);
1479 return visible_panels;
1487 const std::string& description) {
1493 for (
const auto& [card_id, card_info] :
cards_) {
1494 if (card_info.visibility_flag && *card_info.visibility_flag) {
1501 LOG_INFO(
"WorkspaceWindowManager",
"Saved preset: %s (%zu cards)",
1512 for (
auto& [card_id, card_info] :
cards_) {
1513 if (card_info.visibility_flag) {
1515 *card_info.visibility_flag =
false;
1520 for (
const auto& card_id : it->second.visible_cards) {
1521 auto card_it =
cards_.find(card_id);
1522 if (card_it !=
cards_.end() && card_it->second.visibility_flag) {
1523 *card_it->second.visibility_flag =
true;
1524 if (card_it->second.on_show) {
1525 card_it->second.on_show();
1530 LOG_INFO(
"WorkspaceWindowManager",
"Loaded preset: %s", name.c_str());
1539std::vector<WorkspaceWindowManager::WorkspacePreset>
1541 std::vector<WorkspacePreset> result;
1542 for (
const auto& [name, preset] :
presets_) {
1543 result.push_back(preset);
1565 LOG_INFO(
"WorkspaceWindowManager",
"Reset to defaults for session %zu",
1573 if (category.empty()) {
1575 "No category found for editor type %d, skipping reset",
1576 static_cast<int>(editor_type));
1589 for (
const auto& card_id : default_panels) {
1591 LOG_DEBUG(
"WorkspaceWindowManager",
"Showing default card: %s",
1597 "Reset %s editor to defaults (%zu cards visible)", category.c_str(),
1598 default_panels.size());
1606 size_t session_id,
const std::string& base_id)
const {
1611 const std::string& base_id,
1615 return canonical_base_id;
1618 return absl::StrFormat(
"s%zu.%s", session_id, canonical_base_id);
1620 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 bool PrefersFloating() const
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)
std::unordered_set< std::string > & pending_float_window_ids_
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< WindowDescriptor > GetWindowsInCategory(size_t session_id, const std::string &category) const
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)
bool OpenWindowFloating(size_t session_id, const std::string &base_window_id)
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)
bool CloseWindow(size_t session_id, const std::string &base_window_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)
Update the active category and start panel transitions.
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 RequestForceUndock()
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_DEBUG(category, format,...)
#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, const WindowPresentationPolicy &presentation)
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
WindowPresentationPolicy presentation
std::string workflow_label
std::function< bool()> enabled_condition
WindowLifecycle window_lifecycle
static WindowPresentationPolicy OptionalPopOut()
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