Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
TabManager.h
Go to the documentation of this file.
1/**
2 * @file TabManager.h
3 * @brief Central manager for the multi-graph tab system.
4 * @author Olympe Engine
5 * @date 2026-03-11
6 *
7 * @details
8 * TabManager maintains a list of EditorTab objects, each holding a pointer to
9 * an IGraphRenderer. It renders an ImGui tab bar and delegates canvas drawing
10 * to the active tab's renderer.
11 *
12 * Usage (inside BlueprintEditorGUI):
13 * @code
14 * TabManager::Get().RenderTabBar();
15 * TabManager::Get().RenderActiveCanvas();
16 * @endcode
17 *
18 * C++14 compliant — no std::optional, structured bindings, std::filesystem.
19 */
20
21#pragma once
22
23#include "IGraphRenderer.h"
24
25#include <string>
26#include <vector>
27
28namespace Olympe {
29
30// ============================================================================
31// EditorTab
32// ============================================================================
33
34/**
35 * @struct EditorTab
36 * @brief Represents a single open graph in the editor.
37 */
39{
40 std::string tabID; ///< Unique identifier (stringified int counter)
41 std::string displayName; ///< Label shown in the tab bar
42 std::string filePath; ///< Full path, empty for unsaved graphs
43 std::string graphType; ///< "VisualScript", "BehaviorTree", etc.
44 bool isDirty; ///< True when there are unsaved changes
45 bool isActive; ///< True when this is the currently selected tab
46
47 IGraphRenderer* renderer; ///< Owned pointer — deleted when tab is closed
48
54};
55
56// ============================================================================
57// TabManager
58// ============================================================================
59
60/**
61 * @class TabManager
62 * @brief Singleton that owns and manages all open graph editor tabs.
63 */
65{
66public:
68
69 /** @brief Returns the global singleton instance. */
70 static TabManager& Get();
71
72 // ------------------------------------------------------------------
73 // Tab creation / opening
74 // ------------------------------------------------------------------
75
76 /**
77 * @brief Creates a new empty tab of the given graph type.
78 * @param graphType "VisualScript" or "BehaviorTree".
79 * @return The new tab's tabID, or empty string on failure.
80 */
81 std::string CreateNewTab(const std::string& graphType);
82
83 /**
84 * @brief Opens a file in a new tab.
85 * If the file is already open, activates that tab instead.
86 * @param filePath Full path to the .ats / .json file.
87 * @return The tab's tabID, or empty string on failure.
88 */
89 std::string OpenFileInTab(const std::string& filePath);
90
91 // ------------------------------------------------------------------
92 // Navigation
93 // ------------------------------------------------------------------
94
95 void SetActiveTab(const std::string& tabID);
96 std::string GetActiveTabID() const;
98 EditorTab* GetTab(const std::string& tabID);
99
100 const std::vector<EditorTab>& GetAllTabs() const { return m_tabs; }
101
102 // ------------------------------------------------------------------
103 // Closing
104 // ------------------------------------------------------------------
105
106 /**
107 * @brief Closes the given tab.
108 * Shows an "unsaved changes" dialog when the tab is dirty.
109 * @return false if the user chose Cancel.
110 */
111 bool CloseTab(const std::string& tabID);
112
113 /**
114 * @brief Attempts to close all tabs.
115 * @return false if the user cancelled at any point.
116 */
117 bool CloseAllTabs();
118
119 // ------------------------------------------------------------------
120 // Saving
121 // ------------------------------------------------------------------
122
123 /** @brief Saves the active tab. Opens "Save As" if no path is set. */
124 bool SaveActiveTab();
125
126 /**
127 * @brief Saves the active tab to a specific path.
128 * @return true on success.
129 */
130 bool SaveActiveTabAs(const std::string& path);
131
132 // ------------------------------------------------------------------
133 // Rendering
134 // ------------------------------------------------------------------
135
136 /** @brief Renders the horizontal tab bar (call before RenderActiveCanvas). */
137 void RenderTabBar();
138
139 /** @brief Renders the graph canvas of the active tab. */
140 void RenderActiveCanvas();
141
142 // ------------------------------------------------------------------
143 // Query helpers
144 // ------------------------------------------------------------------
145
146 /** @brief Returns true when at least one tab has unsaved changes. */
147 bool HasDirtyTabs() const;
148
149 /** @brief Returns true when there are no open tabs. */
150 bool IsEmpty() const { return m_tabs.empty(); }
151
152private:
153 TabManager();
154
155 // Disable copy
158
159 /**
160 * @brief Shows a 3-button "Save / Don't Save / Cancel" modal dialog.
161 * @param tab Tab whose unsaved state is being queried.
162 * @return 1 = Save, 0 = Don't Save, -1 = Cancel.
163 */
164 int ShowUnsavedDialog(const EditorTab& tab);
165
166 /** @brief Shows the "Save As" input dialog for a tab without a path. */
168
169 /**
170 * @brief Detects the graph type by inspecting the JSON contents.
171 * @return "VisualScript", "BehaviorTree", or "Unknown".
172 */
173 static std::string DetectGraphType(const std::string& filePath);
174
175 /** @brief Generates the next unique tabID. */
176 std::string NextTabID();
177
178 /** @brief Derives a display name from a file path (filename without dir). */
179 static std::string DisplayNameFromPath(const std::string& filePath);
180
181 /** @brief Deletes a renderer and removes its tab entry. */
182 void DestroyTab(size_t index);
183
184 // ------------------------------------------------------------------
185 // State
186 // ------------------------------------------------------------------
187
188 std::vector<EditorTab> m_tabs;
189 std::string m_activeTabID;
190 int m_nextTabNum; ///< Counter for "Untitled-N" names
191 int m_nextTabIDNum; ///< Counter for unique tab IDs
192
193 // One-shot programmatic tab selection request.
194 // Set by SetActiveTab(); applied as ImGuiTabItemFlags_SetSelected for ONE frame,
195 // then cleared so that user-initiated tab clicks are not overridden.
197
198 // Pending close state (for deferred close when dialog is shown)
200
201 // Save As dialog state
203 char m_saveAsBuffer[512];
204 std::string m_saveAsTabID;
205};
206
207} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Abstract interface shared by all graph-renderer adapters.
Polymorphic interface for all graph editor renderers.
Singleton that owns and manages all open graph editor tabs.
Definition TabManager.h:65
int m_nextTabNum
Counter for "Untitled-N" names.
Definition TabManager.h:190
bool SaveActiveTabAs(const std::string &path)
Saves the active tab to a specific path.
bool HasDirtyTabs() const
Returns true when at least one tab has unsaved changes.
int ShowUnsavedDialog(const EditorTab &tab)
Shows a 3-button "Save / Don't Save / Cancel" modal dialog.
static TabManager & Get()
Returns the global singleton instance.
EditorTab * GetActiveTab()
EditorTab * GetTab(const std::string &tabID)
std::string m_saveAsTabID
Definition TabManager.h:204
std::string GetActiveTabID() const
std::string CreateNewTab(const std::string &graphType)
Creates a new empty tab of the given graph type.
std::string NextTabID()
Generates the next unique tabID.
bool CloseAllTabs()
Attempts to close all tabs.
bool SaveActiveTab()
Saves the active tab.
bool IsEmpty() const
Returns true when there are no open tabs.
Definition TabManager.h:150
bool ShowSaveAsDialog(EditorTab *tab)
Shows the "Save As" input dialog for a tab without a path.
bool CloseTab(const std::string &tabID)
Closes the given tab.
const std::vector< EditorTab > & GetAllTabs() const
Definition TabManager.h:100
static std::string DisplayNameFromPath(const std::string &filePath)
Derives a display name from a file path (filename without dir).
int m_nextTabIDNum
Counter for unique tab IDs.
Definition TabManager.h:191
static std::string DetectGraphType(const std::string &filePath)
Detects the graph type by inspecting the JSON contents.
void RenderTabBar()
Renders the horizontal tab bar (call before RenderActiveCanvas).
std::vector< EditorTab > m_tabs
Definition TabManager.h:188
TabManager & operator=(const TabManager &)
std::string m_pendingSelectTabID
Definition TabManager.h:196
TabManager(const TabManager &)
void RenderActiveCanvas()
Renders the graph canvas of the active tab.
char m_saveAsBuffer[512]
Definition TabManager.h:203
void DestroyTab(size_t index)
Deletes a renderer and removes its tab entry.
std::string m_pendingCloseTabID
Definition TabManager.h:199
void SetActiveTab(const std::string &tabID)
std::string OpenFileInTab(const std::string &filePath)
Opens a file in a new tab.
std::string m_activeTabID
Definition TabManager.h:189
< Provides AssetID and INVALID_ASSET_ID
Represents a single open graph in the editor.
Definition TabManager.h:39
bool isDirty
True when there are unsaved changes.
Definition TabManager.h:44
std::string graphType
"VisualScript", "BehaviorTree", etc.
Definition TabManager.h:43
IGraphRenderer * renderer
Owned pointer — deleted when tab is closed.
Definition TabManager.h:47
std::string filePath
Full path, empty for unsaved graphs.
Definition TabManager.h:42
std::string displayName
Label shown in the tab bar.
Definition TabManager.h:41
std::string tabID
Unique identifier (stringified int counter)
Definition TabManager.h:40
bool isActive
True when this is the currently selected tab.
Definition TabManager.h:45