9#include "absl/strings/str_format.h"
12#include <emscripten.h>
15#include <TargetConditionals.h>
17#if defined(__APPLE__) && TARGET_OS_IOS == 1
37#include "imgui/imgui.h"
49 : editor_manager_(editor_manager),
50 rom_manager_(rom_manager),
51 project_manager_(project_manager),
52 editor_registry_(editor_registry),
53 panel_manager_(panel_manager),
54 session_coordinator_(session_coordinator),
55 window_delegate_(window_delegate),
56 toast_manager_(toast_manager),
57 popup_manager_(popup_manager),
58 shortcut_manager_(shortcut_manager) {
69 var romInput = document.getElementById(
'rom-input');
81 absl::StrFormat(
"Failed to load ROM: %s", status.message()),
84#if !(defined(__APPLE__) && TARGET_OS_IOS == 1)
99 absl::StrFormat(
"Failed to create project: %s", status.message()),
108 welcome_screen_->SetOpenProjectCallback([
this](
const std::string& filepath) {
113 absl::StrFormat(
"Failed to open project: %s", status.message()),
124#ifdef YAZE_BUILD_AGENT_UI
165 if (ImGui::GetCurrentContext()) {
166 ImDrawList* bg_draw_list = ImGui::GetBackgroundDrawList();
167 const ImGuiViewport* viewport = ImGui::GetMainViewport();
170 auto current_theme = theme_manager.GetCurrentTheme();
174 ImVec2 grid_pos = viewport->WorkPos;
175 ImVec2 grid_size = viewport->WorkSize;
176 bg_renderer.RenderDockingBackground(bg_draw_list, grid_pos, grid_size,
177 current_theme.primary);
204 const ImGuiViewport* viewport = ImGui::GetMainViewport();
208 const float width = viewport->WorkSize.x;
209#if defined(__APPLE__) && TARGET_OS_IOS == 1
212 return width < 900.0f;
221 const ImGuiViewport* viewport = ImGui::GetMainViewport();
226 const ImGuiStyle& style = ImGui::GetStyle();
227 ImVec2 safe = style.DisplaySafeAreaPadding;
228#if defined(__APPLE__) && TARGET_OS_IOS == 1
230 if (safe_area.left != 0.0f || safe_area.right != 0.0f ||
231 safe_area.top != 0.0f || safe_area.bottom != 0.0f) {
232 safe = ImVec2(safe_area.right, safe_area.bottom);
235 const float button_size = std::max(44.0f, ImGui::GetFontSize() * 2.1f);
236 const float padding = style.WindowPadding.x;
237 const ImVec2 pos(viewport->WorkPos.x + viewport->WorkSize.x - safe.x -
238 padding - button_size,
239 viewport->WorkPos.y + viewport->WorkSize.y - safe.y -
240 padding - button_size);
248 ImGui::SetNextWindowPos(pos, ImGuiCond_Always);
249 ImGui::SetNextWindowSize(ImVec2(button_size, button_size), ImGuiCond_Always);
251 ImGuiWindowFlags flags =
252 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
253 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
254 ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing |
255 ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoSavedSettings |
256 ImGuiWindowFlags_NoBackground;
258 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
259 if (ImGui::Begin(
"##MobileNavButton",
nullptr, flags)) {
260 ImGui::PushStyleColor(ImGuiCol_Button, button_color);
261 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hovered);
262 ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_active);
263 ImGui::PushStyleColor(ImGuiCol_Text, button_text);
265 if (ImGui::Button(
ICON_MD_APPS, ImVec2(button_size, button_size))) {
266 ImGui::OpenPopup(
"##MobileNavPopup");
268 if (ImGui::IsItemHovered()) {
269 ImGui::SetTooltip(
"Navigation");
272 ImGui::PopStyleColor(4);
275 ImGui::PopStyleVar();
277 ImGui::PushStyleColor(ImGuiCol_PopupBg,
279 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.0f, 10.0f));
280 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8.0f, 6.0f));
282 if (ImGui::BeginPopup(
"##MobileNavPopup")) {
283 bool has_rom =
false;
286 has_rom = current_rom && current_rom->is_loaded();
294 absl::StrFormat(
"Failed to load ROM: %s", status.message()),
297#if !(defined(__APPLE__) && TARGET_OS_IOS == 1)
327 const bool settings_active =
339 ImGui::PopStyleVar(2);
340 ImGui::PopStyleColor();
350 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
351 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
353 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
363 bool clicked = ImGui::SmallButton(icon);
365 ImGui::PopStyleColor(4);
367 if (tooltip && ImGui::IsItemHovered()) {
368 ImGui::SetTooltip(
"%s", tooltip);
376 const float frame_padding = ImGui::GetStyle().FramePadding.x;
379 return icon_width + frame_padding * 2.0f;
391 const std::string full_version =
394 const float item_spacing = 6.0f;
396 const float padding = 8.0f;
399 const ImGuiViewport* viewport = ImGui::GetMainViewport();
400 const float true_viewport_right = viewport->WorkPos.x + viewport->WorkSize.x;
404 int panel_button_count = 0;
407 panel_button_count = 5;
409 panel_button_count = 4;
413 float panel_region_width = 0.0f;
414 if (panel_button_count > 0) {
415 panel_region_width = (button_width * panel_button_count) +
416 (item_spacing * (panel_button_count - 1)) + padding;
419 panel_region_width += button_width + item_spacing;
423 float panel_screen_x = true_viewport_right - panel_region_width;
431 const float window_width = ImGui::GetWindowWidth();
432 const float window_screen_x = ImGui::GetWindowPos().x;
433 const float menu_items_end = ImGui::GetCursorPosX() + 16.0f;
436 float panel_local_x = panel_screen_x - window_screen_x;
438 std::min(window_width - padding, panel_local_x - item_spacing);
442 current_rom && current_rom->is_loaded() && current_rom->dirty();
445 float version_width = ImGui::CalcTextSize(full_version.c_str()).x;
448 float session_width = button_width;
450 const float available_width = region_end - menu_items_end - padding;
453 float required_width = button_width;
460 (required_width + version_width + item_spacing) <= available_width;
462 required_width += version_width + item_spacing;
467 has_multiple_sessions &&
468 (required_width + session_width + item_spacing) <= available_width;
470 required_width += session_width + item_spacing;
475 has_dirty_rom && (required_width + dirty_width) <= available_width;
477 required_width += dirty_width;
481 float start_pos = std::max(menu_items_end, region_end - required_width);
486 ImGui::SameLine(start_pos);
487 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(item_spacing, 0.0f));
492 ImGui::Text(
"%s", full_version.c_str());
493 ImGui::PopStyleColor();
500 ImGui::PushStyleColor(ImGuiCol_Text,
503 ImGui::PopStyleColor();
504 if (ImGui::IsItemHovered()) {
505 ImGui::SetTooltip(
"Unsaved changes: %s",
506 current_rom->short_name().c_str());
519 has_multiple_sessions);
524 if (panel_button_count > 0) {
526 float menu_bar_y = ImGui::GetCursorScreenPos().y;
529 ImGui::SetCursorScreenPos(ImVec2(panel_screen_x, menu_bar_y));
539 "Hide menu bar (Alt to restore)")) {
544 ImGui::PopStyleVar();
554 ImGuiWindowFlags flags =
555 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
556 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
557 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize |
558 ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoSavedSettings;
560 ImGui::SetNextWindowPos(ImVec2(8, 8));
561 ImGui::SetNextWindowBgAlpha(0.7f);
563 if (ImGui::Begin(
"##MenuBarRestore",
nullptr, flags)) {
565 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
567 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
575 ImGui::PopStyleColor(4);
577 if (ImGui::IsItemHovered()) {
578 ImGui::SetTooltip(
"Show menu bar (Alt)");
584 if (ImGui::IsKeyPressed(ImGuiKey_LeftAlt) ||
585 ImGui::IsKeyPressed(ImGuiKey_RightAlt)) {
592 bool has_multiple_sessions) {
603 if (unread > 0 || is_active) {
605 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
606 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
608 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
612 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
613 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
615 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
627 ImGui::PopStyleColor(4);
630 if (ImGui::IsItemHovered()) {
631 ImGui::BeginTooltip();
637 unread == 1 ?
"" :
"s");
638 ImGui::PopStyleColor();
642 ImGui::PopStyleColor();
645 ImGui::TextDisabled(
"Click to open Notifications panel");
648 if (!show_dirty && has_dirty_rom) {
650 ImGui::PushStyleColor(
655 current_rom->short_name().c_str());
656 ImGui::PopStyleColor();
659 if (!show_session && has_multiple_sessions) {
660 if (!show_dirty && has_dirty_rom) {
668 ImGui::PopStyleColor();
679 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
680 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
682 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
687 ImVec2 button_min = ImGui::GetCursorScreenPos();
690 ImGui::OpenPopup(
"##SessionSwitcherPopup");
693 ImVec2 button_max = ImGui::GetItemRectMax();
695 ImGui::PopStyleColor(4);
697 if (ImGui::IsItemHovered()) {
698 std::string tooltip = current_rom && current_rom->is_loaded()
699 ? current_rom->short_name()
701 ImGui::SetTooltip(
"%s\n%zu sessions open (Ctrl+Tab)", tooltip.c_str(),
706 const float popup_width = 250.0f;
707 const float screen_width = ImGui::GetIO().DisplaySize.x;
708 const float popup_x =
709 std::min(button_min.x, screen_width - popup_width - 10.0f);
711 ImGui::SetNextWindowPos(ImVec2(popup_x, button_max.y + 2.0f),
712 ImGuiCond_Appearing);
715 if (ImGui::BeginPopup(
"##SessionSwitcherPopup")) {
728 Rom* rom = &session->rom;
729 ImGui::PushID(
static_cast<int>(i));
731 bool is_current = (rom == current_rom);
742 if (ImGui::Selectable(label.c_str(), is_current)) {
747 ImGui::PopStyleColor();
815 "EditorManager is null - cannot check ROM state");
820 LOG_ERROR(
"UICoordinator",
"WelcomeScreen object is null - cannot render");
826 bool rom_is_loaded = current_rom && current_rom->is_loaded();
880 ImGuiWindowFlags_AlwaysAutoResize);
881 static char preset_name[128] =
"";
882 ImGui::InputText(
"Name", preset_name, IM_ARRAYSIZE(preset_name));
884 if (strlen(preset_name) > 0) {
888 preset_name[0] =
'\0';
894 preset_name[0] =
'\0';
901 ImGuiWindowFlags_AlwaysAutoResize);
907 for (
const auto& name : workspace_manager->workspace_presets()) {
908 if (ImGui::Selectable(name.c_str())) {
914 if (workspace_manager->workspace_presets().empty())
915 ImGui::Text(
"No presets found");
953 std::string category =
958 LOG_INFO(
"UICoordinator",
"Hid all panels in category: %s", category.c_str());
987 const std::string& icon,
989 std::function<
void()> callback,
992 ImGui::PushStyleColor(ImGuiCol_Button,
997 std::string button_text =
998 absl::StrFormat(
"%s %s", icon.c_str(), text.c_str());
999 if (ImGui::Button(button_text.c_str())) {
1000 if (enabled && callback) {
1006 ImGui::PopStyleColor(2);
1012 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
1013 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1018 ImGui::SetNextWindowPos(ImVec2(x, y), ImGuiCond_Appearing);
1023 ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiCond_FirstUseEver);
1030 using namespace ImGui;
1033 SetNextWindowPos(GetMainViewport()->GetCenter(), ImGuiCond_Appearing,
1034 ImVec2(0.5f, 0.5f));
1035 SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1037 bool show_palette =
true;
1038 if (Begin(absl::StrFormat(
"%s Command Palette",
ICON_MD_SEARCH).c_str(),
1039 &show_palette, ImGuiWindowFlags_NoCollapse)) {
1041 SetNextItemWidth(-100);
1042 if (IsWindowAppearing()) {
1043 SetKeyboardFocusHere();
1047 bool input_changed = InputTextWithHint(
1049 absl::StrFormat(
"%s Search commands (fuzzy matching enabled)...",
1055 if (Button(absl::StrFormat(
"%s Clear",
ICON_MD_CLEAR).c_str())) {
1057 input_changed =
true;
1064 std::vector<std::pair<int, std::pair<std::string, std::string>>>
1067 std::transform(query_lower.begin(), query_lower.end(), query_lower.begin(),
1071 const auto& name = entry.first;
1072 const auto& shortcut = entry.second;
1074 std::string name_lower = name;
1075 std::transform(name_lower.begin(), name_lower.end(), name_lower.begin(),
1081 }
else if (name_lower.find(query_lower) == 0) {
1083 }
else if (name_lower.find(query_lower) != std::string::npos) {
1087 size_t text_idx = 0, query_idx = 0;
1088 while (text_idx < name_lower.length() &&
1089 query_idx < query_lower.length()) {
1090 if (name_lower[text_idx] == query_lower[query_idx]) {
1096 if (query_idx != query_lower.length())
1101 std::string shortcut_text =
1102 shortcut.keys.empty()
1104 : absl::StrFormat(
"(%s)",
PrintShortcut(shortcut.keys).c_str());
1105 scored_commands.push_back({score, {name, shortcut_text}});
1109 std::sort(scored_commands.begin(), scored_commands.end(),
1110 [](
const auto& a,
const auto& b) { return a.first > b.first; });
1113 if (BeginTabBar(
"CommandCategories")) {
1115 absl::StrFormat(
"%s All Commands",
ICON_MD_LIST).c_str())) {
1117 "CommandPaletteTable", 3,
1118 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
1119 ImGuiTableFlags_SizingStretchProp,
1121 TableSetupColumn(
"Command", ImGuiTableColumnFlags_WidthStretch, 0.5f);
1122 TableSetupColumn(
"Shortcut", ImGuiTableColumnFlags_WidthStretch,
1124 TableSetupColumn(
"Score", ImGuiTableColumnFlags_WidthStretch, 0.2f);
1127 for (
size_t i = 0; i < scored_commands.size(); ++i) {
1128 const auto& [score, cmd_pair] = scored_commands[i];
1129 const auto& [command_name, shortcut_text] = cmd_pair;
1134 PushID(
static_cast<int>(i));
1137 if (Selectable(command_name.c_str(), is_selected,
1138 ImGuiSelectableFlags_SpanAllColumns)) {
1141 auto it = shortcuts.find(command_name);
1142 if (it != shortcuts.end() && it->second.callback) {
1143 it->second.callback();
1150 PushStyleColor(ImGuiCol_Text,
1152 Text(
"%s", shortcut_text.c_str());
1157 PushStyleColor(ImGuiCol_Text,
1169 if (BeginTabItem(absl::StrFormat(
"%s Recent",
ICON_MD_HISTORY).c_str())) {
1170 Text(
"Recent commands coming soon...");
1174 if (BeginTabItem(absl::StrFormat(
"%s Frequent",
ICON_MD_STAR).c_str())) {
1175 Text(
"Frequent commands coming soon...");
1184 Text(
"%s %zu commands | Score: fuzzy match",
ICON_MD_INFO,
1185 scored_commands.size());
1187 PushStyleColor(ImGuiCol_Text,
1189 Text(
"| ↑↓=Navigate | Enter=Execute | Esc=Close");
1195 if (!show_palette) {
1204 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
1205 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1206 ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
1208 bool show_search =
true;
1211 &show_search, ImGuiWindowFlags_NoCollapse)) {
1213 ImGui::SetNextItemWidth(-100);
1214 if (ImGui::IsWindowAppearing()) {
1215 ImGui::SetKeyboardFocusHere();
1218 bool input_changed = ImGui::InputTextWithHint(
1220 absl::StrFormat(
"%s Search everything...",
ICON_MD_SEARCH).c_str(),
1224 if (ImGui::Button(absl::StrFormat(
"%s Clear",
ICON_MD_CLEAR).c_str())) {
1226 input_changed =
true;
1232 if (ImGui::BeginTabBar(
"SearchResultTabs")) {
1234 if (ImGui::BeginTabItem(
1237 auto recent_files = manager.GetRecentFiles();
1239 if (ImGui::BeginTable(
"RecentFilesTable", 3,
1240 ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg |
1241 ImGuiTableFlags_SizingStretchProp)) {
1242 ImGui::TableSetupColumn(
"File", ImGuiTableColumnFlags_WidthStretch,
1244 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthFixed,
1246 ImGui::TableSetupColumn(
"Action", ImGuiTableColumnFlags_WidthFixed,
1248 ImGui::TableHeadersRow();
1250 for (
const auto& file : recent_files) {
1255 ImGui::TableNextRow();
1256 ImGui::TableNextColumn();
1259 ImGui::TableNextColumn();
1261 if (ext ==
"sfc" || ext ==
"smc") {
1262 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f),
"%s ROM",
1264 }
else if (ext ==
"yaze") {
1265 ImGui::TextColored(ImVec4(0.2f, 0.6f, 0.8f, 1.0f),
"%s Project",
1271 ImGui::TableNextColumn();
1272 ImGui::PushID(file.c_str());
1273 if (ImGui::Button(
"Open")) {
1277 absl::StrCat(
"Failed to open: ", status.message()),
1287 ImGui::EndTabItem();
1292 if (current_rom && current_rom->resource_label()) {
1293 if (ImGui::BeginTabItem(
1295 auto& labels = current_rom->resource_label()->labels_;
1297 if (ImGui::BeginTable(
"LabelsTable", 3,
1298 ImGuiTableFlags_ScrollY |
1299 ImGuiTableFlags_RowBg |
1300 ImGuiTableFlags_SizingStretchProp)) {
1301 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthFixed,
1303 ImGui::TableSetupColumn(
"Label", ImGuiTableColumnFlags_WidthStretch,
1305 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch,
1307 ImGui::TableHeadersRow();
1309 for (
const auto& type_pair : labels) {
1310 for (
const auto& kv : type_pair.second) {
1316 ImGui::TableNextRow();
1317 ImGui::TableNextColumn();
1318 ImGui::Text(
"%s", type_pair.first.c_str());
1320 ImGui::TableNextColumn();
1321 if (ImGui::Selectable(kv.first.c_str(),
false,
1322 ImGuiSelectableFlags_SpanAllColumns)) {
1326 ImGui::TableNextColumn();
1327 ImGui::TextDisabled(
"%s", kv.second.c_str());
1333 ImGui::EndTabItem();
1339 if (ImGui::BeginTabItem(
1340 absl::StrFormat(
"%s Sessions",
ICON_MD_TAB).c_str())) {
1341 ImGui::Text(
"Search and switch between active sessions:");
1345 std::string session_info =
1347 if (session_info ==
"[CLOSED SESSION]")
1357 ImGui::PushStyleColor(ImGuiCol_Text,
1358 ImVec4(0.2f, 0.8f, 0.2f, 1.0f));
1361 if (ImGui::Selectable(absl::StrFormat(
"%s %s %s",
ICON_MD_TAB,
1362 session_info.c_str(),
1363 is_current ?
"(Current)" :
"")
1372 ImGui::PopStyleColor();
1375 ImGui::EndTabItem();
1384 ImGui::Text(
"%s Global search across all YAZE data",
ICON_MD_INFO);
1403 const char* surface_names[] = {
"Welcome",
"Dashboard",
"Editor"};
1404 LOG_INFO(
"UICoordinator",
"Startup surface: %s -> %s",
1405 surface_names[
static_cast<int>(old_surface)],
1406 surface_names[
static_cast<int>(surface)]);
1463 if (!current_rom || !current_rom->is_loaded()) {
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
The EditorManager controls the main editor window and manages the various editor classes.
void SaveWorkspacePreset(const std::string &name)
float GetRightLayoutOffset() const
void SwitchToSession(size_t index)
WorkspaceManager * workspace_manager()
void LoadWorkspacePreset(const std::string &name)
absl::Status CreateNewProject(const std::string &template_name="Basic ROM Hack")
void RefreshWorkspacePresets()
auto GetCurrentEditor() const -> Editor *
absl::Status LoadRom()
Load a ROM file into a new or existing session.
auto GetCurrentRom() const -> Rom *
absl::Status OpenRomOrProject(const std::string &filename)
float GetLeftLayoutOffset() const
RightPanelManager * right_panel_manager()
Manages editor types, categories, and lifecycle.
static std::string GetEditorCategory(EditorType type)
Central registry for all editor cards with session awareness and dependency injection.
void ToggleSidebarVisibility()
bool ShowPanel(size_t session_id, const std::string &base_card_id)
bool IsPanelVisible(size_t session_id, const std::string &base_card_id) const
bool IsSidebarVisible() const
void SetSidebarVisible(bool visible)
bool HidePanel(size_t session_id, const std::string &base_card_id)
void HideAllPanelsInCategory(size_t session_id, const std::string &category)
Handles all project file operations with ROM-first workflow.
float GetPanelWidth() const
Get the width of the panel when expanded.
bool IsPanelExpanded() const
Check if any panel is currently expanded.
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
auto 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_
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
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
void HideCurrentEditorPanels()
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
StartupVisibility welcome_behavior_override_
bool welcome_screen_manually_closed_
void DrawMobileNavigation()
StartupVisibility dashboard_behavior_override_
StartupSurface current_startup_surface_
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
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()
EditorRegistry & editor_registry_
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)
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
static RecentFilesManager & GetInstance()
#define ICON_MD_NOTIFICATIONS
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_FULLSCREEN_EXIT
#define ICON_MD_EXPAND_LESS
#define ICON_MD_VIDEOGAME_ASSET
#define ICON_MD_MANAGE_SEARCH
#define ICON_MD_DESCRIPTION
#define ICON_MD_DASHBOARD
#define ICON_MD_VIEW_SIDEBAR
#define ICON_MD_FIBER_MANUAL_RECORD
#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)
ImVec4 GetSurfaceContainerHighestVec4()
ImVec4 GetTextDisabledVec4()
ImVec4 GetTextSecondaryVec4()
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.
Represents a single session, containing a ROM and its associated editors.