yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
workspace_manager.cc
Go to the documentation of this file.
1#define IMGUI_DEFINE_MATH_OPERATORS
2
4
5#include "absl/strings/str_format.h"
10#include "imgui/imgui.h"
11#include "imgui/imgui_internal.h"
12#include "rom/rom.h"
13#include "util/file_util.h"
14#include "util/log.h"
15#include "util/platform_paths.h"
16
17namespace yaze {
18namespace editor {
19
20absl::Status WorkspaceManager::SaveWorkspaceLayout(const std::string& name) {
21 if (layout_manager_) {
22 const std::string layout_name = name.empty() ? "workspace" : name;
24 }
25 if (toast_manager_) {
26 toast_manager_->Show("Layout saved", ToastType::kSuccess);
27 }
28 return absl::OkStatus();
29}
30
31absl::Status WorkspaceManager::LoadWorkspaceLayout(const std::string& name) {
32 bool loaded = false;
33 if (layout_manager_) {
34 const std::string layout_name = name.empty() ? "workspace" : name;
35 if (layout_manager_->HasLayout(layout_name)) {
36 layout_manager_->LoadLayout(layout_name);
37 loaded = true;
38 } else if (toast_manager_) {
39 toast_manager_->Show("Layout not found", ToastType::kWarning);
40 }
41 }
42 if (toast_manager_ && loaded) {
43 toast_manager_->Show("Layout loaded", ToastType::kSuccess);
44 }
45 return absl::OkStatus();
46}
47
49 if (ImGui::GetCurrentContext()) {
50 static const char kEmptyIni[] = "\n";
51 ImGui::LoadIniSettingsFromMemory(kEmptyIni, sizeof(kEmptyIni) - 1);
52 }
53
54 if (auto ini_path = util::PlatformPaths::GetImGuiIniPath(); ini_path.ok()) {
55 std::error_code ec;
56 std::filesystem::remove(*ini_path, ec);
57 if (ec) {
58 LOG_WARN("WorkspaceManager", "Failed to remove ImGui ini: %s",
59 ec.message().c_str());
60 }
61 }
62
63 if (layout_manager_) {
65
67 if (panel_manager_) {
68 editor_type =
71 }
74 }
75 if (toast_manager_) {
76 toast_manager_->Show("Layout reset to default", ToastType::kInfo);
77 }
78 return absl::OkStatus();
79}
80
81void WorkspaceManager::SaveWorkspacePreset(const std::string& name) {
82 if (name.empty())
83 return;
84
85 std::filesystem::path workspace_dir = std::filesystem::current_path();
86 auto workspace_dir_status =
88 if (workspace_dir_status.ok()) {
89 workspace_dir = *workspace_dir_status;
90 }
91
92 if (layout_manager_) {
94 } else {
95 std::filesystem::path ini_path =
96 workspace_dir / absl::StrFormat("workspace_%s.ini", name.c_str());
97 ImGui::SaveIniSettingsToDisk(ini_path.string().c_str());
98 }
99
101 // RefreshWorkspacePresets(); // This will be implemented next
102 }
103
104 if (std::find(workspace_presets_.begin(), workspace_presets_.end(), name) ==
105 workspace_presets_.end()) {
106 workspace_presets_.emplace_back(name);
107 try {
108 std::ostringstream ss;
109 for (const auto& n : workspace_presets_)
110 ss << n << "\n";
111 std::filesystem::path presets_path =
112 workspace_dir / "workspace_presets.txt";
113 util::SaveFile(presets_path.string(), ss.str());
114 } catch (const std::exception& e) {
115 // LOG_WARN("WorkspaceManager", "Failed to save presets: %s", e.what());
116 }
117 }
119 if (toast_manager_) {
120 toast_manager_->Show(absl::StrFormat("Preset '%s' saved", name),
122 }
123}
124
125void WorkspaceManager::LoadWorkspacePreset(const std::string& name) {
126 if (name.empty())
127 return;
128
129 if (layout_manager_) {
130 if (layout_manager_->HasLayout(name)) {
133 if (toast_manager_) {
134 toast_manager_->Show(absl::StrFormat("Preset '%s' loaded", name),
136 }
137 return;
138 }
139 }
140 std::filesystem::path workspace_dir = std::filesystem::current_path();
141 auto workspace_dir_status =
143 if (workspace_dir_status.ok()) {
144 workspace_dir = *workspace_dir_status;
145 }
146 std::filesystem::path ini_path =
147 workspace_dir / absl::StrFormat("workspace_%s.ini", name.c_str());
148 ImGui::LoadIniSettingsFromDisk(ini_path.string().c_str());
150 if (toast_manager_) {
151 toast_manager_->Show(absl::StrFormat("Preset '%s' loaded", name),
153 }
154}
155
157 try {
158 std::vector<std::string> new_presets;
159 auto workspace_dir = util::PlatformPaths::GetAppDataSubdirectory("workspaces");
160 if (workspace_dir.ok()) {
161 std::filesystem::path presets_path =
162 *workspace_dir / "workspace_presets.txt";
163 auto data = util::LoadFile(presets_path.string());
164 if (!data.empty()) {
165 std::istringstream ss(data);
166 std::string name;
167 while (std::getline(ss, name)) {
168 name.erase(0, name.find_first_not_of(" \t\r\n"));
169 name.erase(name.find_last_not_of(" \t\r\n") + 1);
170 if (!name.empty() && name.length() < 256) {
171 new_presets.emplace_back(std::move(name));
172 }
173 }
174 }
175 }
176 workspace_presets_ = std::move(new_presets);
178 } catch (const std::exception& e) {
179 // LOG_ERROR("WorkspaceManager", "Error refreshing presets: %s", e.what());
180 workspace_presets_.clear();
182 }
183}
184
187 apply_preset_callback_("Developer");
188 } else if (toast_manager_) {
189 toast_manager_->Show("Layout presets not available", ToastType::kWarning);
190 }
191}
192
195 apply_preset_callback_("Designer");
196 } else if (toast_manager_) {
197 toast_manager_->Show("Layout presets not available", ToastType::kWarning);
198 }
199}
200
203 apply_preset_callback_("Modder");
204 } else if (toast_manager_) {
205 toast_manager_->Show("Layout presets not available", ToastType::kWarning);
206 }
207}
208
210 if (panel_manager_) {
212 }
213 if (toast_manager_) {
214 toast_manager_->Show("All windows shown", ToastType::kInfo);
215 }
216}
217
219 if (panel_manager_) {
221 }
222 if (toast_manager_) {
223 toast_manager_->Show("All windows hidden", ToastType::kInfo);
224 }
225}
226
228 // Use ImGui internal API to maximize current window
229 ImGuiWindow* window = ImGui::GetCurrentWindowRead();
230 if (window && window->DockNode) {
231 ImGuiID central_node_id =
232 ImGui::DockBuilderGetCentralNode(ImGui::GetID("MainDockSpace"))->ID;
233 ImGui::DockBuilderDockWindow(window->Name, central_node_id);
234 }
235 if (toast_manager_) {
236 toast_manager_->Show("Window maximized", ToastType::kInfo);
237 }
238}
239
241 // Reset all window sizes - ImGui will auto-restore based on docking
242 ImGuiContext* ctx = ImGui::GetCurrentContext();
243 if (ctx) {
244 for (ImGuiWindow* window : ctx->Windows) {
245 if (window && !window->Collapsed) {
246 ImGui::SetWindowSize(window->Name, ImVec2(0, 0)); // Auto-size
247 }
248 }
249 }
250 if (toast_manager_) {
251 toast_manager_->Show("All windows restored", ToastType::kInfo);
252 }
253}
254
256 // Close all windows that are not docked
257 ImGuiContext* ctx = ImGui::GetCurrentContext();
258 if (ctx) {
259 for (ImGuiWindow* window : ctx->Windows) {
260 if (window && !window->DockNode && !window->Collapsed) {
261 window->Hidden = true;
262 }
263 }
264 }
265 if (toast_manager_) {
266 toast_manager_->Show("Floating windows closed", ToastType::kInfo);
267 }
268}
269
271 if (!sessions_)
272 return 0;
273
274 size_t count = 0;
275 for (const auto& session : *sessions_) {
276 if (session.rom && session.rom->is_loaded()) {
277 count++;
278 }
279 }
280 return count;
281}
282
283bool WorkspaceManager::HasDuplicateSession(const std::string& filepath) const {
284 if (!sessions_)
285 return false;
286
287 for (const auto& session : *sessions_) {
288 if (session.filepath == filepath && session.rom &&
289 session.rom->is_loaded()) {
290 return true;
291 }
292 }
293 return false;
294}
295
296// Window navigation operations
298 ImGuiContext* ctx = ImGui::GetCurrentContext();
299 if (ctx && ctx->NavWindow) {
300 ImGui::FocusWindow(ImGui::FindWindowByName(ctx->NavWindow->Name));
301 }
302 // TODO: Implement proper window cycling
303}
304
306 // TODO: Implement window cycling backward
307}
308
310 ImGuiWindow* window = ImGui::GetCurrentWindowRead();
311 if (window && window->DockNode) {
312 ImGuiID node_id = window->DockNode->ID;
313 ImGuiID out_id_at_dir = 0;
314 ImGuiID out_id_at_opposite_dir = 0;
315 ImGui::DockBuilderSplitNode(node_id, ImGuiDir_Down, 0.5f, &out_id_at_dir,
316 &out_id_at_opposite_dir);
317 }
318}
319
321 ImGuiWindow* window = ImGui::GetCurrentWindowRead();
322 if (window && window->DockNode) {
323 ImGuiID node_id = window->DockNode->ID;
324 ImGuiID out_id_at_dir = 0;
325 ImGuiID out_id_at_opposite_dir = 0;
326 ImGui::DockBuilderSplitNode(node_id, ImGuiDir_Right, 0.5f, &out_id_at_dir,
327 &out_id_at_opposite_dir);
328 }
329}
330
332 ImGuiWindow* window = ImGui::GetCurrentWindowRead();
333 if (window) {
334 window->Hidden = true;
335 }
336}
337
338// Command execution for WhichKey integration
339void WorkspaceManager::ExecuteWorkspaceCommand(const std::string& command_id) {
340 // Window commands (Space + w)
341 if (command_id == "w.s") {
343 } else if (command_id == "w.h") {
345 } else if (command_id == "w.m") {
347 } else if (command_id == "w.r") {
349 } else if (command_id == "w.c") {
351 } else if (command_id == "w.f") {
353 } else if (command_id == "w.v") {
355 } else if (command_id == "w.H") {
357 }
358
359 // Layout commands (Space + l)
360 else if (command_id == "l.s") {
362 } else if (command_id == "l.l") {
364 } else if (command_id == "l.r") {
366 } else if (command_id == "l.d") {
368 } else if (command_id == "l.g") {
370 } else if (command_id == "l.m") {
372 }
373
374 // Unknown command
375 else if (toast_manager_) {
376 toast_manager_->Show(absl::StrFormat("Unknown command: %s", command_id),
378 }
379}
380
381} // namespace editor
382} // namespace yaze
static EditorType GetEditorTypeFromCategory(const std::string &category)
void LoadLayout(const std::string &name)
Load a saved layout by name.
void ClearInitializationFlags()
Clear all initialization flags (for testing)
void ResetToDefaultLayout(EditorType type)
Reset the layout for an editor to its default.
void SaveCurrentLayout(const std::string &name, bool persist=true)
Save the current layout with a custom name.
void RequestRebuild()
Request a layout rebuild on next frame.
bool HasLayout(const std::string &name) const
Check if a layout exists.
void HideAll(size_t session_id)
std::string GetActiveCategory() const
void ShowAll(size_t session_id)
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
void SaveWorkspacePreset(const std::string &name)
bool HasDuplicateSession(const std::string &filepath) const
std::function< void(const std::string &) apply_preset_callback_)
std::vector< std::string > workspace_presets_
std::deque< SessionInfo > * sessions_
void LoadWorkspacePreset(const std::string &name)
absl::Status SaveWorkspaceLayout(const std::string &name="")
absl::Status LoadWorkspaceLayout(const std::string &name="")
void ExecuteWorkspaceCommand(const std::string &command_id)
static absl::StatusOr< std::filesystem::path > GetImGuiIniPath()
Get the ImGui ini path for YAZE.
static absl::StatusOr< std::filesystem::path > GetAppDataSubdirectory(const std::string &subdir)
Get a subdirectory within the app data folder.
#define LOG_WARN(category, format,...)
Definition log.h:107
void SaveFile(const std::string &filename, const std::string &contents)
Definition file_util.cc:56
std::string LoadFile(const std::string &filename)
Loads the entire contents of a file into a string.
Definition file_util.cc:23