9#include "absl/strings/match.h"
10#include "absl/strings/str_format.h"
13#include <emscripten.h>
38#include "imgui/imgui.h"
51 : editor_manager_(editor_manager),
52 rom_manager_(rom_manager),
53 project_manager_(project_manager),
54 editor_registry_(editor_registry),
55 panel_manager_(panel_manager),
56 session_coordinator_(session_coordinator),
57 window_delegate_(window_delegate),
58 toast_manager_(toast_manager),
59 popup_manager_(popup_manager),
60 shortcut_manager_(shortcut_manager) {
71 var romInput = document.getElementById(
'rom-input');
83 absl::StrFormat(
"Failed to load ROM: %s", status.message()),
86#if !(defined(__APPLE__) && TARGET_OS_IOS == 1)
101 absl::StrFormat(
"Failed to create project: %s", status.message()),
110 welcome_screen_->SetOpenProjectCallback([
this](
const std::string& filepath) {
115 absl::StrFormat(
"Failed to open project: %s", status.message()),
126#ifdef YAZE_BUILD_AGENT_UI
139 absl::StrFormat(
"Failed to open project: %s", status.message()),
159 if (!project || project->filepath.empty()) {
201 if (!ImGui::GetCurrentContext()) {
205 const ImGuiViewport* viewport = ImGui::GetMainViewport();
210 ImDrawList* bg_draw_list =
211 ImGui::GetBackgroundDrawList(
const_cast<ImGuiViewport*
>(viewport));
214 auto current_theme = theme_manager.GetCurrentTheme();
218 ImVec2 grid_pos = viewport->WorkPos;
219 ImVec2 grid_size = viewport->WorkSize;
220 bg_renderer.RenderDockingBackground(bg_draw_list, grid_pos, grid_size,
221 current_theme.primary);
241#ifdef YAZE_BUILD_AGENT_UI
272 const ImGuiViewport* viewport = ImGui::GetMainViewport();
276 const float width = viewport->WorkSize.x;
277#if defined(__APPLE__) && TARGET_OS_IOS == 1
280 static bool compact_mode =
false;
281 constexpr float kEnterCompactWidth = 900.0f;
282 constexpr float kExitCompactWidth = 940.0f;
284 compact_mode ? (width < kExitCompactWidth) : (width < kEnterCompactWidth);
287 return width < 900.0f;
299 {{ImGuiCol_Button, ImVec4(0, 0, 0, 0)},
305 bool clicked = ImGui::SmallButton(icon);
307 if (tooltip && ImGui::IsItemHovered()) {
308 ImGui::SetTooltip(
"%s", tooltip);
316 const float frame_padding = ImGui::GetStyle().FramePadding.x;
319 return icon_width + frame_padding * 2.0f;
331 const std::string full_version =
334 const float item_spacing = 6.0f;
335 const float padding = 8.0f;
337 auto CalcSmallButtonWidth = [](
const char* label) ->
float {
339 const float frame_padding = ImGui::GetStyle().FramePadding.x;
340 const float text_w = ImGui::CalcTextSize(label).x;
341 return text_w + frame_padding * 2.0f;
345 const ImGuiViewport* viewport = ImGui::GetMainViewport();
346 const float true_viewport_right = viewport->WorkPos.x + viewport->WorkSize.x;
350 const bool has_panel_toggles =
352 float panel_buttons_width = 0.0f;
353 if (has_panel_toggles) {
354 const char* kIcons[] = {
361 constexpr size_t kIconCount =
sizeof(kIcons) /
sizeof(kIcons[0]);
363 for (
size_t i = 0; i < kIconCount; ++i) {
364 panel_buttons_width += CalcSmallButtonWidth(kIcons[i]);
365 if (i + 1 < kIconCount) {
366 panel_buttons_width += item_spacing;
373 float panel_region_width = panel_buttons_width;
376 panel_region_width +=
381 float panel_screen_x = true_viewport_right - panel_region_width;
389 const float window_width = ImGui::GetWindowWidth();
390 const float window_screen_x = ImGui::GetWindowPos().x;
391 const float menu_items_end = ImGui::GetCursorPosX() + 16.0f;
394 float panel_local_x = panel_screen_x - window_screen_x;
396 std::min(window_width - padding, panel_local_x - item_spacing);
400 current_rom && current_rom->is_loaded() && current_rom->dirty();
403 float version_width = ImGui::CalcTextSize(full_version.c_str()).x;
408 const float available_width = region_end - menu_items_end - padding;
418 (required_width + version_width + item_spacing) <= available_width;
420 required_width += version_width + item_spacing;
425 has_multiple_sessions &&
426 (required_width + session_width + item_spacing) <= available_width;
428 required_width += session_width + item_spacing;
433 has_dirty_rom && (required_width + dirty_width) <= available_width;
435 required_width += dirty_width;
439 float start_pos = std::max(menu_items_end, region_end - required_width);
444 ImGui::SameLine(start_pos);
446 ImVec2(item_spacing, 0.0f));
459 if (ImGui::IsItemHovered()) {
460 ImGui::SetTooltip(
"Unsaved changes: %s",
461 current_rom->short_name().c_str());
474 has_multiple_sessions);
479 if (has_panel_toggles) {
481 float menu_bar_y = ImGui::GetCursorScreenPos().y;
484 ImGui::SetCursorScreenPos(ImVec2(panel_screen_x, menu_bar_y));
494 "Hide menu bar (Alt to restore)")) {
507 ImGuiWindowFlags flags =
508 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
509 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
510 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize |
511 ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoSavedSettings;
513 ImGui::SetNextWindowPos(ImVec2(8, 8));
514 ImGui::SetNextWindowBgAlpha(0.7f);
516 if (ImGui::Begin(
"##MenuBarRestore",
nullptr, flags)) {
527 if (ImGui::IsItemHovered()) {
528 ImGui::SetTooltip(
"Show menu bar (Alt)");
534 if (ImGui::IsKeyPressed(ImGuiKey_LeftAlt) ||
535 ImGui::IsKeyPressed(ImGuiKey_RightAlt)) {
542 bool has_multiple_sessions) {
553 ImVec4 bell_text_color = (unread > 0 || is_active)
557 {{ImGuiCol_Text, bell_text_color},
558 {ImGuiCol_Button, ImVec4(0, 0, 0, 0)},
571 if (ImGui::IsItemHovered()) {
572 ImGui::BeginTooltip();
583 ImGui::TextDisabled(
"Click to open Notifications panel");
586 if (!show_dirty && has_dirty_rom) {
591 current_rom->short_name().c_str());
594 if (!show_session && has_multiple_sessions) {
595 if (!show_dirty && has_dirty_rom) {
614 {{ImGuiCol_Button, ImVec4(0, 0, 0, 0)},
620 ImVec2 button_min = ImGui::GetCursorScreenPos();
623 ImGui::OpenPopup(
"##SessionSwitcherPopup");
626 ImVec2 button_max = ImGui::GetItemRectMax();
628 if (ImGui::IsItemHovered()) {
629 std::string tooltip = current_rom && current_rom->is_loaded()
630 ? current_rom->short_name()
632 ImGui::SetTooltip(
"%s\n%zu sessions open (Ctrl+Tab)", tooltip.c_str(),
637 const float popup_width = 250.0f;
638 const float screen_width = ImGui::GetIO().DisplaySize.x;
639 const float popup_x =
640 std::min(button_min.x, screen_width - popup_width - 10.0f);
642 ImGui::SetNextWindowPos(ImVec2(popup_x, button_max.y + 2.0f),
643 ImGuiCond_Appearing);
646 if (ImGui::BeginPopup(
"##SessionSwitcherPopup")) {
659 Rom* rom = &session->rom;
660 ImGui::PushID(
static_cast<int>(i));
662 bool is_current = (rom == current_rom);
663 std::optional<gui::StyleColorGuard> current_guard;
674 if (ImGui::Selectable(label.c_str(), is_current)) {
710 auto emulator_panels =
712 for (
const auto& panel : emulator_panels) {
713 if (panel.visibility_flag && *panel.visibility_flag) {
723 auto default_panels =
725 for (
const auto& panel_id : default_panels) {
754 "EditorManager is null - cannot check ROM state");
759 LOG_ERROR(
"UICoordinator",
"WelcomeScreen object is null - cannot render");
765 bool rom_is_loaded = current_rom && current_rom->
is_loaded();
826 ImGuiWindowFlags_AlwaysAutoResize);
827 static char preset_name[128] =
"";
828 ImGui::InputText(
"Name", preset_name, IM_ARRAYSIZE(preset_name));
830 if (strlen(preset_name) > 0) {
834 preset_name[0] =
'\0';
840 preset_name[0] =
'\0';
847 ImGuiWindowFlags_AlwaysAutoResize);
853 for (
const auto& name : workspace_manager->workspace_presets()) {
854 if (ImGui::Selectable(name.c_str())) {
860 if (workspace_manager->workspace_presets().empty())
861 ImGui::Text(
"No presets found");
917 const std::string& icon,
919 std::function<
void()> callback,
921 std::optional<gui::StyleColorGuard> disabled_guard;
923 disabled_guard.emplace(std::initializer_list<gui::StyleColorGuard::Entry>{
928 std::string button_text =
929 absl::StrFormat(
"%s %s", icon.c_str(), text.c_str());
930 if (ImGui::Button(button_text.c_str())) {
931 if (enabled && callback) {
939 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
940 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
945 ImGui::SetNextWindowPos(ImVec2(x, y), ImGuiCond_Appearing);
950 ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiCond_FirstUseEver);
962 using namespace ImGui;
965 SetNextWindowPos(GetMainViewport()->GetCenter(), ImGuiCond_Appearing,
967 SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
969 bool show_palette =
true;
970 if (Begin(absl::StrFormat(
"%s Command Palette",
ICON_MD_SEARCH).c_str(),
971 &show_palette, ImGuiWindowFlags_NoCollapse)) {
973 SetNextItemWidth(-100);
974 if (IsWindowAppearing()) {
975 SetKeyboardFocusHere();
979 bool input_changed = InputTextWithHint(
981 absl::StrFormat(
"%s Search commands (fuzzy matching enabled)...",
987 if (Button(absl::StrFormat(
"%s Clear",
ICON_MD_CLEAR).c_str())) {
989 input_changed =
true;
996 struct ScoredCommand {
999 std::string category;
1000 std::string shortcut;
1001 std::function<void()> callback;
1003 std::vector<ScoredCommand> scored_commands;
1006 std::transform(query_lower.begin(), query_lower.end(), query_lower.begin(),
1009 auto score_text = [&query_lower](
const std::string& text) ->
int {
1010 std::string text_lower = text;
1011 std::transform(text_lower.begin(), text_lower.end(), text_lower.begin(),
1014 if (query_lower.empty())
1016 if (text_lower.find(query_lower) == 0)
1018 if (text_lower.find(query_lower) != std::string::npos)
1022 size_t text_idx = 0, query_idx = 0;
1024 while (text_idx < text_lower.length() &&
1025 query_idx < query_lower.length()) {
1026 if (text_lower[text_idx] == query_lower[query_idx]) {
1032 return (query_idx == query_lower.length()) ? score : 0;
1037 int score = score_text(name);
1039 std::string shortcut_text =
1040 shortcut.keys.empty()
1042 : absl::StrFormat(
"(%s)",
PrintShortcut(shortcut.keys).c_str());
1043 scored_commands.push_back(
1044 {score, name,
"Shortcuts", shortcut_text, shortcut.callback});
1050 int score = score_text(entry.name);
1052 score += score_text(entry.category) / 2;
1053 score += score_text(entry.description) / 4;
1056 scored_commands.push_back({score, entry.name, entry.category,
1057 entry.shortcut, entry.callback});
1062 std::sort(scored_commands.begin(), scored_commands.end(),
1063 [](
const auto& a,
const auto& b) { return a.score > b.score; });
1068 absl::StrFormat(
"%s All Commands",
ICON_MD_LIST).c_str())) {
1070 "CommandPaletteTable", 4,
1071 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
1072 ImGuiTableFlags_SizingStretchProp,
1074 TableSetupColumn(
"Command", ImGuiTableColumnFlags_WidthStretch,
1076 TableSetupColumn(
"Category", ImGuiTableColumnFlags_WidthStretch,
1078 TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthStretch,
1080 TableSetupColumn(
"Score", ImGuiTableColumnFlags_WidthStretch, 0.15f);
1083 for (
size_t i = 0; i < scored_commands.size(); ++i) {
1084 const auto& cmd = scored_commands[i];
1089 PushID(
static_cast<int>(i));
1092 if (Selectable(cmd.name.c_str(), is_selected,
1093 ImGuiSelectableFlags_SpanAllColumns)) {
1122 if (BeginTabItem(absl::StrFormat(
"%s Recent",
ICON_MD_HISTORY).c_str())) {
1124 if (recent.empty()) {
1125 Text(
"No recent commands yet.");
1127 for (
const auto& entry : recent) {
1128 if (Selectable(entry.name.c_str())) {
1129 if (entry.callback) {
1140 if (BeginTabItem(absl::StrFormat(
"%s Frequent",
ICON_MD_STAR).c_str())) {
1142 if (frequent.empty()) {
1143 Text(
"No frequently used commands yet.");
1145 for (
const auto& entry : frequent) {
1146 if (Selectable(absl::StrFormat(
"%s (%d uses)", entry.name,
1149 if (entry.callback) {
1165 Text(
"%s %zu commands | Score: fuzzy match",
ICON_MD_INFO,
1166 scored_commands.size());
1174 if (!show_palette) {
1178 if (config_dir.ok()) {
1179 std::filesystem::path history_file = *config_dir /
"command_history.json";
1189 using namespace ImGui;
1193 const ImGuiViewport* viewport = GetMainViewport();
1194 ImDrawList* bg_list = GetBackgroundDrawList();
1195 bg_list->AddRectFilled(viewport->WorkPos,
1196 ImVec2(viewport->WorkPos.x + viewport->WorkSize.x,
1197 viewport->WorkPos.y + viewport->WorkSize.y),
1198 IM_COL32(0, 0, 0, 100));
1200 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Appearing,
1201 ImVec2(0.5f, 0.3f));
1204 ImVec2(viewport->WorkSize.x * 0.95f, viewport->WorkSize.y * 0.70f),
1205 ImGuiCond_Appearing);
1207 SetNextWindowSize(ImVec2(600, 420), ImGuiCond_Appearing);
1210 const ImGuiWindowFlags finder_flags =
1211 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove |
1212 ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking |
1213 ImGuiWindowFlags_NoSavedSettings;
1218 if (IsWindowAppearing()) {
1219 SetKeyboardFocusHere();
1223 SetNextItemWidth(-1);
1224 bool input_changed = InputTextWithHint(
1228 if (input_changed) {
1236 std::string card_id;
1237 std::string display_name;
1239 std::string category;
1244 std::vector<PanelEntry> entries;
1249 for (
const auto& [card_id, desc] :
1252 if (!query.empty()) {
1259 bool vis = desc.visibility_flag ? *desc.visibility_flag :
false;
1261 entries.push_back({card_id, desc.display_name, desc.icon, desc.category,
1266 if (query.empty()) {
1268 std::sort(entries.begin(), entries.end(),
1269 [
this](
const PanelEntry& lhs,
const PanelEntry& rhs) {
1270 if (lhs.pinned != rhs.pinned)
1271 return lhs.pinned > rhs.pinned;
1272 uint64_t lhs_t = panel_manager_.GetPanelMRUTime(lhs.card_id);
1273 uint64_t rhs_t = panel_manager_.GetPanelMRUTime(rhs.card_id);
1275 return lhs_t > rhs_t;
1276 return lhs.display_name < rhs.display_name;
1280 std::sort(entries.begin(), entries.end(),
1281 [](
const PanelEntry& lhs,
const PanelEntry& rhs) {
1282 if (lhs.score != rhs.score)
1283 return lhs.score > rhs.score;
1284 if (lhs.pinned != rhs.pinned)
1285 return lhs.pinned > rhs.pinned;
1286 return lhs.display_name < rhs.display_name;
1291 if (IsKeyPressed(ImGuiKey_DownArrow) &&
1298 bool enter_pressed = IsKeyPressed(ImGuiKey_Enter);
1303 PushStyleVar(ImGuiStyleVar_ItemSpacing,
1304 ImVec2(GetStyle().ItemSpacing.x, 10.0f));
1308 BeginChild(
"##PanelFinderList");
1309 for (
int i = 0; i < static_cast<int>(entries.size()); ++i) {
1310 const auto& entry = entries[i];
1314 const char* vis_icon =
1318 std::optional<gui::StyleColorGuard> dim_guard;
1319 if (!entry.visible) {
1320 ImVec4 dimmed = GetStyleColorVec4(ImGuiCol_Text);
1322 dim_guard.emplace(ImGuiCol_Text, dimmed);
1326 absl::StrFormat(
"%s %s %s", vis_icon, entry.icon.c_str(),
1327 entry.display_name.c_str());
1331 is_touch ? std::max(GetTextLineHeightWithSpacing(), 44.0f) : 0.0f;
1333 PushID(entry.card_id.c_str());
1334 if (Selectable(label.c_str(), is_selected, ImGuiSelectableFlags_None,
1335 ImVec2(0, item_h))) {
1341 SameLine(GetContentRegionAvail().x - 80);
1342 TextDisabled(
"%s", entry.category.c_str());
1350 if (is_selected && enter_pressed) {
1357 if (is_selected && (IsKeyPressed(ImGuiKey_DownArrow) ||
1358 IsKeyPressed(ImGuiKey_UpArrow))) {
1371 if (!show || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
1393 "Switch to essential cards only",
"", [
this]() {
1401 "Switch to debug and development focused layout",
"", [
this]() {
1409 "Switch to visual and overworld focused layout",
"", [
this]() {
1417 "Switch to comprehensive dungeon editing layout",
"", [
this]() {
1425 "Switch to music and sound editing layout",
"", [
this]() {
1433 [
this](
const std::string& filepath) {
1438 absl::StrFormat(
"Failed to open: %s", status.message()),
1447#ifdef YAZE_WITH_GRPC
1453 "Auto-discover and connect to Mesen2 socket",
"", [
this]() {
1465 "Execute one instruction without entering subroutines",
"F10",
1466 [emu_backend]() { emu_backend->StepOver(); });
1469 "Run until return from current subroutine",
1471 [emu_backend]() { emu_backend->StepOut(); });
1475 "Show collision mask in Mesen2",
"",
1476 [emu_backend]() { emu_backend->SetCollisionOverlay(
true); });
1480 "Hide collision mask in Mesen2",
"",
1481 [emu_backend]() { emu_backend->SetCollisionOverlay(
false); });
1487 if (config_dir.ok()) {
1488 std::filesystem::path history_file = *config_dir /
"command_history.json";
1503 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
1504 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1505 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1507 bool show_search =
true;
1510 &show_search, ImGuiWindowFlags_NoCollapse)) {
1512 ImGui::SetNextItemWidth(-100);
1513 if (ImGui::IsWindowAppearing()) {
1514 ImGui::SetKeyboardFocusHere();
1517 bool input_changed = ImGui::InputTextWithHint(
1519 absl::StrFormat(
"%s Search everything...",
ICON_MD_SEARCH).c_str(),
1523 if (ImGui::Button(absl::StrFormat(
"%s Clear",
ICON_MD_CLEAR).c_str())) {
1525 input_changed =
true;
1533 if (ImGui::BeginTabItem(
1536 auto recent_files = manager.GetRecentFiles();
1538 if (ImGui::BeginTable(
"RecentFilesTable", 3,
1539 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
1540 ImGuiTableFlags_SizingStretchProp)) {
1541 ImGui::TableSetupColumn(
"File", ImGuiTableColumnFlags_WidthStretch,
1543 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthFixed,
1545 ImGui::TableSetupColumn(
"Action", ImGuiTableColumnFlags_WidthFixed,
1547 ImGui::TableHeadersRow();
1549 for (
const auto& file : recent_files) {
1554 ImGui::TableNextRow();
1555 ImGui::TableNextColumn();
1558 ImGui::TableNextColumn();
1560 if (ext ==
"sfc" || ext ==
"smc") {
1561 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s ROM",
1563 }
else if (ext ==
"yaze") {
1564 ImGui::TextColored(ImVec4(0.2f, 0.6f, 0.8f, 1.0f),
"%s Project",
1570 ImGui::TableNextColumn();
1571 ImGui::PushID(file.c_str());
1572 if (ImGui::Button(
"Open")) {
1576 absl::StrCat(
"Failed to open: ", status.message()),
1586 ImGui::EndTabItem();
1591 if (current_rom && current_rom->resource_label()) {
1592 if (ImGui::BeginTabItem(
1596 if (ImGui::BeginTable(
"LabelsTable", 3,
1597 ImGuiTableFlags_ScrollY |
1598 ImGuiTableFlags_RowBg |
1599 ImGuiTableFlags_SizingStretchProp)) {
1600 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthFixed,
1602 ImGui::TableSetupColumn(
"Label", ImGuiTableColumnFlags_WidthStretch,
1604 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch,
1606 ImGui::TableHeadersRow();
1608 for (
const auto& type_pair : labels) {
1609 for (
const auto& kv : type_pair.second) {
1615 ImGui::TableNextRow();
1616 ImGui::TableNextColumn();
1617 ImGui::Text(
"%s", type_pair.first.c_str());
1619 ImGui::TableNextColumn();
1620 if (ImGui::Selectable(kv.first.c_str(),
false,
1621 ImGuiSelectableFlags_SpanAllColumns)) {
1625 ImGui::TableNextColumn();
1626 ImGui::TextDisabled(
"%s", kv.second.c_str());
1632 ImGui::EndTabItem();
1638 if (ImGui::BeginTabItem(
1639 absl::StrFormat(
"%s Sessions",
ICON_MD_TAB).c_str())) {
1640 ImGui::Text(
"Search and switch between active sessions:");
1644 std::string session_info =
1646 if (session_info ==
"[CLOSED SESSION]")
1655 std::optional<gui::StyleColorGuard> current_guard;
1657 current_guard.emplace(ImGuiCol_Text,
1658 ImVec4(0.2f, 0.8f, 0.2f, 1.0f));
1661 if (ImGui::Selectable(absl::StrFormat(
"%s %s %s",
ICON_MD_TAB,
1662 session_info.c_str(),
1663 is_current ?
"(Current)" :
"")
1671 ImGui::EndTabItem();
1680 ImGui::Text(
"%s Global search across all YAZE data",
ICON_MD_INFO);
1699 const char* surface_names[] = {
"Welcome",
"Dashboard",
"Editor"};
1700 LOG_INFO(
"UICoordinator",
"Startup surface: %s -> %s",
1701 surface_names[
static_cast<int>(old_surface)],
1702 surface_names[
static_cast<int>(surface)]);
1764 if (!current_rom || !current_rom->is_loaded()) {
static Application & Instance()
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
project::ResourceLabelManager * resource_label()
void RegisterDungeonRoomCommands(size_t session_id)
Register dungeon room navigation commands.
void RegisterPanelCommands(PanelManager *panel_manager, size_t session_id)
Register all panel toggle commands from PanelManager.
void SaveHistory(const std::string &filepath)
Save command usage history to disk.
void Clear()
Clear all commands.
void AddCommand(const std::string &name, const std::string &category, const std::string &description, const std::string &shortcut, std::function< void()> callback)
void LoadHistory(const std::string &filepath)
Load command usage history from disk.
std::vector< CommandEntry > GetAllCommands() const
Get all registered commands.
void RecordUsage(const std::string &name)
void RegisterEditorCommands(std::function< void(const std::string &)> switch_callback)
Register all editor switch commands.
std::vector< CommandEntry > GetRecentCommands(int limit=10)
void RegisterRecentFilesCommands(std::function< void(const std::string &)> open_callback)
Register commands to open recent files.
std::vector< CommandEntry > GetFrequentCommands(int limit=10)
static int FuzzyScore(const std::string &text, const std::string &query)
The EditorManager controls the main editor window and manages the various editor classes.
void SaveWorkspacePreset(const std::string &name)
float GetRightLayoutOffset() const
void SwitchToEditor(EditorType editor_type, bool force_visible=false, bool from_dialog=false) override
void SwitchToSession(size_t index)
absl::Status OpenProject()
Rom * GetCurrentRom() const override
WorkspaceManager * workspace_manager()
void LoadWorkspacePreset(const std::string &name)
void ShowProjectManagement()
Injects dependencies into all editors within an EditorSet.
absl::Status CreateNewProject(const std::string &template_name="Basic ROM Hack")
void RefreshWorkspacePresets()
void ApplyLayoutPreset(const std::string &preset_name)
absl::Status LoadRom()
Load a ROM file into a new or existing session.
void ShowProjectFileEditor()
project::YazeProject * GetCurrentProject()
absl::Status OpenRomOrProject(const std::string &filename)
float GetLeftLayoutOffset() const
RightPanelManager * right_panel_manager()
Manages editor types, categories, and lifecycle.
static EditorType GetEditorTypeFromCategory(const std::string &category)
static std::vector< std::string > GetDefaultPanels(EditorType type)
Get default visible panels for an editor.
Central registry for all editor cards with session awareness and dependency injection.
void ToggleSidebarVisibility()
void SetSidebarVisible(bool visible, bool notify=true)
std::vector< PanelDescriptor > GetPanelsInCategory(size_t session_id, const std::string &category) const
bool ShowPanel(size_t session_id, const std::string &base_card_id)
bool IsSidebarVisible() const
void MarkPanelRecentlyUsed(const std::string &card_id)
Record that a panel was used (for MRU ordering in sidebar)
bool IsPanelPinned(size_t session_id, const std::string &base_card_id) const
const std::unordered_map< std::string, PanelDescriptor > & GetAllPanelDescriptors() const
Get all panel descriptors (for layout designer, panel browser, etc.)
size_t GetActiveSessionId() const
void HideAllPanelsInCategory(size_t session_id, const std::string &category)
Handles all project file operations with ROM-first workflow.
bool HasActiveProject() const
float GetPanelWidth() const
Get the width of the panel when expanded.
bool IsPanelExpanded() const
Check if any panel is currently expanded (or animating closed)
bool DrawPanelToggleButtons()
Draw toggle buttons for the status cluster.
bool IsPanelActive(PanelType type) const
Check if a specific panel is active.
Handles all ROM file I/O operations.
High-level orchestrator for multi-session UI.
void * GetSession(size_t index) const
bool IsSessionSwitcherVisible() const
size_t GetActiveSessionIndex() const
size_t GetActiveSessionCount() const
void HideSessionSwitcher()
std::string GetSessionDisplayName(size_t index) const
void ShowSessionSwitcher()
size_t GetTotalSessionCount() const
bool IsSessionClosed(size_t index) const
bool HasMultipleSessions() const
const std::unordered_map< std::string, Shortcut > & GetShortcuts() const
size_t GetUnreadCount() const
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
ShortcutManager & shortcut_manager_
void DrawMaterialButton(const std::string &text, const std::string &icon, const ImVec4 &color, std::function< void()> callback, bool enabled=true)
void SetPanelSidebarVisible(bool visible)
bool show_save_workspace_preset_
void SetSessionSwitcherVisible(bool visible)
void SetGlobalSearchVisible(bool visible)
void HidePopup(const std::string &popup_name)
void SetStartupSurface(StartupSurface surface)
SessionCoordinator & session_coordinator_
void InitializeCommandPalette(size_t session_id)
Initialize command palette with all discoverable commands.
void RefreshCommandPalette(size_t session_id)
Refresh command palette commands (call after session switch)
char global_search_query_[256]
UICoordinator(EditorManager *editor_manager, RomFileManager &rom_manager, ProjectManager &project_manager, EditorRegistry &editor_registry, PanelManager &card_registry, SessionCoordinator &session_coordinator, WindowDelegate &window_delegate, ToastManager &toast_manager, PopupManager &popup_manager, ShortcutManager &shortcut_manager)
bool IsEmulatorVisible() const
bool show_proposal_drawer_
void ShowSessionSwitcher()
ToastManager & toast_manager_
void DrawWorkspacePresetDialogs()
void SetEmulatorVisible(bool visible)
char command_palette_query_[256]
bool ShouldShowActivityBar() const
void DrawNotificationBell(bool show_dirty, bool has_dirty_rom, bool show_session, bool has_multiple_sessions)
bool show_command_palette_
bool IsPanelSidebarVisible() const
WindowDelegate & window_delegate_
bool DrawMenuBarIconButton(const char *icon, const char *tooltip, bool is_active=false)
bool ShouldShowDashboard() const
void ShowPopup(const std::string &popup_name)
void TogglePanelSidebar()
bool IsCompactLayout() const
ProjectManager & project_manager_
StartupVisibility welcome_behavior_override_
int panel_finder_selected_idx_
char panel_finder_query_[256]
bool welcome_screen_manually_closed_
StartupVisibility dashboard_behavior_override_
StartupSurface current_startup_surface_
bool command_palette_initialized_
PopupManager & popup_manager_
void DrawWindowManagementUI()
void PositionWindow(const std::string &window_name, float x, float y)
void SetWindowSize(const std::string &window_name, float width, float height)
void ShowDisplaySettings()
void SetWelcomeScreenBehavior(StartupVisibility mode)
bool show_editor_selection_
bool show_welcome_screen_
PanelManager & panel_manager_
EditorManager * editor_manager_
void SetDashboardBehavior(StartupVisibility mode)
bool IsSessionSwitcherVisible() const
CommandPalette command_palette_
std::unique_ptr< WelcomeScreen > welcome_screen_
static float GetMenuBarIconButtonWidth()
bool show_load_workspace_preset_
void DrawMenuBarRestoreButton()
int command_palette_selected_idx_
bool ShouldShowWelcome() const
void DrawCommandPalette()
void CenterWindow(const std::string &window_name)
Low-level window operations with minimal dependencies.
static BackgroundRenderer & Get()
static void EndTableWithTheming()
static bool BeginTableWithTheming(const char *str_id, int columns, ImGuiTableFlags flags=0, const ImVec2 &outer_size=ImVec2(0, 0), float inner_width=0.0f)
static bool IsTouchDevice()
RAII guard for ImGui style colors.
RAII guard for ImGui style vars.
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
static RecentFilesManager & GetInstance()
#define ICON_MD_NOTIFICATIONS
#define ICON_MD_FOLDER_SPECIAL
#define ICON_MD_FULLSCREEN_EXIT
#define ICON_MD_EXPAND_LESS
#define ICON_MD_VIDEOGAME_ASSET
#define ICON_MD_VISIBILITY
#define ICON_MD_MANAGE_SEARCH
#define ICON_MD_VISIBILITY_OFF
#define ICON_MD_DESCRIPTION
#define ICON_MD_HELP_OUTLINE
#define ICON_MD_DASHBOARD
#define ICON_MD_FIBER_MANUAL_RECORD
#define ICON_MD_SMART_TOY
#define LOG_ERROR(category, format,...)
#define LOG_INFO(category, format,...)
StartupSurface
Represents the current startup surface state.
std::string PrintShortcut(const std::vector< ImGuiKey > &keys)
ImVec4 ConvertColorToImVec4(const Color &color)
void ColoredText(const char *text, const ImVec4 &color)
ImVec4 GetSurfaceContainerHighestVec4()
bool BeginThemedTabBar(const char *id, ImGuiTabBarFlags flags)
A stylized tab bar with "Mission Control" branding.
ImVec4 GetTextDisabledVec4()
ImVec4 GetTextSecondaryVec4()
void ColoredTextF(const ImVec4 &color, const char *fmt,...)
ImVec4 GetSurfaceContainerHighVec4()
constexpr ImVec2 kDefaultModalSize
ImVec4 GetOnSurfaceVariantVec4()
ImVec4 GetSurfaceContainerVec4()
std::string GetFileName(const std::string &filename)
Gets the filename from a full path.
std::string GetFileExtension(const std::string &filename)
Gets the file extension from a filename.
StartupVisibility
Tri-state toggle used for startup UI visibility controls.
static constexpr const char * kTools
static constexpr const char * kLayout
Represents a single session, containing a ROM and its associated editors.
std::unordered_map< std::string, std::unordered_map< std::string, std::string > > labels_