yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
menu_orchestrator.cc
Go to the documentation of this file.
1#include "menu_orchestrator.h"
2
3#include <algorithm>
4#include <fstream>
5#include <map>
6
7#include "absl/status/status.h"
8#include "absl/strings/str_format.h"
10#include "app/editor/editor.h"
21#include "app/gui/core/icons.h"
23#include "core/features.h"
24#include "rom/rom.h"
25#include "util/bps.h"
26#include "util/file_util.h"
28
29// Platform-aware shortcut macros for menu display
30#define SHORTCUT_CTRL(key) gui::FormatCtrlShortcut(ImGuiKey_##key).c_str()
31#define SHORTCUT_CTRL_SHIFT(key) \
32 gui::FormatCtrlShiftShortcut(ImGuiKey_##key).c_str()
33
34namespace yaze {
35namespace editor {
36
38 EditorManager* editor_manager, MenuBuilder& menu_builder,
39 RomFileManager& rom_manager, ProjectManager& project_manager,
40 EditorRegistry& editor_registry, SessionCoordinator& session_coordinator,
41 ToastManager& toast_manager, PopupManager& popup_manager)
42 : editor_manager_(editor_manager),
43 menu_builder_(menu_builder),
44 rom_manager_(rom_manager),
45 project_manager_(project_manager),
46 editor_registry_(editor_registry),
47 session_coordinator_(session_coordinator),
48 toast_manager_(toast_manager),
49 popup_manager_(popup_manager) {}
50
52 ClearMenu();
53
54 // Build all menu sections in order
55 // Traditional order: File, Edit, View, then app-specific menus
59 // Windows menu now owns what used to live in the legacy "Window" menu
60 // (Sessions, Layout, Snapshots) in addition to the dynamic category
61 // toggles from WorkspaceWindowManager.
63 BuildToolsMenu(); // Debug menu items merged into Tools
65
66 // Draw the constructed menu
68
69 // Render any deferred modal popups owned by the menu layer. These run
70 // after the menu stack unwinds so the popup has a clean ImGui stack.
72 ImGui::OpenPopup("Save Layout Snapshot##menu_orch_save_snapshot");
74 }
75 if (ImGui::BeginPopupModal("Save Layout Snapshot##menu_orch_save_snapshot",
76 nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
77 ImGui::TextUnformatted("Snapshot name:");
78 ImGui::SetNextItemWidth(320.0f);
79 const bool submitted =
80 ImGui::InputText("##snapshot_name", save_snapshot_name_buffer_,
82 ImGuiInputTextFlags_EnterReturnsTrue);
83 const bool has_name = save_snapshot_name_buffer_[0] != '\0';
84 ImGui::Separator();
85 if ((ImGui::Button("Save", ImVec2(120, 0)) || submitted) && has_name) {
86 if (editor_manager_) {
88 }
90 ImGui::CloseCurrentPopup();
91 }
92 ImGui::SameLine();
93 if (ImGui::Button("Cancel", ImVec2(120, 0))) {
95 ImGui::CloseCurrentPopup();
96 }
97 ImGui::EndPopup();
98 }
99
100 menu_needs_refresh_ = false;
101}
102
108
110 // ROM Operations
112 .Item(
113 "Open ROM / Project...", ICON_MD_FILE_OPEN, [this]() { OnOpenRom(); },
114 SHORTCUT_CTRL(O))
115 .Item(
116 "Save ROM", ICON_MD_SAVE, [this]() { OnSaveRom(); }, SHORTCUT_CTRL(S),
117 [this]() { return CanSaveRom(); })
118 .Item(
119 "Save As...", ICON_MD_SAVE_AS, [this]() { OnSaveRomAs(); }, nullptr,
120 [this]() { return CanSaveRom(); })
121 .Item("Save Scope...", ICON_MD_TUNE,
123 .Separator();
124
125 // Project Operations
127 .Item("New Project", ICON_MD_CREATE_NEW_FOLDER,
128 [this]() { OnCreateProject(); })
129 .Item("Open Project Only...", ICON_MD_FOLDER_OPEN,
130 [this]() { OnOpenProject(); })
131 .Item(
132 "Save Project", ICON_MD_SAVE, [this]() { OnSaveProject(); }, nullptr,
133 [this]() { return CanSaveProject(); })
134 .Item(
135 "Save Project As...", ICON_MD_SAVE_AS,
136 [this]() { OnSaveProjectAs(); }, nullptr,
137 [this]() { return CanSaveProject(); })
138 .Item(
139 "Project Management...", ICON_MD_FOLDER_SPECIAL,
140 [this]() { OnShowProjectManagement(); }, nullptr,
141 [this]() { return CanSaveProject(); })
142 .Item(
143 "Edit Project File...", ICON_MD_DESCRIPTION,
144 [this]() { OnShowProjectFileEditor(); }, nullptr,
145 [this]() { return HasProjectFile(); })
146 .Separator();
147
148 // ROM Information and Validation
150 .Item(
151 "ROM Information", ICON_MD_INFO, [this]() { OnShowRomInfo(); },
152 nullptr, [this]() { return HasActiveRom(); })
153 .Item(
154 "Create Backup", ICON_MD_BACKUP, [this]() { OnCreateBackup(); },
155 nullptr, [this]() { return HasActiveRom(); })
156 .Item(
157 "ROM Backups...", ICON_MD_BACKUP,
158 [this]() { popup_manager_.Show(PopupID::kRomBackups); }, nullptr,
159 [this]() { return HasActiveRom(); })
160 .Item(
161 "Validate ROM", ICON_MD_CHECK_CIRCLE, [this]() { OnValidateRom(); },
162 nullptr, [this]() { return HasActiveRom(); })
163 .Separator();
164
165 // BPS Patch Operations
167 .Item(
168 "Export BPS Patch...", ICON_MD_DIFFERENCE,
169 [this]() { OnExportBpsPatch(); }, nullptr,
170 [this]() { return HasActiveRom(); })
171 .Item(
172 "Apply BPS Patch...", ICON_MD_BUILD, [this]() { OnApplyBpsPatch(); },
173 nullptr, [this]() { return HasActiveRom(); })
174 .Separator();
175
176 // Settings and Quit
178 .Item("Settings", ICON_MD_SETTINGS, [this]() { OnShowSettings(); })
179 .Separator()
180 .Item(
181 "Quit", ICON_MD_EXIT_TO_APP, [this]() { OnQuit(); },
182 SHORTCUT_CTRL(Q));
183}
184
190
192 // Undo/Redo operations - delegate to current editor
194 .Item(
195 "Undo", ICON_MD_UNDO, [this]() { OnUndo(); }, SHORTCUT_CTRL(Z),
196 [this]() { return HasCurrentEditor(); })
197 .Item(
198 "Redo", ICON_MD_REDO, [this]() { OnRedo(); }, SHORTCUT_CTRL(Y),
199 [this]() { return HasCurrentEditor(); })
200 .Separator();
201
202 // Clipboard operations - delegate to current editor
204 .Item(
205 "Cut", ICON_MD_CONTENT_CUT, [this]() { OnCut(); }, SHORTCUT_CTRL(X),
206 [this]() { return HasCurrentEditor(); })
207 .Item(
208 "Copy", ICON_MD_CONTENT_COPY, [this]() { OnCopy(); },
209 SHORTCUT_CTRL(C), [this]() { return HasCurrentEditor(); })
210 .Item(
211 "Paste", ICON_MD_CONTENT_PASTE, [this]() { OnPaste(); },
212 SHORTCUT_CTRL(V), [this]() { return HasCurrentEditor(); })
213 .Separator();
214
215 // Search operations (Find in Files moved to Tools > Global Search)
217 "Find", ICON_MD_SEARCH, [this]() { OnFind(); }, SHORTCUT_CTRL(F),
218 [this]() { return HasCurrentEditor(); });
219}
220
226
230
233
234 // Editor selection (Switch Editor)
236 "Switch Editor...", ICON_MD_SWAP_HORIZ,
237 [this]() { OnShowEditorSelection(); }, SHORTCUT_CTRL(E),
238 [this]() { return HasActiveRom(); });
239}
240
242 // Appearance/Layout controls
244 .Item(
245 "Show Sidebar", ICON_MD_VIEW_SIDEBAR,
246 [this]() {
247 if (window_manager_)
249 },
250 SHORTCUT_CTRL(B), nullptr,
251 [this]() {
253 })
254 .Item(
255 "Show Status Bar", ICON_MD_HORIZONTAL_RULE,
256 [this]() {
257 if (user_settings_) {
261 if (status_bar_) {
264 }
265 }
266 },
267 nullptr, nullptr,
268 [this]() {
270 })
271 .Separator()
272 .Item("Display Settings", ICON_MD_DISPLAY_SETTINGS,
273 [this]() { OnShowDisplaySettings(); })
274 .Item("Welcome Screen", ICON_MD_HOME,
275 [this]() { OnShowWelcomeScreen(); });
276}
277
279 const auto layout_enabled = [this]() {
280 return HasCurrentEditor();
281 };
282
284 .Item(
285 "Profile: Code", ICON_MD_CODE,
286 [this]() {
287 if (editor_manager_) {
289 }
290 },
291 nullptr, layout_enabled)
292 .Item(
293 "Profile: Debug", ICON_MD_BUG_REPORT,
294 [this]() {
295 if (editor_manager_) {
297 }
298 },
299 nullptr, layout_enabled)
300 .Item(
301 "Profile: Mapping", ICON_MD_MAP,
302 [this]() {
303 if (editor_manager_) {
305 }
306 },
307 nullptr, layout_enabled)
308 .Item(
309 "Profile: Chat + Agent", ICON_MD_SMART_TOY,
310 [this]() {
311 if (editor_manager_) {
313 }
314 },
315 nullptr, layout_enabled)
316 .Separator()
317 .Item(
318 "Developer", ICON_MD_DEVELOPER_MODE,
319 [this]() { OnLoadDeveloperLayout(); }, nullptr, layout_enabled)
320 .Item(
321 "Designer", ICON_MD_DESIGN_SERVICES,
322 [this]() { OnLoadDesignerLayout(); }, nullptr, layout_enabled)
323 .Item(
324 "Modder", ICON_MD_BUILD, [this]() { OnLoadModderLayout(); }, nullptr,
325 layout_enabled)
326 .Separator()
327 .Item(
328 "Reset Current Editor", ICON_MD_REFRESH,
329 [this]() {
330 if (editor_manager_) {
332 }
333 },
334 nullptr, layout_enabled)
335 .EndMenu();
336}
337
339 // Use CustomMenu to integrate dynamic panel content with the menu builder
340 menu_builder_.CustomMenu("Windows", [this]() { AddPanelsMenuItems(); });
341}
342
344 if (!window_manager_) {
345 return;
346 }
347
348 const size_t session_id = session_coordinator_.GetActiveSessionIndex();
349 std::string active_category = window_manager_->GetActiveCategory();
350 auto all_categories = window_manager_->GetAllCategories(session_id);
351
352 // Window Browser action at top
353 if (ImGui::MenuItem(
354 absl::StrFormat("%s Window Browser", ICON_MD_APPS).c_str(),
357 }
358 if (ImGui::MenuItem(
359 absl::StrFormat("%s Show All Windows", ICON_MD_VISIBILITY).c_str())) {
361 }
362 if (ImGui::MenuItem(
363 absl::StrFormat("%s Hide All Windows", ICON_MD_VISIBILITY_OFF)
364 .c_str())) {
366 }
367 ImGui::Separator();
368
369 // Sessions and Layout — folded in from the former "Window" top-level menu.
370 // These draw directly against ImGui (not through MenuBuilder) because
371 // CustomMenu's callback runs *inside* an already-open BeginMenu scope.
375 ImGui::Separator();
376
377 if (all_categories.empty()) {
378 ImGui::TextDisabled("No windows available");
379 return;
380 }
381
382 // Show all categories as direct submenus (no nested "All Categories" wrapper)
383 for (const auto& category : all_categories) {
384 // Mark active category with icon
385 std::string label = category;
386 if (category == active_category) {
387 label = absl::StrFormat("%s %s", ICON_MD_FOLDER_OPEN, category);
388 } else {
389 label = absl::StrFormat("%s %s", ICON_MD_FOLDER, category);
390 }
391
392 if (ImGui::BeginMenu(label.c_str())) {
393 auto cards = window_manager_->GetWindowsInCategory(session_id, category);
394
395 if (cards.empty()) {
396 ImGui::TextDisabled("No windows in this category");
397 } else {
398 if (ImGui::MenuItem(
399 absl::StrFormat("%s Show Category", ICON_MD_VISIBILITY)
400 .c_str())) {
401 window_manager_->ShowAllWindowsInCategory(session_id, category);
402 }
403 if (ImGui::MenuItem(
404 absl::StrFormat("%s Hide Category", ICON_MD_VISIBILITY_OFF)
405 .c_str())) {
406 window_manager_->HideAllWindowsInCategory(session_id, category);
407 }
408 ImGui::Separator();
409
410 for (const auto& card : cards) {
411 bool is_visible =
412 window_manager_->IsWindowOpen(session_id, card.card_id);
413 const char* shortcut =
414 card.shortcut_hint.empty() ? nullptr : card.shortcut_hint.c_str();
415
416 // Show icon for visible panels
417 std::string item_label =
418 is_visible
419 ? absl::StrFormat("%s %s", ICON_MD_CHECK_BOX,
420 card.display_name)
421 : absl::StrFormat("%s %s", ICON_MD_CHECK_BOX_OUTLINE_BLANK,
422 card.display_name);
423
424 if (ImGui::MenuItem(item_label.c_str(), shortcut)) {
425 window_manager_->ToggleWindow(session_id, card.card_id);
426 }
427 }
428 }
429 ImGui::EndMenu();
430 }
431 }
432}
433
439
444
448
450
451#ifdef YAZE_ENABLE_TESTING
453#endif
454
455 // ImGui Debug (moved from Debug menu)
457 .Item("ImGui Demo", ICON_MD_HELP, [this]() { OnShowImGuiDemo(); })
458 .Item("ImGui Metrics", ICON_MD_ANALYTICS,
459 [this]() { OnShowImGuiMetrics(); })
460 .EndMenu()
461 .Separator();
462
463#ifdef YAZE_WITH_GRPC
464 AddCollaborationMenuItems();
465#endif
466}
467
469 // Search & Navigation
471 .Item(
472 "Global Search", ICON_MD_SEARCH, [this]() { OnShowGlobalSearch(); },
474 .Item(
475 "Command Palette", ICON_MD_SEARCH,
476 [this]() { OnShowCommandPalette(); }, SHORTCUT_CTRL_SHIFT(P))
477 .Item(
478 "Window Finder", ICON_MD_DASHBOARD, [this]() { OnShowPanelFinder(); },
479 SHORTCUT_CTRL(P))
480 .Item("Resource Label Manager", ICON_MD_LABEL,
481 [this]() { OnShowResourceLabelManager(); });
482}
483
486
487 std::map<std::string, std::vector<WorkflowItem>> grouped_items;
488
489 if (window_manager_) {
490 const size_t session_id = session_coordinator_.GetActiveSessionIndex();
491 const auto categories = window_manager_->GetAllCategories(session_id);
492 for (const auto& category : categories) {
493 for (const auto& descriptor :
494 window_manager_->GetWindowsInCategory(session_id, category)) {
495 if (descriptor.workflow_group.empty()) {
496 continue;
497 }
498 WorkflowItem item;
499 item.id = absl::StrFormat("panel.%s", descriptor.card_id);
500 item.group = descriptor.workflow_group;
501 item.label = descriptor.workflow_label.empty()
502 ? descriptor.display_name
503 : descriptor.workflow_label;
504 item.description =
505 descriptor.workflow_description.empty()
506 ? absl::StrFormat("Open %s", descriptor.display_name)
507 : descriptor.workflow_description;
508 item.shortcut = descriptor.shortcut_hint;
509 item.priority = descriptor.workflow_priority;
510 item.callback = [this, session_id, panel_id = descriptor.card_id]() {
511 if (window_manager_) {
512 window_manager_->OpenWindow(session_id, panel_id);
513 }
514 };
515 item.enabled = descriptor.enabled_condition;
516 const std::string group = item.group.empty() ? "General" : item.group;
517 grouped_items[group].push_back(std::move(item));
518 }
519 }
520 }
521
522 for (const auto& action : ContentRegistry::WorkflowActions::GetAll()) {
523 const std::string group = action.group.empty() ? "General" : action.group;
524 grouped_items[group].push_back(action);
525 }
526
527 if (grouped_items.empty()) {
528 return;
529 }
530
531 menu_builder_.BeginSubMenu("Hack Workflows", ICON_MD_ROUTE);
532 for (auto& [group, items] : grouped_items) {
533 std::sort(items.begin(), items.end(),
534 [](const WorkflowItem& lhs, const WorkflowItem& rhs) {
535 if (lhs.priority != rhs.priority) {
536 return lhs.priority < rhs.priority;
537 }
538 return lhs.label < rhs.label;
539 });
541 for (const auto& item : items) {
542 MenuBuilder::EnabledCheck enabled = item.enabled;
544 item.label.c_str(), item.callback,
545 item.shortcut.empty() ? nullptr : item.shortcut.c_str(), enabled);
546 }
548 }
549 menu_builder_.EndMenu();
550}
551
552void MenuOrchestrator::AddRomAnalysisMenuItems() {
553 // ROM Analysis (moved from Debug menu)
554 menu_builder_.BeginSubMenu("ROM Analysis", ICON_MD_STORAGE)
555 .Item(
556 "ROM Information", ICON_MD_INFO, [this]() { OnShowRomInfo(); },
557 nullptr, [this]() { return HasActiveRom(); })
558 .Item(
559 "Data Integrity Check", ICON_MD_ANALYTICS,
560 [this]() { OnRunDataIntegrityCheck(); }, nullptr,
561 [this]() { return HasActiveRom(); })
562 .Item(
563 "Test Save/Load", ICON_MD_SAVE_ALT, [this]() { OnTestSaveLoad(); },
564 nullptr, [this]() { return HasActiveRom(); })
565 .EndMenu();
566
567 // ZSCustomOverworld (moved from Debug menu)
568 menu_builder_.BeginSubMenu("ZSCustomOverworld", ICON_MD_CODE)
569 .Item(
570 "Check ROM Version", ICON_MD_INFO, [this]() { OnCheckRomVersion(); },
571 nullptr, [this]() { return HasActiveRom(); })
572 .Item(
573 "Upgrade ROM", ICON_MD_UPGRADE, [this]() { OnUpgradeRom(); }, nullptr,
574 [this]() { return HasActiveRom(); })
575 .Item("Toggle Custom Loading", ICON_MD_SETTINGS,
576 [this]() { OnToggleCustomLoading(); })
577 .EndMenu();
578}
579
580void MenuOrchestrator::AddAsarIntegrationMenuItems() {
581 // Asar Integration (moved from Debug menu)
582 menu_builder_.BeginSubMenu("Asar Integration", ICON_MD_BUILD)
583 .Item("Asar Status", ICON_MD_INFO,
584 [this]() { popup_manager_.Show(PopupID::kAsarIntegration); })
585 .Item(
586 "Toggle ASM Patch", ICON_MD_CODE, [this]() { OnToggleAsarPatch(); },
587 nullptr, [this]() { return HasActiveRom(); })
588 .Item("Load ASM File", ICON_MD_FOLDER_OPEN, [this]() { OnLoadAsmFile(); })
589 .EndMenu();
590}
591
592void MenuOrchestrator::AddDevelopmentMenuItems() {
593 // Development Tools (moved from Debug menu)
594 menu_builder_.BeginSubMenu("Development", ICON_MD_DEVELOPER_MODE)
595 .Item("Memory Editor", ICON_MD_MEMORY, [this]() { OnShowMemoryEditor(); })
596 .Item("Assembly Editor", ICON_MD_CODE,
597 [this]() { OnShowAssemblyEditor(); })
598 .Item("Feature Flags", ICON_MD_FLAG,
599 [this]() { popup_manager_.Show(PopupID::kFeatureFlags); })
600 .Item("Performance Dashboard", ICON_MD_SPEED,
601 [this]() { OnShowPerformanceDashboard(); })
602#ifdef YAZE_BUILD_AGENT_UI
603 .Item("Agent Workspace", ICON_MD_SMART_TOY, [this]() { OnShowAIAgent(); })
604#endif
605#ifdef YAZE_WITH_GRPC
606 .Item("Agent Proposals", ICON_MD_PREVIEW,
607 [this]() { OnShowProposalDrawer(); })
608#endif
609 .EndMenu();
610}
611
612void MenuOrchestrator::AddTestingMenuItems() {
613 // Testing (moved from Debug menu)
614 menu_builder_.BeginSubMenu("Testing", ICON_MD_SCIENCE);
615#ifdef YAZE_ENABLE_TESTING
616 menu_builder_
617 .Item(
618 "Test Dashboard", ICON_MD_DASHBOARD,
619 [this]() { OnShowTestDashboard(); }, SHORTCUT_CTRL(T))
620 .Item("Run All Tests", ICON_MD_PLAY_ARROW, [this]() { OnRunAllTests(); })
621 .Item("Run Unit Tests", ICON_MD_CHECK_BOX, [this]() { OnRunUnitTests(); })
622 .Item("Run Integration Tests", ICON_MD_INTEGRATION_INSTRUCTIONS,
623 [this]() { OnRunIntegrationTests(); })
624 .Item("Run E2E Tests", ICON_MD_VISIBILITY, [this]() { OnRunE2ETests(); });
625#else
626 menu_builder_.DisabledItem(
627 "Testing support disabled (YAZE_ENABLE_TESTING=OFF)", ICON_MD_INFO);
628#endif
629 menu_builder_.EndMenu();
630}
631
632#ifdef YAZE_WITH_GRPC
633void MenuOrchestrator::AddCollaborationMenuItems() {
634 // Collaboration (GRPC builds only)
635 menu_builder_.BeginSubMenu("Collaborate", ICON_MD_PEOPLE)
636 .Item("Start Collaboration Session", ICON_MD_PLAY_CIRCLE,
637 [this]() { OnStartCollaboration(); })
638 .Item("Join Collaboration Session", ICON_MD_GROUP_ADD,
639 [this]() { OnJoinCollaboration(); })
640 .Item("Network Status", ICON_MD_CLOUD,
641 [this]() { OnShowNetworkStatus(); })
642 .EndMenu();
643}
644#endif
645
646// Sessions submenu (folded from the former top-level "Window" menu).
647// Drawn inline inside the "Windows" CustomMenu callback using raw ImGui
648// calls so the entries land in the same menu scope.
649void MenuOrchestrator::AddSessionsSubmenu() {
650 if (ImGui::BeginMenu(absl::StrFormat("%s Sessions", ICON_MD_TAB).c_str())) {
651 if (ImGui::MenuItem(absl::StrFormat("%s New Session", ICON_MD_ADD).c_str(),
653 OnCreateNewSession();
654 }
655 if (ImGui::MenuItem(
656 absl::StrFormat("%s Duplicate Session", ICON_MD_CONTENT_COPY)
657 .c_str(),
658 nullptr, false, HasActiveRom())) {
659 OnDuplicateCurrentSession();
660 }
661 if (ImGui::MenuItem(
662 absl::StrFormat("%s Close Session", ICON_MD_CLOSE).c_str(),
663 SHORTCUT_CTRL_SHIFT(W), false, HasMultipleSessions())) {
664 OnCloseCurrentSession();
665 }
666 ImGui::Separator();
667 if (ImGui::MenuItem(
668 absl::StrFormat("%s Session Switcher", ICON_MD_SWITCH_ACCOUNT)
669 .c_str(),
670 SHORTCUT_CTRL(Tab), false, HasMultipleSessions())) {
671 OnShowSessionSwitcher();
672 }
673 if (ImGui::MenuItem(
674 absl::StrFormat("%s Session Manager", ICON_MD_VIEW_LIST).c_str())) {
675 OnShowSessionManager();
676 }
677 ImGui::EndMenu();
678 }
679}
680
681// Layout submenu (folded from the former top-level "Window" menu).
682// Contains Save/Load/Reset, session snapshots, and named presets.
683void MenuOrchestrator::AddLayoutSubmenu() {
684 const bool layout_enabled = HasCurrentEditor();
685 auto apply_preset = [this](const char* name) {
686 if (editor_manager_)
687 editor_manager_->ApplyLayoutPreset(name);
688 };
689 auto apply_profile = [this](const char* name) {
690 if (editor_manager_)
691 editor_manager_->ApplyLayoutProfile(name);
692 };
693
694 if (ImGui::BeginMenu(
695 absl::StrFormat("%s Layout", ICON_MD_VIEW_QUILT).c_str())) {
696 if (ImGui::MenuItem(absl::StrFormat("%s Save Layout", ICON_MD_SAVE).c_str(),
698 OnSaveWorkspaceLayout();
699 }
700 if (ImGui::MenuItem(
701 absl::StrFormat("%s Load Layout", ICON_MD_FOLDER_OPEN).c_str(),
703 OnLoadWorkspaceLayout();
704 }
705 if (ImGui::MenuItem(
706 absl::StrFormat("%s Reset Layout", ICON_MD_RESET_TV).c_str())) {
707 OnResetWorkspaceLayout();
708 }
709 if (ImGui::MenuItem(
710 absl::StrFormat("%s Reset Active Editor Layout", ICON_MD_REFRESH)
711 .c_str(),
712 nullptr, false, layout_enabled)) {
713 if (editor_manager_)
714 editor_manager_->ResetCurrentEditorLayout();
715 }
716
717 ImGui::Separator();
718 if (ImGui::BeginMenu(
719 absl::StrFormat("%s Snapshots", ICON_MD_BOOKMARKS).c_str(),
720 layout_enabled)) {
721 if (ImGui::MenuItem(
722 absl::StrFormat("%s Save Snapshot As...", ICON_MD_BOOKMARK_ADD)
723 .c_str(),
724 nullptr, false, layout_enabled)) {
725 save_snapshot_name_buffer_[0] = '\0';
726 open_save_snapshot_modal_ = true;
727 }
728
729 // Named snapshots (session-scoped, in-memory).
730 std::vector<std::string> named =
731 editor_manager_ ? editor_manager_->ListLayoutSnapshots()
732 : std::vector<std::string>{};
733 if (!named.empty()) {
734 ImGui::Separator();
735 for (const auto& name : named) {
736 ImGui::PushID(name.c_str());
737 if (ImGui::MenuItem(
738 absl::StrFormat("%s %s", ICON_MD_RESTORE, name).c_str(),
739 nullptr, false, layout_enabled)) {
740 if (editor_manager_)
741 editor_manager_->RestoreLayoutSnapshot(name);
742 }
743 ImGui::SameLine(ImGui::GetContentRegionAvail().x);
744 if (ImGui::SmallButton(ICON_MD_DELETE)) {
745 if (editor_manager_)
746 editor_manager_->DeleteLayoutSnapshot(name);
747 }
748 ImGui::PopID();
749 }
750 }
751
752 ImGui::Separator();
753 // Legacy unnamed temporary slot (backward-compatible Capture/Restore).
754 if (ImGui::MenuItem(
755 absl::StrFormat("%s Capture Unnamed", ICON_MD_BOOKMARK_ADD)
756 .c_str(),
757 nullptr, false, layout_enabled)) {
758 if (editor_manager_)
759 editor_manager_->CaptureTemporaryLayoutSnapshot();
760 }
761 if (ImGui::MenuItem(
762 absl::StrFormat("%s Restore Unnamed", ICON_MD_RESTORE).c_str(),
763 nullptr, false, layout_enabled)) {
764 if (editor_manager_)
765 editor_manager_->RestoreTemporaryLayoutSnapshot();
766 }
767 if (ImGui::MenuItem(
768 absl::StrFormat("%s Clear Unnamed", ICON_MD_BOOKMARK_REMOVE)
769 .c_str(),
770 nullptr, false, layout_enabled)) {
771 if (editor_manager_)
772 editor_manager_->ClearTemporaryLayoutSnapshot();
773 }
774 ImGui::EndMenu();
775 }
776
777 ImGui::Separator();
778 if (ImGui::BeginMenu(
779 absl::StrFormat("%s Presets", ICON_MD_DASHBOARD).c_str())) {
780 if (ImGui::MenuItem(absl::StrFormat("%s Code", ICON_MD_CODE).c_str(),
781 nullptr, false, layout_enabled)) {
782 apply_profile("code");
783 }
784 if (ImGui::MenuItem(
785 absl::StrFormat("%s Debug", ICON_MD_BUG_REPORT).c_str(), nullptr,
786 false, layout_enabled)) {
787 apply_profile("debug");
788 }
789 if (ImGui::MenuItem(absl::StrFormat("%s Mapping", ICON_MD_MAP).c_str(),
790 nullptr, false, layout_enabled)) {
791 apply_profile("mapping");
792 }
793 if (ImGui::MenuItem(
794 absl::StrFormat("%s Chat + Agent", ICON_MD_SMART_TOY).c_str(),
795 nullptr, false, layout_enabled)) {
796 apply_profile("chat");
797 }
798 ImGui::Separator();
799 if (ImGui::MenuItem(
800 absl::StrFormat("%s Minimal", ICON_MD_VIEW_COMPACT).c_str(),
801 nullptr, false, layout_enabled)) {
802 apply_preset("Minimal");
803 }
804 if (ImGui::MenuItem(
805 absl::StrFormat("%s Developer", ICON_MD_DEVELOPER_MODE).c_str(),
806 nullptr, false, layout_enabled)) {
807 OnLoadDeveloperLayout();
808 }
809 if (ImGui::MenuItem(
810 absl::StrFormat("%s Designer", ICON_MD_DESIGN_SERVICES).c_str(),
811 nullptr, false, layout_enabled)) {
812 OnLoadDesignerLayout();
813 }
814 if (ImGui::MenuItem(absl::StrFormat("%s Modder", ICON_MD_BUILD).c_str(),
815 nullptr, false, layout_enabled)) {
816 OnLoadModderLayout();
817 }
818 if (ImGui::MenuItem(
819 absl::StrFormat("%s Overworld Expert", ICON_MD_MAP).c_str(),
820 nullptr, false, layout_enabled)) {
821 apply_preset("Overworld Expert");
822 }
823 if (ImGui::MenuItem(
824 absl::StrFormat("%s Dungeon Expert", ICON_MD_CASTLE).c_str(),
825 nullptr, false, layout_enabled)) {
826 apply_preset("Dungeon Expert");
827 }
828 if (ImGui::MenuItem(
829 absl::StrFormat("%s Testing", ICON_MD_SCIENCE).c_str(), nullptr,
830 false, layout_enabled)) {
831 apply_preset("Testing");
832 }
833 if (ImGui::MenuItem(
834 absl::StrFormat("%s Audio", ICON_MD_MUSIC_NOTE).c_str(), nullptr,
835 false, layout_enabled)) {
836 apply_preset("Audio");
837 }
838 ImGui::Separator();
839 if (ImGui::MenuItem(
840 absl::StrFormat("%s Manage Presets...", ICON_MD_TUNE).c_str())) {
841 OnShowLayoutPresets();
842 }
843 ImGui::EndMenu();
844 }
845 ImGui::EndMenu();
846 }
847}
848
849// Sidebar submenu — surfaces ActivityBar pin/hide/reorder operations so the
850// feature is discoverable from the menubar without touching the rail.
851void MenuOrchestrator::AddSidebarSubmenu() {
852 if (!user_settings_) {
853 return;
854 }
855
856 if (!ImGui::BeginMenu(
857 absl::StrFormat("%s Sidebar", ICON_MD_VIEW_SIDEBAR).c_str())) {
858 return;
859 }
860
861 auto persist = [this]() { (void)user_settings_->Save(); };
862 auto& prefs = user_settings_->prefs();
863
864 if (ImGui::MenuItem(absl::StrFormat("%s Reset Order", ICON_MD_RESTART_ALT)
865 .c_str(),
866 nullptr, false, !prefs.sidebar_order.empty())) {
867 prefs.sidebar_order.clear();
868 persist();
869 }
870 if (ImGui::MenuItem(
871 absl::StrFormat("%s Show All Categories", ICON_MD_VISIBILITY).c_str(),
872 nullptr, false, !prefs.sidebar_hidden.empty())) {
873 prefs.sidebar_hidden.clear();
874 persist();
875 }
876
877 ImGui::Separator();
878
879 const size_t session_id = session_coordinator_.GetActiveSessionIndex();
880 std::vector<std::string> categories;
881 if (window_manager_) {
882 categories = window_manager_->GetAllCategories(session_id);
883 }
884
885 // Build pinned list (in canonical category order).
886 std::vector<std::string> pinned_list;
887 std::vector<std::string> hidden_list;
888 for (const auto& cat : categories) {
889 if (cat == WorkspaceWindowManager::kDashboardCategory) continue;
890 if (prefs.sidebar_pinned.count(cat)) pinned_list.push_back(cat);
891 if (prefs.sidebar_hidden.count(cat)) hidden_list.push_back(cat);
892 }
893
894 if (ImGui::BeginMenu(
895 absl::StrFormat("%s Pinned", ICON_MD_PUSH_PIN).c_str())) {
896 if (pinned_list.empty()) {
897 ImGui::TextDisabled("(none)");
898 } else {
899 for (const auto& cat : pinned_list) {
900 ImGui::PushID(cat.c_str());
901 if (ImGui::MenuItem(absl::StrFormat("%s Unpin %s", ICON_MD_CLOSE, cat)
902 .c_str())) {
903 prefs.sidebar_pinned.erase(cat);
904 persist();
905 }
906 ImGui::PopID();
907 }
908 }
909 ImGui::EndMenu();
910 }
911
912 if (ImGui::BeginMenu(
913 absl::StrFormat("%s Hidden", ICON_MD_VISIBILITY_OFF).c_str())) {
914 if (hidden_list.empty()) {
915 ImGui::TextDisabled("(none)");
916 } else {
917 for (const auto& cat : hidden_list) {
918 ImGui::PushID(cat.c_str());
919 if (ImGui::MenuItem(
920 absl::StrFormat("%s Show %s", ICON_MD_VISIBILITY, cat).c_str())) {
921 prefs.sidebar_hidden.erase(cat);
922 persist();
923 }
924 ImGui::PopID();
925 }
926 }
927 ImGui::EndMenu();
928 }
929
930 ImGui::Separator();
931
932 // Per-category toggles (pin/hide) for all categories. Keeps the menu
933 // discoverable even for users who haven't right-clicked the rail.
934 if (ImGui::BeginMenu(
935 absl::StrFormat("%s Customize", ICON_MD_TUNE).c_str())) {
936 if (categories.empty()) {
937 ImGui::TextDisabled("No categories available");
938 } else {
939 for (const auto& cat : categories) {
940 if (cat == WorkspaceWindowManager::kDashboardCategory) continue;
941 ImGui::PushID(cat.c_str());
942 const bool pinned = prefs.sidebar_pinned.count(cat) > 0;
943 const bool hidden = prefs.sidebar_hidden.count(cat) > 0;
944 if (ImGui::BeginMenu(cat.c_str())) {
945 if (ImGui::MenuItem(pinned ? "Unpin from top" : "Pin to top", nullptr,
946 pinned)) {
947 if (pinned) {
948 prefs.sidebar_pinned.erase(cat);
949 } else {
950 prefs.sidebar_pinned.insert(cat);
951 }
952 persist();
953 }
954 if (ImGui::MenuItem(hidden ? "Show on sidebar" : "Hide from sidebar",
955 nullptr, hidden)) {
956 if (hidden) {
957 prefs.sidebar_hidden.erase(cat);
958 } else {
959 prefs.sidebar_hidden.insert(cat);
960 }
961 persist();
962 }
963 ImGui::EndMenu();
964 }
965 ImGui::PopID();
966 }
967 }
968 ImGui::EndMenu();
969 }
970
971 ImGui::EndMenu();
972}
973
974void MenuOrchestrator::BuildHelpMenu() {
975 menu_builder_.BeginMenu("Help");
976 AddHelpMenuItems();
977 menu_builder_.EndMenu();
978}
979
980void MenuOrchestrator::AddHelpMenuItems() {
981 // Note: Asar Integration moved to Tools menu to reduce redundancy
982 menu_builder_
983 .Item("Getting Started", ICON_MD_PLAY_ARROW,
984 [this]() { OnShowGettingStarted(); })
985 .Item("Keyboard Shortcuts", ICON_MD_KEYBOARD,
986 [this]() { OnShowSettings(); })
987 .Item("Build Instructions", ICON_MD_BUILD,
988 [this]() { OnShowBuildInstructions(); })
989 .Item("CLI Usage", ICON_MD_TERMINAL, [this]() { OnShowCLIUsage(); })
990 .Separator()
991 .Item("Supported Features", ICON_MD_CHECK_CIRCLE,
992 [this]() { OnShowSupportedFeatures(); })
993 .Item("What's New", ICON_MD_NEW_RELEASES, [this]() { OnShowWhatsNew(); })
994 .Separator()
995 .Item("Troubleshooting", ICON_MD_BUILD_CIRCLE,
996 [this]() { OnShowTroubleshooting(); })
997 .Item("Contributing", ICON_MD_VOLUNTEER_ACTIVISM,
998 [this]() { OnShowContributing(); })
999 .Separator()
1000 .Item("About", ICON_MD_INFO, [this]() { OnShowAbout(); }, "F1");
1001}
1002
1003// Menu state management
1004void MenuOrchestrator::ClearMenu() {
1005 menu_builder_.Clear();
1006}
1007
1008void MenuOrchestrator::RefreshMenu() {
1009 menu_needs_refresh_ = true;
1010}
1011
1012// Menu item callbacks - delegate to appropriate managers
1013void MenuOrchestrator::OnOpenRom() {
1014 // Delegate to EditorManager's LoadRom which handles session management
1015 if (editor_manager_) {
1016 auto status = editor_manager_->LoadRom();
1017 if (!status.ok()) {
1018 toast_manager_.Show(
1019 absl::StrFormat("Failed to load ROM: %s", status.message()),
1020 ToastType::kError);
1021 }
1022 }
1023}
1024
1025void MenuOrchestrator::OnSaveRom() {
1026 // Delegate to EditorManager's SaveRom which handles editor data saving
1027 if (editor_manager_) {
1028 auto status = editor_manager_->SaveRom();
1029 if (!status.ok()) {
1030 if (absl::IsCancelled(status)) {
1031 return;
1032 }
1033 toast_manager_.Show(
1034 absl::StrFormat("Failed to save ROM: %s", status.message()),
1035 ToastType::kError);
1036 } else {
1037 toast_manager_.Show("ROM saved successfully", ToastType::kSuccess);
1038 }
1039 }
1040}
1041
1042void MenuOrchestrator::OnSaveRomAs() {
1043 popup_manager_.Show(PopupID::kSaveAs);
1044}
1045
1046void MenuOrchestrator::OnCreateProject() {
1047 // Delegate to EditorManager which handles the full project creation flow
1048 if (editor_manager_) {
1049 auto status = editor_manager_->CreateNewProject();
1050 if (!status.ok()) {
1051 toast_manager_.Show(
1052 absl::StrFormat("Failed to create project: %s", status.message()),
1053 ToastType::kError);
1054 }
1055 }
1056}
1057
1058void MenuOrchestrator::OnOpenProject() {
1059 // Delegate to EditorManager which handles ROM loading and session creation
1060 if (editor_manager_) {
1061 auto status = editor_manager_->OpenProject();
1062 if (!status.ok()) {
1063 toast_manager_.Show(
1064 absl::StrFormat("Failed to open project: %s", status.message()),
1065 ToastType::kError);
1066 }
1067 }
1068}
1069
1070void MenuOrchestrator::OnSaveProject() {
1071 // Delegate to EditorManager which updates project with current state
1072 if (editor_manager_) {
1073 auto status = editor_manager_->SaveProject();
1074 if (!status.ok()) {
1075 toast_manager_.Show(
1076 absl::StrFormat("Failed to save project: %s", status.message()),
1077 ToastType::kError);
1078 } else {
1079 toast_manager_.Show("Project saved successfully", ToastType::kSuccess);
1080 }
1081 }
1082}
1083
1084void MenuOrchestrator::OnSaveProjectAs() {
1085 // Delegate to EditorManager
1086 if (editor_manager_) {
1087 auto status = editor_manager_->SaveProjectAs();
1088 if (!status.ok()) {
1089 toast_manager_.Show(
1090 absl::StrFormat("Failed to save project as: %s", status.message()),
1091 ToastType::kError);
1092 }
1093 }
1094}
1095
1096void MenuOrchestrator::OnShowProjectManagement() {
1097 // Show project management panel in right sidebar
1098 if (editor_manager_) {
1099 editor_manager_->ShowProjectManagement();
1100 }
1101}
1102
1103void MenuOrchestrator::OnShowProjectFileEditor() {
1104 // Open the project file editor with the current project file
1105 if (editor_manager_) {
1106 editor_manager_->ShowProjectFileEditor();
1107 }
1108}
1109
1110// Edit menu actions - delegate to current editor
1111void MenuOrchestrator::OnUndo() {
1112 if (editor_manager_) {
1113 auto* current_editor = editor_manager_->GetCurrentEditor();
1114 if (current_editor) {
1115 // Capture description before undo moves the action to the redo stack
1116 std::string desc = current_editor->GetUndoDescription();
1117 auto status = current_editor->Undo();
1118 if (status.ok()) {
1119 if (!desc.empty()) {
1120 toast_manager_.Show(absl::StrFormat("Undid: %s", desc),
1121 ToastType::kInfo, 2.0f);
1122 }
1123 } else {
1124 toast_manager_.Show(
1125 absl::StrFormat("Undo failed: %s", status.message()),
1126 ToastType::kError);
1127 }
1128 }
1129 }
1130}
1131
1132void MenuOrchestrator::OnRedo() {
1133 if (editor_manager_) {
1134 auto* current_editor = editor_manager_->GetCurrentEditor();
1135 if (current_editor) {
1136 // Capture description before redo moves the action to the undo stack
1137 std::string desc = current_editor->GetRedoDescription();
1138 auto status = current_editor->Redo();
1139 if (status.ok()) {
1140 if (!desc.empty()) {
1141 toast_manager_.Show(absl::StrFormat("Redid: %s", desc),
1142 ToastType::kInfo, 2.0f);
1143 }
1144 } else {
1145 toast_manager_.Show(
1146 absl::StrFormat("Redo failed: %s", status.message()),
1147 ToastType::kError);
1148 }
1149 }
1150 }
1151}
1152
1153void MenuOrchestrator::OnCut() {
1154 if (editor_manager_) {
1155 auto* current_editor = editor_manager_->GetCurrentEditor();
1156 if (current_editor) {
1157 auto status = current_editor->Cut();
1158 if (!status.ok()) {
1159 toast_manager_.Show(absl::StrFormat("Cut failed: %s", status.message()),
1160 ToastType::kError);
1161 }
1162 }
1163 }
1164}
1165
1166void MenuOrchestrator::OnCopy() {
1167 if (editor_manager_) {
1168 auto* current_editor = editor_manager_->GetCurrentEditor();
1169 if (current_editor) {
1170 auto status = current_editor->Copy();
1171 if (!status.ok()) {
1172 toast_manager_.Show(
1173 absl::StrFormat("Copy failed: %s", status.message()),
1174 ToastType::kError);
1175 }
1176 }
1177 }
1178}
1179
1180void MenuOrchestrator::OnPaste() {
1181 if (editor_manager_) {
1182 auto* current_editor = editor_manager_->GetCurrentEditor();
1183 if (current_editor) {
1184 auto status = current_editor->Paste();
1185 if (!status.ok()) {
1186 toast_manager_.Show(
1187 absl::StrFormat("Paste failed: %s", status.message()),
1188 ToastType::kError);
1189 }
1190 }
1191 }
1192}
1193
1194void MenuOrchestrator::OnFind() {
1195 if (editor_manager_) {
1196 auto* current_editor = editor_manager_->GetCurrentEditor();
1197 if (current_editor) {
1198 auto status = current_editor->Find();
1199 if (!status.ok()) {
1200 toast_manager_.Show(
1201 absl::StrFormat("Find failed: %s", status.message()),
1202 ToastType::kError);
1203 }
1204 }
1205 }
1206}
1207
1208// Editor-specific menu actions
1209void MenuOrchestrator::OnSwitchToEditor(EditorType editor_type) {
1210 // Delegate to EditorManager which manages editor switching
1211 if (editor_manager_) {
1212 editor_manager_->SwitchToEditor(editor_type);
1213 }
1214}
1215
1216void MenuOrchestrator::OnShowEditorSelection() {
1217 // Delegate to UICoordinator for editor selection dialog display
1218 if (editor_manager_) {
1219 if (auto* ui = editor_manager_->ui_coordinator()) {
1220 ui->ShowEditorSelection();
1221 }
1222 }
1223}
1224
1225void MenuOrchestrator::OnShowDisplaySettings() {
1226 popup_manager_.Show(PopupID::kDisplaySettings);
1227}
1228
1229void MenuOrchestrator::OnShowHexEditor() {
1230 // Show hex editor window via WorkspaceWindowManager
1231 if (editor_manager_) {
1232 editor_manager_->window_manager().OpenWindow(
1233 editor_manager_->GetCurrentSessionId(), "Hex Editor");
1234 }
1235}
1236
1237void MenuOrchestrator::OnShowPanelBrowser() {
1238 if (editor_manager_) {
1239 if (auto* ui = editor_manager_->ui_coordinator()) {
1240 ui->SetWindowBrowserVisible(true);
1241 }
1242 }
1243}
1244
1245void MenuOrchestrator::OnShowPanelFinder() {
1246 if (editor_manager_) {
1247 if (auto* ui = editor_manager_->ui_coordinator()) {
1248 ui->ShowPanelFinder();
1249 }
1250 }
1251}
1252
1253void MenuOrchestrator::OnShowWelcomeScreen() {
1254 if (editor_manager_) {
1255 if (auto* ui = editor_manager_->ui_coordinator()) {
1256 ui->SetWelcomeScreenVisible(true);
1257 }
1258 }
1259}
1260
1261#ifdef YAZE_BUILD_AGENT_UI
1262void MenuOrchestrator::OnShowAIAgent() {
1263 if (editor_manager_) {
1264 if (auto* ui = editor_manager_->ui_coordinator()) {
1265 ui->SetAIAgentVisible(true);
1266 }
1267 }
1268}
1269
1270void MenuOrchestrator::OnShowProposalDrawer() {
1271 if (editor_manager_) {
1272 if (auto* ui = editor_manager_->ui_coordinator()) {
1273 ui->SetProposalDrawerVisible(true);
1274 }
1275 }
1276}
1277#endif
1278
1279// Session management menu actions
1280void MenuOrchestrator::OnCreateNewSession() {
1281 session_coordinator_.CreateNewSession();
1282}
1283
1284void MenuOrchestrator::OnDuplicateCurrentSession() {
1285 session_coordinator_.DuplicateCurrentSession();
1286}
1287
1288void MenuOrchestrator::OnCloseCurrentSession() {
1289 session_coordinator_.CloseCurrentSession();
1290}
1291
1292void MenuOrchestrator::OnShowSessionSwitcher() {
1293 // Delegate to UICoordinator for session switcher UI
1294 if (editor_manager_) {
1295 if (auto* ui = editor_manager_->ui_coordinator()) {
1296 ui->ShowSessionSwitcher();
1297 }
1298 }
1299}
1300
1301void MenuOrchestrator::OnShowSessionManager() {
1302 popup_manager_.Show(PopupID::kSessionManager);
1303}
1304
1305// Window management menu actions
1306void MenuOrchestrator::OnShowAllWindows() {
1307 // Delegate to EditorManager
1308 if (editor_manager_) {
1309 if (auto* ui = editor_manager_->ui_coordinator()) {
1310 ui->ShowAllWindows();
1311 }
1312 }
1313}
1314
1315void MenuOrchestrator::OnHideAllWindows() {
1316 // Delegate to EditorManager
1317 if (editor_manager_) {
1318 editor_manager_->HideAllWindows();
1319 }
1320}
1321
1322void MenuOrchestrator::OnResetWorkspaceLayout() {
1323 // Queue as deferred action to avoid modifying ImGui state during menu rendering
1324 if (editor_manager_) {
1325 editor_manager_->QueueDeferredAction([this]() {
1326 editor_manager_->ResetWorkspaceLayout();
1327 toast_manager_.Show("Layout reset to default", ToastType::kInfo);
1328 });
1329 }
1330}
1331
1332void MenuOrchestrator::OnSaveWorkspaceLayout() {
1333 // Delegate to EditorManager
1334 if (editor_manager_) {
1335 editor_manager_->SaveWorkspaceLayout();
1336 }
1337}
1338
1339void MenuOrchestrator::OnLoadWorkspaceLayout() {
1340 // Delegate to EditorManager
1341 if (editor_manager_) {
1342 editor_manager_->LoadWorkspaceLayout();
1343 }
1344}
1345
1346void MenuOrchestrator::OnShowLayoutPresets() {
1347 popup_manager_.Show(PopupID::kLayoutPresets);
1348}
1349
1350void MenuOrchestrator::OnLoadDeveloperLayout() {
1351 if (editor_manager_) {
1352 editor_manager_->ApplyLayoutPreset("Developer");
1353 }
1354}
1355
1356void MenuOrchestrator::OnLoadDesignerLayout() {
1357 if (editor_manager_) {
1358 editor_manager_->ApplyLayoutPreset("Designer");
1359 }
1360}
1361
1362void MenuOrchestrator::OnLoadModderLayout() {
1363 if (editor_manager_) {
1364 editor_manager_->ApplyLayoutPreset("Modder");
1365 }
1366}
1367
1368// Tool menu actions
1369void MenuOrchestrator::OnShowGlobalSearch() {
1370 if (editor_manager_) {
1371 if (auto* ui = editor_manager_->ui_coordinator()) {
1372 ui->ShowGlobalSearch();
1373 }
1374 }
1375}
1376
1377void MenuOrchestrator::OnShowCommandPalette() {
1378 if (editor_manager_) {
1379 if (auto* ui = editor_manager_->ui_coordinator()) {
1380 ui->ShowCommandPalette();
1381 }
1382 }
1383}
1384
1385void MenuOrchestrator::OnShowPerformanceDashboard() {
1386 if (editor_manager_) {
1387 if (auto* ui = editor_manager_->ui_coordinator()) {
1388 ui->SetPerformanceDashboardVisible(true);
1389 }
1390 }
1391}
1392
1393void MenuOrchestrator::OnShowImGuiDemo() {
1394 if (editor_manager_) {
1395 editor_manager_->ShowImGuiDemo();
1396 }
1397}
1398
1399void MenuOrchestrator::OnShowImGuiMetrics() {
1400 if (editor_manager_) {
1401 editor_manager_->ShowImGuiMetrics();
1402 }
1403}
1404
1405void MenuOrchestrator::OnShowMemoryEditor() {
1406 if (editor_manager_) {
1407 editor_manager_->window_manager().OpenWindow(
1408 editor_manager_->GetCurrentSessionId(), "Memory Editor");
1409 }
1410}
1411
1412void MenuOrchestrator::OnShowResourceLabelManager() {
1413 if (editor_manager_) {
1414 if (auto* ui = editor_manager_->ui_coordinator()) {
1415 ui->SetResourceLabelManagerVisible(true);
1416 }
1417 }
1418}
1419
1420#ifdef YAZE_ENABLE_TESTING
1421void MenuOrchestrator::OnShowTestDashboard() {
1422 if (editor_manager_) {
1423 editor_manager_->ShowTestDashboard();
1424 }
1425}
1426
1427void MenuOrchestrator::OnRunAllTests() {
1428 toast_manager_.Show("Running all tests...", ToastType::kInfo);
1429 // TODO: Implement test runner integration
1430}
1431
1432void MenuOrchestrator::OnRunUnitTests() {
1433 toast_manager_.Show("Running unit tests...", ToastType::kInfo);
1434 // TODO: Implement unit test runner
1435}
1436
1437void MenuOrchestrator::OnRunIntegrationTests() {
1438 toast_manager_.Show("Running integration tests...", ToastType::kInfo);
1439 // TODO: Implement integration test runner
1440}
1441
1442void MenuOrchestrator::OnRunE2ETests() {
1443 toast_manager_.Show(
1444 "E2E runner is not wired in-app yet. Use scripts/agents/run-tests.sh or "
1445 "z3ed test-run.",
1446 ToastType::kWarning);
1447}
1448#endif
1449
1450#ifdef YAZE_WITH_GRPC
1451void MenuOrchestrator::OnStartCollaboration() {
1452 toast_manager_.Show(
1453 "Collaboration session start is not wired yet. Run yaze-server and use "
1454 "the web client for live sync.",
1455 ToastType::kWarning);
1456}
1457
1458void MenuOrchestrator::OnJoinCollaboration() {
1459 toast_manager_.Show(
1460 "Join collaboration is not wired yet. Use the web client + yaze-server.",
1461 ToastType::kWarning);
1462}
1463
1464void MenuOrchestrator::OnShowNetworkStatus() {
1465 toast_manager_.Show("Network status panel is not implemented yet.",
1466 ToastType::kWarning);
1467}
1468#endif
1469
1470// Help menu actions
1471void MenuOrchestrator::OnShowAbout() {
1472 popup_manager_.Show(PopupID::kAbout);
1473}
1474
1475void MenuOrchestrator::OnShowGettingStarted() {
1476 popup_manager_.Show(PopupID::kGettingStarted);
1477}
1478
1479void MenuOrchestrator::OnShowBuildInstructions() {
1480 popup_manager_.Show(PopupID::kBuildInstructions);
1481}
1482
1483void MenuOrchestrator::OnShowCLIUsage() {
1484 popup_manager_.Show(PopupID::kCLIUsage);
1485}
1486
1487void MenuOrchestrator::OnShowTroubleshooting() {
1488 popup_manager_.Show(PopupID::kTroubleshooting);
1489}
1490
1491void MenuOrchestrator::OnShowContributing() {
1492 popup_manager_.Show(PopupID::kContributing);
1493}
1494
1495void MenuOrchestrator::OnShowWhatsNew() {
1496 popup_manager_.Show(PopupID::kWhatsNew);
1497}
1498
1499void MenuOrchestrator::OnShowSupportedFeatures() {
1500 popup_manager_.Show(PopupID::kSupportedFeatures);
1501}
1502
1503// Additional File menu actions
1504void MenuOrchestrator::OnShowRomInfo() {
1505 popup_manager_.Show(PopupID::kRomInfo);
1506}
1507
1508void MenuOrchestrator::OnCreateBackup() {
1509 if (editor_manager_) {
1510 auto status = rom_manager_.CreateBackup(editor_manager_->GetCurrentRom());
1511 if (status.ok()) {
1512 toast_manager_.Show("Backup created successfully", ToastType::kSuccess);
1513 } else {
1514 toast_manager_.Show(
1515 absl::StrFormat("Backup failed: %s", status.message()),
1516 ToastType::kError);
1517 }
1518 }
1519}
1520
1521void MenuOrchestrator::OnValidateRom() {
1522 if (editor_manager_) {
1523 auto status = rom_manager_.ValidateRom(editor_manager_->GetCurrentRom());
1524 if (status.ok()) {
1525 toast_manager_.Show("ROM validation passed", ToastType::kSuccess);
1526 } else {
1527 toast_manager_.Show(
1528 absl::StrFormat("ROM validation failed: %s", status.message()),
1529 ToastType::kError);
1530 }
1531 }
1532}
1533
1534void MenuOrchestrator::OnShowSettings() {
1535 // Activate settings editor
1536 if (editor_manager_) {
1537 editor_manager_->SwitchToEditor(EditorType::kSettings);
1538 }
1539}
1540
1541void MenuOrchestrator::OnQuit() {
1542 if (editor_manager_) {
1543 editor_manager_->Quit();
1544 }
1545}
1546
1547// Menu item validation helpers
1548bool MenuOrchestrator::CanSaveRom() const {
1549 auto* rom = editor_manager_->GetCurrentRom();
1550 return rom ? rom_manager_.IsRomLoaded(rom) : false;
1551}
1552
1553bool MenuOrchestrator::CanSaveProject() const {
1554 return project_manager_.HasActiveProject();
1555}
1556
1557bool MenuOrchestrator::HasActiveRom() const {
1558 auto* rom = editor_manager_->GetCurrentRom();
1559 return rom ? rom_manager_.IsRomLoaded(rom) : false;
1560}
1561
1562bool MenuOrchestrator::HasActiveProject() const {
1563 return project_manager_.HasActiveProject();
1564}
1565
1566bool MenuOrchestrator::HasProjectFile() const {
1567 // Check if EditorManager has a project with a valid filepath
1568 // This is separate from HasActiveProject which checks ProjectManager
1569 const auto* project =
1570 editor_manager_ ? editor_manager_->GetCurrentProject() : nullptr;
1571 return project && !project->filepath.empty();
1572}
1573
1574bool MenuOrchestrator::HasCurrentEditor() const {
1575 return editor_manager_ && editor_manager_->GetCurrentEditor() != nullptr;
1576}
1577
1578bool MenuOrchestrator::HasMultipleSessions() const {
1579 return session_coordinator_.HasMultipleSessions();
1580}
1581
1582// Menu item text generation
1583std::string MenuOrchestrator::GetRomFilename() const {
1584 auto* rom = editor_manager_->GetCurrentRom();
1585 return rom ? rom_manager_.GetRomFilename(rom) : "";
1586}
1587
1588std::string MenuOrchestrator::GetProjectName() const {
1589 return project_manager_.GetProjectName();
1590}
1591
1592std::string MenuOrchestrator::GetCurrentEditorName() const {
1593 // TODO: Get current editor name
1594 return "Unknown Editor";
1595}
1596
1597// Shortcut key management
1598std::string MenuOrchestrator::GetShortcutForAction(
1599 const std::string& action) const {
1600 // TODO: Implement shortcut mapping
1601 return "";
1602}
1603
1604void MenuOrchestrator::RegisterGlobalShortcuts() {
1605 // TODO: Register global keyboard shortcuts
1606}
1607
1608// ============================================================================
1609// Debug Menu Actions
1610// ============================================================================
1611
1612void MenuOrchestrator::OnRunDataIntegrityCheck() {
1613#ifdef YAZE_ENABLE_TESTING
1614 if (!editor_manager_)
1615 return;
1616 auto* rom = editor_manager_->GetCurrentRom();
1617 if (!rom || !rom->is_loaded())
1618 return;
1619
1620 toast_manager_.Show("Running ROM integrity tests...", ToastType::kInfo);
1621 // This would integrate with the test system in master
1622 // For now, just show a placeholder
1623 toast_manager_.Show("Data integrity check completed", ToastType::kSuccess,
1624 3.0f);
1625#else
1626 toast_manager_.Show("Testing not enabled in this build", ToastType::kWarning);
1627#endif
1628}
1629
1630void MenuOrchestrator::OnTestSaveLoad() {
1631#ifdef YAZE_ENABLE_TESTING
1632 if (!editor_manager_)
1633 return;
1634 auto* rom = editor_manager_->GetCurrentRom();
1635 if (!rom || !rom->is_loaded())
1636 return;
1637
1638 toast_manager_.Show("Running ROM save/load tests...", ToastType::kInfo);
1639 // This would integrate with the test system in master
1640 toast_manager_.Show("Save/load test completed", ToastType::kSuccess, 3.0f);
1641#else
1642 toast_manager_.Show("Testing not enabled in this build", ToastType::kWarning);
1643#endif
1644}
1645
1646void MenuOrchestrator::OnCheckRomVersion() {
1647 if (!editor_manager_)
1648 return;
1649 auto* rom = editor_manager_->GetCurrentRom();
1650 if (!rom || !rom->is_loaded())
1651 return;
1652
1653 // Check ZSCustomOverworld version
1654 uint8_t version = (*rom)[zelda3::OverworldCustomASMHasBeenApplied];
1655 std::string version_str =
1656 (version == 0xFF) ? "Vanilla" : absl::StrFormat("v%d", version);
1657
1658 toast_manager_.Show(
1659 absl::StrFormat("ROM: %s | ZSCustomOverworld: %s", rom->title().c_str(),
1660 version_str.c_str()),
1661 ToastType::kInfo, 5.0f);
1662}
1663
1664void MenuOrchestrator::OnUpgradeRom() {
1665 if (!editor_manager_)
1666 return;
1667 auto* rom = editor_manager_->GetCurrentRom();
1668 if (!rom || !rom->is_loaded())
1669 return;
1670
1671 toast_manager_.Show("Use Overworld Editor to upgrade ROM version",
1672 ToastType::kInfo, 4.0f);
1673}
1674
1675void MenuOrchestrator::OnToggleCustomLoading() {
1676 auto& flags = core::FeatureFlags::get();
1677 flags.overworld.kLoadCustomOverworld = !flags.overworld.kLoadCustomOverworld;
1678
1679 toast_manager_.Show(
1680 absl::StrFormat(
1681 "Custom Overworld Loading: %s",
1682 flags.overworld.kLoadCustomOverworld ? "Enabled" : "Disabled"),
1683 ToastType::kInfo);
1684}
1685
1686void MenuOrchestrator::OnToggleAsarPatch() {
1687 if (!editor_manager_)
1688 return;
1689 auto* rom = editor_manager_->GetCurrentRom();
1690 if (!rom || !rom->is_loaded())
1691 return;
1692
1693 auto& flags = core::FeatureFlags::get();
1694 flags.overworld.kApplyZSCustomOverworldASM =
1695 !flags.overworld.kApplyZSCustomOverworldASM;
1696
1697 toast_manager_.Show(
1698 absl::StrFormat(
1699 "ZSCustomOverworld ASM Application: %s",
1700 flags.overworld.kApplyZSCustomOverworldASM ? "Enabled" : "Disabled"),
1701 ToastType::kInfo);
1702}
1703
1704void MenuOrchestrator::OnLoadAsmFile() {
1705 toast_manager_.Show("ASM file loading not yet implemented",
1706 ToastType::kWarning);
1707}
1708
1709void MenuOrchestrator::OnShowAssemblyEditor() {
1710 if (editor_manager_) {
1711 editor_manager_->SwitchToEditor(EditorType::kAssembly);
1712 }
1713}
1714
1715void MenuOrchestrator::OnExportBpsPatch() {
1716 if (!editor_manager_)
1717 return;
1718 auto* rom = editor_manager_->GetCurrentRom();
1719 if (!rom || !rom->is_loaded())
1720 return;
1721
1722 // Ask user to select the original/clean ROM to diff against
1723 auto options = util::MakeRomFileDialogOptions();
1724 std::string original_path =
1726 if (original_path.empty()) {
1727 return; // User cancelled
1728 }
1729
1730 // Load the original ROM
1731 Rom original_rom;
1732 auto load_status = original_rom.LoadFromFile(original_path);
1733 if (!load_status.ok()) {
1734 toast_manager_.Show(absl::StrFormat("Failed to load original ROM: %s",
1735 load_status.message()),
1736 ToastType::kError);
1737 return;
1738 }
1739
1740 // Generate BPS patch
1741 std::vector<uint8_t> patch_data;
1742 auto create_status =
1743 util::CreateBpsPatch(original_rom.vector(), rom->vector(), patch_data);
1744 if (!create_status.ok()) {
1745 toast_manager_.Show(absl::StrFormat("Failed to create BPS patch: %s",
1746 create_status.message()),
1747 ToastType::kError);
1748 return;
1749 }
1750
1751 // Ask user where to save the patch
1752 std::string default_name = rom->short_name() + ".bps";
1753 std::string save_path =
1755 if (save_path.empty()) {
1756 return; // User cancelled
1757 }
1758
1759 // Ensure .bps extension
1760 if (save_path.size() < 4 ||
1761 save_path.substr(save_path.size() - 4) != ".bps") {
1762 save_path += ".bps";
1763 }
1764
1765 // Write the patch file
1766 std::ofstream file(save_path, std::ios::binary);
1767 if (!file.is_open()) {
1768 toast_manager_.Show(
1769 absl::StrFormat("Failed to open file for writing: %s", save_path),
1770 ToastType::kError);
1771 return;
1772 }
1773
1774 file.write(reinterpret_cast<const char*>(patch_data.data()),
1775 patch_data.size());
1776 file.close();
1777
1778 if (file.fail()) {
1779 toast_manager_.Show(
1780 absl::StrFormat("Failed to write patch file: %s", save_path),
1781 ToastType::kError);
1782 return;
1783 }
1784
1785 toast_manager_.Show(absl::StrFormat("BPS patch exported: %s (%zu bytes)",
1786 save_path, patch_data.size()),
1787 ToastType::kSuccess);
1788}
1789
1790void MenuOrchestrator::OnApplyBpsPatch() {
1791 if (!editor_manager_)
1792 return;
1793 auto* rom = editor_manager_->GetCurrentRom();
1794 if (!rom || !rom->is_loaded())
1795 return;
1796
1797 // Ask user to select a .bps file
1799 options.filters.push_back({"BPS Patch", "bps"});
1800 std::string patch_path = util::FileDialogWrapper::ShowOpenFileDialog(options);
1801 if (patch_path.empty()) {
1802 return; // User cancelled
1803 }
1804
1805 // Read the patch file
1806 std::ifstream file(patch_path, std::ios::binary);
1807 if (!file.is_open()) {
1808 toast_manager_.Show(
1809 absl::StrFormat("Failed to open patch file: %s", patch_path),
1810 ToastType::kError);
1811 return;
1812 }
1813
1814 std::vector<uint8_t> patch_data((std::istreambuf_iterator<char>(file)),
1815 std::istreambuf_iterator<char>());
1816 file.close();
1817
1818 if (patch_data.empty()) {
1819 toast_manager_.Show("Patch file is empty", ToastType::kError);
1820 return;
1821 }
1822
1823 // Apply the patch
1824 std::vector<uint8_t> patched_rom;
1825 auto apply_status =
1826 util::ApplyBpsPatch(rom->vector(), patch_data, patched_rom);
1827 if (!apply_status.ok()) {
1828 toast_manager_.Show(absl::StrFormat("Failed to apply BPS patch: %s",
1829 apply_status.message()),
1830 ToastType::kError);
1831 return;
1832 }
1833
1834 // Load the patched data into the ROM
1835 auto load_status = rom->LoadFromData(patched_rom);
1836 if (!load_status.ok()) {
1837 toast_manager_.Show(absl::StrFormat("Failed to load patched ROM data: %s",
1838 load_status.message()),
1839 ToastType::kError);
1840 return;
1841 }
1842
1843 rom->set_dirty(true);
1844 toast_manager_.Show("BPS patch applied successfully", ToastType::kSuccess);
1845}
1846
1847} // namespace editor
1848} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:28
absl::Status LoadFromFile(const std::string &filename, const LoadOptions &options=LoadOptions::Defaults())
Definition rom.cc:155
void set_dirty(bool dirty)
Definition rom.h:134
const auto & vector() const
Definition rom.h:143
absl::Status LoadFromData(const std::vector< uint8_t > &data, const LoadOptions &options=LoadOptions::Defaults())
Definition rom.cc:255
auto short_name() const
Definition rom.h:147
bool is_loaded() const
Definition rom.h:132
auto title() const
Definition rom.h:137
static Flags & get()
Definition features.h:118
The EditorManager controls the main editor window and manages the various editor classes.
bool SaveLayoutSnapshotAs(const std::string &name)
bool ApplyLayoutProfile(const std::string &profile_id)
Manages editor types, categories, and lifecycle.
virtual absl::Status Cut()=0
virtual absl::Status Copy()=0
virtual absl::Status Redo()=0
virtual std::string GetRedoDescription() const
Definition editor.h:277
virtual absl::Status Find()=0
virtual absl::Status Paste()=0
virtual absl::Status Undo()=0
virtual std::string GetUndoDescription() const
Definition editor.h:274
Fluent interface for building ImGui menus with icons.
MenuBuilder & Item(const char *label, const char *icon, Callback callback, const char *shortcut=nullptr, EnabledCheck enabled=nullptr, EnabledCheck checked=nullptr)
Add a menu item.
MenuBuilder & CustomMenu(const char *label, Callback draw_callback)
Add a custom menu with a callback for drawing dynamic content.
void Draw()
Draw the menu bar (call in main menu bar)
std::function< bool()> EnabledCheck
MenuBuilder & BeginMenu(const char *label, const char *icon=nullptr)
Begin a top-level menu.
MenuBuilder & Separator()
Add a separator.
MenuBuilder & EndMenu()
End the current menu/submenu.
MenuBuilder & BeginSubMenu(const char *label, const char *icon=nullptr, EnabledCheck enabled=nullptr)
Begin a submenu.
SessionCoordinator & session_coordinator_
WorkspaceWindowManager * window_manager_
MenuOrchestrator(EditorManager *editor_manager, MenuBuilder &menu_builder, RomFileManager &rom_manager, ProjectManager &project_manager, EditorRegistry &editor_registry, SessionCoordinator &session_coordinator, ToastManager &toast_manager, PopupManager &popup_manager)
void Show(const char *name)
Handles all project file operations with ROM-first workflow.
Handles all ROM file I/O operations.
High-level orchestrator for multi-session UI.
void SetEnabled(bool enabled)
Enable or disable the status bar.
Definition status_bar.h:68
void HideAllWindowsInCategory(size_t session_id, const std::string &category)
std::vector< WindowDescriptor > GetWindowsInCategory(size_t session_id, const std::string &category) const
bool IsWindowOpen(size_t session_id, const std::string &base_window_id) const
bool OpenWindow(size_t session_id, const std::string &base_window_id)
std::vector< std::string > GetAllCategories(size_t session_id) const
bool ToggleWindow(size_t session_id, const std::string &base_window_id)
void ShowAllWindowsInCategory(size_t session_id, const std::string &category)
static std::string ShowSaveFileDialog(const std::string &default_name="", const std::string &default_extension="")
ShowSaveFileDialog opens a save file dialog and returns the selected filepath. Uses global feature fl...
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define ICON_MD_DEVELOPER_MODE
Definition icons.h:549
#define ICON_MD_FOLDER_OPEN
Definition icons.h:813
#define ICON_MD_CONTENT_CUT
Definition icons.h:466
#define ICON_MD_SAVE_ALT
Definition icons.h:1645
#define ICON_MD_VOLUNTEER_ACTIVISM
Definition icons.h:2112
#define ICON_MD_SETTINGS
Definition icons.h:1699
#define ICON_MD_FILE_OPEN
Definition icons.h:747
#define ICON_MD_CHECK_BOX
Definition icons.h:398
#define ICON_MD_EXIT_TO_APP
Definition icons.h:699
#define ICON_MD_VIEW_QUILT
Definition icons.h:2094
#define ICON_MD_APPS
Definition icons.h:168
#define ICON_MD_INFO
Definition icons.h:993
#define ICON_MD_WORKSPACE_PREMIUM
Definition icons.h:2185
#define ICON_MD_BOOKMARKS
Definition icons.h:291
#define ICON_MD_MEMORY
Definition icons.h:1195
#define ICON_MD_STORAGE
Definition icons.h:1865
#define ICON_MD_UPGRADE
Definition icons.h:2047
#define ICON_MD_FOLDER_SPECIAL
Definition icons.h:815
#define ICON_MD_VIEW_LIST
Definition icons.h:2092
#define ICON_MD_SEARCH
Definition icons.h:1673
#define ICON_MD_NEW_RELEASES
Definition icons.h:1291
#define ICON_MD_PLAY_ARROW
Definition icons.h:1479
#define ICON_MD_SWAP_HORIZ
Definition icons.h:1896
#define ICON_MD_SAVE_AS
Definition icons.h:1646
#define ICON_MD_DESIGN_SERVICES
Definition icons.h:541
#define ICON_MD_INTEGRATION_INSTRUCTIONS
Definition icons.h:1008
#define ICON_MD_RESET_TV
Definition icons.h:1601
#define ICON_MD_TUNE
Definition icons.h:2022
#define ICON_MD_REFRESH
Definition icons.h:1572
#define ICON_MD_DIFFERENCE
Definition icons.h:559
#define ICON_MD_MAP
Definition icons.h:1173
#define ICON_MD_CODE
Definition icons.h:434
#define ICON_MD_LABEL
Definition icons.h:1053
#define ICON_MD_REDO
Definition icons.h:1570
#define ICON_MD_SWITCH_ACCOUNT
Definition icons.h:1913
#define ICON_MD_VISIBILITY
Definition icons.h:2101
#define ICON_MD_BUG_REPORT
Definition icons.h:327
#define ICON_MD_SPEED
Definition icons.h:1817
#define ICON_MD_CASTLE
Definition icons.h:380
#define ICON_MD_BUILD_CIRCLE
Definition icons.h:329
#define ICON_MD_MUSIC_NOTE
Definition icons.h:1264
#define ICON_MD_RESTORE
Definition icons.h:1605
#define ICON_MD_CONTENT_PASTE
Definition icons.h:467
#define ICON_MD_HOME
Definition icons.h:953
#define ICON_MD_ROUTE
Definition icons.h:1627
#define ICON_MD_VISIBILITY_OFF
Definition icons.h:2102
#define ICON_MD_DISPLAY_SETTINGS
Definition icons.h:587
#define ICON_MD_BOOKMARK_ADD
Definition icons.h:286
#define ICON_MD_VIEW_COMPACT
Definition icons.h:2085
#define ICON_MD_ADD
Definition icons.h:86
#define ICON_MD_KEYBOARD
Definition icons.h:1028
#define ICON_MD_SCIENCE
Definition icons.h:1656
#define ICON_MD_PLAY_CIRCLE
Definition icons.h:1480
#define ICON_MD_CHECK_CIRCLE
Definition icons.h:400
#define ICON_MD_TERMINAL
Definition icons.h:1951
#define ICON_MD_PREVIEW
Definition icons.h:1512
#define ICON_MD_FLAG
Definition icons.h:784
#define ICON_MD_DESCRIPTION
Definition icons.h:539
#define ICON_MD_BUILD
Definition icons.h:328
#define ICON_MD_HORIZONTAL_RULE
Definition icons.h:960
#define ICON_MD_CREATE_NEW_FOLDER
Definition icons.h:483
#define ICON_MD_DASHBOARD
Definition icons.h:517
#define ICON_MD_SAVE
Definition icons.h:1644
#define ICON_MD_DELETE
Definition icons.h:530
#define ICON_MD_TAB
Definition icons.h:1930
#define ICON_MD_PEOPLE
Definition icons.h:1401
#define ICON_MD_FOLDER
Definition icons.h:809
#define ICON_MD_BACKUP
Definition icons.h:231
#define ICON_MD_CONTENT_COPY
Definition icons.h:465
#define ICON_MD_PUSH_PIN
Definition icons.h:1529
#define ICON_MD_CLOUD
Definition icons.h:423
#define ICON_MD_CLOSE
Definition icons.h:418
#define ICON_MD_ANALYTICS
Definition icons.h:154
#define ICON_MD_HELP
Definition icons.h:933
#define ICON_MD_RESTART_ALT
Definition icons.h:1602
#define ICON_MD_CHECK_BOX_OUTLINE_BLANK
Definition icons.h:399
#define ICON_MD_VIEW_SIDEBAR
Definition icons.h:2095
#define ICON_MD_BOOKMARK_REMOVE
Definition icons.h:290
#define ICON_MD_UNDO
Definition icons.h:2039
#define ICON_MD_SMART_TOY
Definition icons.h:1781
#define ICON_MD_GROUP_ADD
Definition icons.h:899
#define SHORTCUT_CTRL_SHIFT(key)
#define SHORTCUT_CTRL(key)
constexpr const char * kSaveScope
constexpr const char * kRomBackups
absl::Status ApplyBpsPatch(const std::vector< uint8_t > &source, const std::vector< uint8_t > &patch, std::vector< uint8_t > &output)
Definition bps.cc:75
absl::Status CreateBpsPatch(const std::vector< uint8_t > &source, const std::vector< uint8_t > &target, std::vector< uint8_t > &patch)
Definition bps.cc:228
FileDialogOptions MakeRomFileDialogOptions(bool include_all_files)
Definition file_util.cc:87
constexpr int OverworldCustomASMHasBeenApplied
Definition common.h:89
std::vector< FileDialogFilter > filters
Definition file_util.h:17