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_INFO(
"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);
528 LOG_INFO(
"WorkspaceWindowManager",
"Unregistered card with prefix '%s': %s",
529 prefix.c_str(), info.prefixed_id.c_str());
534 card_list.erase(std::remove_if(card_list.begin(), card_list.end(),
535 [&prefix](
const std::string&
id) {
536 return id.find(prefix) == 0;
556 LOG_INFO(
"WorkspaceWindowManager",
"Cleared all cards");
564 std::unique_ptr<WindowContent> panel) {
567 "Attempted to register null WindowContent");
572 if (resource_panel) {
576 std::string panel_id = panel->GetId();
581 "WindowContent '%s' already registered, skipping registry add",
596 LOG_INFO(
"WorkspaceWindowManager",
"Registered registry WindowContent: %s",
613 std::unique_ptr<WindowContent> panel) {
615 panel ? panel->GetPresentationPolicy()
621 std::unique_ptr<WindowContent> panel,
625 "Attempted to register null WindowContent");
630 if (resource_panel) {
637 WindowDescriptor descriptor = BuildDescriptorFromPanel(*panel, presentation);
640 bool visible_by_default = panel->IsVisibleByDefault();
648 std::string instance_id;
649 bool descriptor_preexisting =
false;
651 if (
const auto* session_mapping =
653 if (
auto mapping_it = session_mapping->find(panel_id);
654 mapping_it != session_mapping->end() &&
655 cards_.contains(mapping_it->second)) {
656 instance_id = mapping_it->second;
657 descriptor_preexisting =
true;
661 descriptor_preexisting =
cards_.contains(panel_id);
663 if (instance_id.empty()) {
668 if (instance_id.empty()) {
675 if (descriptor_preexisting && presentation.
declared) {
676 if (
auto descriptor_it =
cards_.find(instance_id);
677 descriptor_it !=
cards_.end() &&
678 !descriptor_it->second.presentation.declared) {
679 descriptor_it->second.presentation = presentation;
687 if (!descriptor_preexisting) {
688 if (
auto descriptor_it =
cards_.find(instance_id);
689 descriptor_it !=
cards_.end()) {
690 descriptor_it->second.enabled_condition = [
this, instance_id]() {
693 instance_it->second->IsEnabled();
703 existing->second->OnClose();
706 existing->second = std::move(panel);
708 if (visible_by_default) {
711 LOG_INFO(
"WorkspaceWindowManager",
"Replaced WindowContent: %s",
712 instance_id.c_str());
717 if (visible_by_default) {
726 LOG_INFO(
"WorkspaceWindowManager",
"Registered WindowContent: %s (%s)",
735 const std::string& resource_type) {
740 auto& panel_list = it->second;
744 while (panel_list.size() >= limit) {
746 if (panel_to_evict.empty()) {
751 panel_list.remove(panel_to_evict);
762 std::string type = type_it->second;
767 list.remove(panel_id);
768 list.push_back(panel_id);
772 const std::string& panel_id) {
774 std::string base_panel_id;
775 std::string instance_id;
782 for (
const auto& [session_id, reverse_mapping] :
784 if (
auto reverse_it = reverse_mapping.find(panel_id);
785 reverse_it != reverse_mapping.end()) {
786 owner_session = session_id;
787 base_panel_id = reverse_it->second;
788 instance_id = panel_id;
794 if (instance_id.empty()) {
796 if (
const auto* active_mapping =
798 if (
auto mapping_it = active_mapping->find(requested_base_id);
799 mapping_it != active_mapping->end()) {
800 base_panel_id = requested_base_id;
801 instance_id = mapping_it->second;
808 if (instance_id.empty()) {
809 for (
const auto& [session_id, reverse_mapping] :
811 if (
auto reverse_it = reverse_mapping.find(panel_id);
812 reverse_it != reverse_mapping.end()) {
813 owner_session = session_id;
814 base_panel_id = reverse_it->second;
815 instance_id = panel_id;
820 if (instance_id.empty()) {
824 if (instance_id.empty()) {
825 instance_id = panel_id;
832 it->second->OnClose();
837 LOG_INFO(
"WorkspaceWindowManager",
"Unregistered WindowContent: %s",
838 instance_id.c_str());
846 const std::string& panel_id) {
851 size_t session_id,
const std::string& panel_id) {
853 if (!session_mapping) {
858 if (base_panel_id.empty()) {
861 auto mapping_it = session_mapping->find(base_panel_id);
862 if (mapping_it == session_mapping->end()) {
869 const std::string& prefixed_panel_id,
const std::string& base_panel_id) {
872 return prefixed_it->second.get();
876 return base_it->second.get();
882 const std::string& prefixed_panel_id,
883 const std::string& base_panel_id)
const {
886 return prefixed_it->second.get();
890 return base_it->second.get();
909 bool animations_enabled = animator.IsEnabled();
912 const auto resolve_switch_speed = [&](
float snappy,
float standard,
914 switch (animator.motion_profile()) {
924 const float category_transition_speed =
925 resolve_switch_speed(8.5f, 6.0f, 4.5f);
926 const float panel_fade_speed = resolve_switch_speed(11.0f, 8.0f, 6.0f);
929 float global_alpha = 1.0f;
930 if (animations_enabled) {
931 global_alpha = animator.Animate(
"global",
"category_transition", 1.0f,
932 category_transition_speed);
935 for (
const auto& prefixed_panel_id : session_it->second) {
936 auto descriptor_it =
cards_.find(prefixed_panel_id);
937 if (descriptor_it ==
cards_.end()) {
942 std::string base_panel_id =
944 if (base_panel_id.empty()) {
945 base_panel_id = prefixed_panel_id;
958 bool should_draw =
false;
969 float target_alpha = should_draw ? 1.0f : 0.0f;
972 float current_alpha = 1.0f;
973 if (animations_enabled) {
974 current_alpha = animator.Animate(prefixed_panel_id,
"panel_alpha",
975 target_alpha, panel_fade_speed);
976 current_alpha *= global_alpha;
978 current_alpha = target_alpha;
982 if (current_alpha < 0.01f) {
991 std::string display_name = descriptor.
display_name.empty()
1007 const bool force_float =
1011 }
else if (touch_device) {
1024 if (preferred_width > 0.0f || preferred_height > 0.0f) {
1026 preferred_width > 0.0f ? preferred_width : 400.0f,
1027 preferred_height > 0.0f ? preferred_height : 300.0f);
1040 std::optional<gui::StyleVarGuard> alpha_guard;
1041 if (current_alpha < 1.0f) {
1042 alpha_guard.emplace(ImGuiStyleVar_Alpha, current_alpha);
1045 animator.ApplyPanelTransitionPre(prefixed_panel_id);
1046 if (window.
Begin(visibility_flag)) {
1050 animator.ApplyPanelTransitionPost(prefixed_panel_id);
1052 alpha_guard.reset();
1055 if (visibility_flag && !*visibility_flag) {
1062 const std::string& to_category) {
1063 if (from_category == to_category) {
1067 LOG_INFO(
"WorkspaceWindowManager",
"Switching from category '%s' to '%s'",
1068 from_category.c_str(), to_category.c_str());
1090 const auto incoming =
1092 for (
const auto& descriptor : incoming) {
1093 if (descriptor.visibility_flag && *descriptor.visibility_flag) {
1109 size_t session_id,
const std::string& base_window_id) {
1111 if (descriptor ==
nullptr || !descriptor->IsAdmitted() ||
1112 !descriptor->presentation.allow_popout) {
1124 const std::string& base_card_id) {
1127 if (prefixed_id.empty()) {
1133 if (!descriptor->IsAdmitted()) {
1136 const bool was_visible =
1137 (descriptor->visibility_flag && *descriptor->visibility_flag);
1138 if (descriptor->visibility_flag) {
1139 *descriptor->visibility_flag =
true;
1141 if (descriptor->on_show) {
1142 descriptor->on_show();
1152 descriptor->category,
true);
1159 const std::string& base_card_id) {
1162 if (prefixed_id.empty()) {
1170 const bool was_visible =
1171 (descriptor->visibility_flag && *descriptor->visibility_flag);
1172 if (descriptor->visibility_flag) {
1173 *descriptor->visibility_flag =
false;
1175 if (descriptor->on_hide) {
1176 descriptor->on_hide();
1186 descriptor->category,
false);
1193 const std::string& base_card_id) {
1196 if (prefixed_id.empty()) {
1201 if (descriptor && descriptor->visibility_flag) {
1202 bool new_state = !(*descriptor->visibility_flag);
1203 *descriptor->visibility_flag = new_state;
1207 if (new_state && descriptor->on_show) {
1208 descriptor->on_show();
1209 }
else if (!new_state && descriptor->on_hide) {
1210 descriptor->on_hide();
1222 descriptor->category, new_state);
1229 size_t session_id,
const std::string& base_card_id)
const {
1232 if (prefixed_id.empty()) {
1237 if (descriptor && descriptor->visibility_flag) {
1238 return *descriptor->visibility_flag;
1244 size_t session_id,
const std::string& base_card_id) {
1247 if (prefixed_id.empty()) {
1253 return descriptor->visibility_flag;
1264 for (
const auto& prefixed_card_id : *session_windows) {
1266 if (!descriptor->IsListedInWindowBrowser()) {
1269 if (descriptor->visibility_flag) {
1270 *descriptor->visibility_flag =
true;
1272 if (descriptor->on_show) {
1273 descriptor->on_show();
1282 for (
const auto& prefixed_card_id : *session_windows) {
1284 if (descriptor->visibility_flag) {
1286 *descriptor->visibility_flag =
false;
1288 if (descriptor->on_hide) {
1289 descriptor->on_hide();
1297 size_t session_id,
const std::string& category) {
1299 for (
const auto& prefixed_card_id : *session_windows) {
1301 if (descriptor->category != category) {
1304 if (!descriptor->IsListedInWindowBrowser()) {
1307 if (descriptor->visibility_flag) {
1308 *descriptor->visibility_flag =
true;
1310 if (descriptor->on_show) {
1311 descriptor->on_show();
1319 size_t session_id,
const std::string& category) {
1321 for (
const auto& prefixed_card_id : *session_windows) {
1323 if (descriptor->category != category) {
1326 if (descriptor->visibility_flag) {
1328 *descriptor->visibility_flag =
false;
1330 if (descriptor->on_hide) {
1331 descriptor->on_hide();
1339 const std::string& base_card_id) {
1342 if (prefixed_id.empty()) {
1351 std::string category = target->category;
1365 size_t session_id)
const {
1366 std::vector<std::string> result;
1368 result.reserve(session_windows->size());
1369 for (
const auto& prefixed_window_id : *session_windows) {
1370 const std::string base_window_id =
1372 result.push_back(base_window_id.empty() ? prefixed_window_id
1380 size_t session_id,
const std::string& category)
const {
1381 std::vector<WindowDescriptor> result;
1384 for (
const auto& prefixed_window_id : *session_windows) {
1385 if (
const auto* descriptor =
1387 if (descriptor->category == category) {
1389 const std::string base_window_id =
1391 if (!base_window_id.empty()) {
1392 window.
card_id = base_window_id;
1394 result.push_back(std::move(window));
1401 std::sort(result.begin(), result.end(),
1403 return a.priority < b.priority;
1410 size_t session_id)
const {
1411 std::vector<std::string> categories;
1414 for (
const auto& prefixed_window_id : *session_windows) {
1415 if (
const auto* descriptor =
1417 if (std::find(categories.begin(), categories.end(),
1418 descriptor->category) == categories.end()) {
1419 categories.push_back(descriptor->category);
1428 size_t session_id,
const std::string& base_card_id)
const {
1431 if (prefixed_id.empty()) {
1439 std::vector<std::string> categories;
1441 if (std::find(categories.begin(), categories.end(), card_info.category) ==
1443 categories.push_back(card_info.category);
1454 size_t session_id)
const {
1455 std::vector<std::string> visible_panels;
1458 if (!window_mapping) {
1459 return visible_panels;
1462 for (
const auto& [base_id, prefixed_id] : *window_mapping) {
1464 if (descriptor->visibility_flag && *descriptor->visibility_flag) {
1465 visible_panels.push_back(base_id);
1470 return visible_panels;
1478 const std::string& description) {
1484 for (
const auto& [card_id, card_info] :
cards_) {
1485 if (card_info.visibility_flag && *card_info.visibility_flag) {
1492 LOG_INFO(
"WorkspaceWindowManager",
"Saved preset: %s (%zu cards)",
1503 for (
auto& [card_id, card_info] :
cards_) {
1504 if (card_info.visibility_flag) {
1506 *card_info.visibility_flag =
false;
1511 for (
const auto& card_id : it->second.visible_cards) {
1512 auto card_it =
cards_.find(card_id);
1513 if (card_it !=
cards_.end() && card_it->second.visibility_flag) {
1514 *card_it->second.visibility_flag =
true;
1515 if (card_it->second.on_show) {
1516 card_it->second.on_show();
1521 LOG_INFO(
"WorkspaceWindowManager",
"Loaded preset: %s", name.c_str());
1530std::vector<WorkspaceWindowManager::WorkspacePreset>
1532 std::vector<WorkspacePreset> result;
1533 for (
const auto& [name, preset] :
presets_) {
1534 result.push_back(preset);
1556 LOG_INFO(
"WorkspaceWindowManager",
"Reset to defaults for session %zu",
1564 if (category.empty()) {
1566 "No category found for editor type %d, skipping reset",
1567 static_cast<int>(editor_type));
1580 for (
const auto& card_id : default_panels) {
1582 LOG_INFO(
"WorkspaceWindowManager",
"Showing default card: %s",
1588 "Reset %s editor to defaults (%zu cards visible)", category.c_str(),
1589 default_panels.size());
1597 size_t session_id,
const std::string& base_id)
const {
1602 const std::string& base_id,
1606 return canonical_base_id;
1609 return absl::StrFormat(
"s%zu.%s", session_id, canonical_base_id);
1611 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)
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 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_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