2#include <absl/status/status.h>
3#include <absl/status/statusor.h>
15#include "absl/strings/str_format.h"
31#include "imgui/imgui.h"
39 ToastManager* toast_manager,
40 UserSettings* user_settings)
41 : window_manager_(window_manager),
42 toast_manager_(toast_manager),
43 user_settings_(user_settings) {}
45void SessionCoordinator::NotifySessionSwitched(
size_t index,
46 RomSession* session) {
50 size_t old_index = active_session_index_;
52 SessionSwitchedEvent::Create(old_index, index, session));
56void SessionCoordinator::NotifySessionCreated(
size_t index,
57 RomSession* session) {
60 event_bus_->Publish(SessionCreatedEvent::Create(index, session));
64void SessionCoordinator::NotifySessionClosed(
size_t index) {
67 event_bus_->Publish(SessionClosedEvent::Create(index));
71void SessionCoordinator::NotifySessionRomLoaded(
size_t index,
72 RomSession* session) {
74 if (event_bus_ && session) {
76 RomLoadedEvent::Create(&session->rom, session->filepath, index));
80void SessionCoordinator::CreateNewSession() {
81 if (session_count_ >= kMaxSessions) {
82 ShowSessionLimitWarning();
87 sessions_.push_back(std::make_unique<RomSession>());
91 active_session_index_ = sessions_.size() - 1;
94 if (editor_manager_) {
95 auto& session = sessions_.back();
96 editor_manager_->ConfigureSession(session.get());
99 LOG_INFO(
"SessionCoordinator",
"Created new session %zu (total: %zu)",
100 active_session_index_, session_count_);
103 NotifySessionCreated(active_session_index_, sessions_.back().get());
105 ShowSessionOperationResult(
"Create Session",
true);
108void SessionCoordinator::DuplicateCurrentSession() {
109 if (sessions_.empty())
112 if (session_count_ >= kMaxSessions) {
113 ShowSessionLimitWarning();
120 sessions_.push_back(std::make_unique<RomSession>());
121 UpdateSessionCount();
124 active_session_index_ = sessions_.size() - 1;
127 if (editor_manager_) {
128 auto& session = sessions_.back();
129 editor_manager_->ConfigureSession(session.get());
132 LOG_INFO(
"SessionCoordinator",
"Duplicated session %zu (total: %zu)",
133 active_session_index_, session_count_);
136 NotifySessionCreated(active_session_index_, sessions_.back().get());
138 ShowSessionOperationResult(
"Duplicate Session",
true);
141void SessionCoordinator::CloseCurrentSession() {
142 CloseSession(active_session_index_);
145void SessionCoordinator::CloseSession(
size_t index) {
146 if (!IsValidSessionIndex(index))
149 if (session_count_ <= kMinSessions) {
151 if (toast_manager_) {
152 toast_manager_->Show(
"Cannot close the last session",
153 ToastType::kWarning);
159 if (window_manager_) {
160 window_manager_->UnregisterSession(index);
164 NotifySessionClosed(index);
167 sessions_.erase(sessions_.begin() + index);
168 UpdateSessionCount();
171 if (active_session_index_ >= index && active_session_index_ > 0) {
172 active_session_index_--;
175 LOG_INFO(
"SessionCoordinator",
"Closed session %zu (total: %zu)", index,
178 ShowSessionOperationResult(
"Close Session",
true);
181void SessionCoordinator::RemoveSession(
size_t index) {
185void SessionCoordinator::SwitchToSession(
size_t index) {
186 if (!IsValidSessionIndex(index))
189 size_t old_index = active_session_index_;
190 active_session_index_ = index;
192 if (window_manager_) {
193 window_manager_->SetActiveSession(index);
197 if (old_index != index) {
198 NotifySessionSwitched(index, sessions_[index].get());
202void SessionCoordinator::ActivateSession(
size_t index) {
203 SwitchToSession(index);
206size_t SessionCoordinator::GetActiveSessionIndex()
const {
207 return active_session_index_;
210void* SessionCoordinator::GetActiveSession()
const {
211 if (!IsValidSessionIndex(active_session_index_)) {
214 return sessions_[active_session_index_].get();
217RomSession* SessionCoordinator::GetActiveRomSession()
const {
218 return static_cast<RomSession*
>(GetActiveSession());
221Rom* SessionCoordinator::GetCurrentRom()
const {
222 auto* session = GetActiveRomSession();
223 return session ? &session->rom :
nullptr;
226zelda3::GameData* SessionCoordinator::GetCurrentGameData()
const {
227 auto* session = GetActiveRomSession();
228 return session ? &session->game_data :
nullptr;
231EditorSet* SessionCoordinator::GetCurrentEditorSet()
const {
232 auto* session = GetActiveRomSession();
233 return session ? &session->editors :
nullptr;
236void* SessionCoordinator::GetSession(
size_t index)
const {
237 if (!IsValidSessionIndex(index)) {
240 return sessions_[index].get();
243bool SessionCoordinator::HasMultipleSessions()
const {
244 return session_count_ > 1;
247size_t SessionCoordinator::GetActiveSessionCount()
const {
248 return session_count_;
251bool SessionCoordinator::HasDuplicateSession(
252 const std::string& filepath)
const {
253 if (filepath.empty())
256 for (
const auto& session : sessions_) {
257 if (session->filepath == filepath) {
264void SessionCoordinator::DrawSessionSwitcher() {
265 if (sessions_.empty())
268 if (!show_session_switcher_)
271 ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver);
272 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
273 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
275 if (!ImGui::Begin(
"Session Switcher", &show_session_switcher_)) {
280 ImGui::Text(
"%s Active Sessions (%zu)",
ICON_MD_TAB, session_count_);
283 for (
size_t i = 0; i < sessions_.size(); ++i) {
284 bool is_active = (i == active_session_index_);
286 ImGui::PushID(
static_cast<int>(i));
289 if (ImGui::Selectable(GetSessionDisplayName(i).c_str(), is_active)) {
294 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
295 ImGui::OpenPopup(
"SessionContextMenu");
298 if (ImGui::BeginPopup(
"SessionContextMenu")) {
299 DrawSessionContextMenu(i);
309 if (ImGui::Button(absl::StrFormat(
"%s New Session",
ICON_MD_ADD).c_str())) {
316 DuplicateCurrentSession();
320 if (HasMultipleSessions() &&
321 ImGui::Button(absl::StrFormat(
"%s Close",
ICON_MD_CLOSE).c_str())) {
322 CloseCurrentSession();
328void SessionCoordinator::DrawSessionManager() {
329 if (sessions_.empty())
332 if (!show_session_manager_)
335 ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_FirstUseEver);
336 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
337 ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
339 if (!ImGui::Begin(
"Session Manager", &show_session_manager_)) {
348 ImGui::Text(
"Total Sessions: %zu", GetTotalSessionCount());
349 ImGui::Text(
"Loaded Sessions: %zu", GetLoadedSessionCount());
350 ImGui::Text(
"Empty Sessions: %zu", GetEmptySessionCount());
355 if (ImGui::BeginTable(
"SessionTable", 4,
356 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
357 ImGuiTableFlags_Resizable)) {
358 ImGui::TableSetupColumn(
"Session", ImGuiTableColumnFlags_WidthStretch,
360 ImGui::TableSetupColumn(
"ROM File", ImGuiTableColumnFlags_WidthStretch,
362 ImGui::TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthStretch, 0.2f);
363 ImGui::TableSetupColumn(
"Actions", ImGuiTableColumnFlags_WidthFixed,
365 ImGui::TableHeadersRow();
367 for (
size_t i = 0; i < sessions_.size(); ++i) {
368 const auto& session = sessions_[i];
369 bool is_active = (i == active_session_index_);
371 ImGui::PushID(
static_cast<int>(i));
373 ImGui::TableNextRow();
376 ImGui::TableNextColumn();
378 ImGui::TextColored(gui::GetSuccessColor(),
"%s %s",
380 GetSessionDisplayName(i).c_str());
383 GetSessionDisplayName(i).c_str());
387 ImGui::TableNextColumn();
388 if (session->rom.is_loaded()) {
389 ImGui::Text(
"%s", session->filepath.c_str());
391 ImGui::TextDisabled(
"(No ROM loaded)");
395 ImGui::TableNextColumn();
396 if (session->rom.is_loaded()) {
397 ImGui::TextColored(gui::GetSuccessColor(),
"Loaded");
399 ImGui::TextColored(gui::GetWarningColor(),
"Empty");
403 ImGui::TableNextColumn();
404 if (!is_active && ImGui::SmallButton(
"Switch")) {
409 if (HasMultipleSessions() && ImGui::SmallButton(
"Close")) {
422void SessionCoordinator::DrawSessionRenameDialog() {
423 if (!show_session_rename_dialog_)
426 ImGui::SetNextWindowSize(ImVec2(300, 150), ImGuiCond_Always);
427 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
428 ImGuiCond_Always, ImVec2(0.5f, 0.5f));
430 if (!ImGui::Begin(
"Rename Session", &show_session_rename_dialog_)) {
435 ImGui::Text(
"Rename session %zu:", session_to_rename_);
436 ImGui::InputText(
"Name", session_rename_buffer_,
437 sizeof(session_rename_buffer_));
441 if (ImGui::Button(
"OK")) {
442 RenameSession(session_to_rename_, session_rename_buffer_);
443 show_session_rename_dialog_ =
false;
444 session_rename_buffer_[0] =
'\0';
448 if (ImGui::Button(
"Cancel")) {
449 show_session_rename_dialog_ =
false;
450 session_rename_buffer_[0] =
'\0';
456void SessionCoordinator::DrawSessionTabs() {
457 if (sessions_.empty())
460 if (gui::BeginThemedTabBar(
"SessionTabs")) {
461 for (
size_t i = 0; i < sessions_.size(); ++i) {
462 bool is_active = (i == active_session_index_);
463 const auto& session = sessions_[i];
465 std::string tab_name = GetSessionDisplayName(i);
466 if (session->rom.is_loaded()) {
471 if (ImGui::BeginTabItem(tab_name.c_str())) {
479 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
480 ImGui::OpenPopup(absl::StrFormat(
"SessionTabContext_%zu", i).c_str());
483 if (ImGui::BeginPopup(
484 absl::StrFormat(
"SessionTabContext_%zu", i).c_str())) {
485 DrawSessionContextMenu(i);
489 gui::EndThemedTabBar();
493void SessionCoordinator::DrawSessionIndicator() {
494 if (!HasMultipleSessions())
497 const auto& theme = gui::ThemeManager::Get().GetCurrentTheme();
501 gui::StyleColorGuard accent_guard(ImGuiCol_Text, accent_color);
502 ImGui::Text(
"%s Session %zu",
ICON_MD_TAB, active_session_index_);
505 if (ImGui::IsItemHovered()) {
506 ImGui::SetTooltip(
"Active Session: %s\nClick to open session switcher",
507 GetActiveSessionDisplayName().c_str());
510 if (ImGui::IsItemClicked()) {
511 ToggleSessionSwitcher();
515std::string SessionCoordinator::GetSessionDisplayName(
size_t index)
const {
516 if (!IsValidSessionIndex(index)) {
517 return "Invalid Session";
520 const auto& session = sessions_[index];
522 if (!session->custom_name.empty()) {
523 return session->custom_name;
526 if (session->rom.is_loaded()) {
527 return absl::StrFormat(
528 "Session %zu (%s)", index,
529 std::filesystem::path(session->filepath).stem().string());
532 return absl::StrFormat(
"Session %zu (Empty)", index);
535std::string SessionCoordinator::GetActiveSessionDisplayName()
const {
536 return GetSessionDisplayName(active_session_index_);
539void SessionCoordinator::RenameSession(
size_t index,
540 const std::string& new_name) {
541 if (!IsValidSessionIndex(index) || new_name.empty())
544 sessions_[index]->custom_name = new_name;
545 LOG_INFO(
"SessionCoordinator",
"Renamed session %zu to '%s'", index,
549std::string SessionCoordinator::GenerateUniqueEditorTitle(
550 const std::string& editor_name,
size_t session_index)
const {
551 if (sessions_.size() <= 1) {
556 if (session_index >= sessions_.size()) {
561 const auto& session = sessions_[session_index];
562 std::string session_name = session->custom_name.empty()
563 ? session->rom.title()
564 : session->custom_name;
567 if (session_name.length() > 20) {
568 session_name = session_name.substr(0, 17) +
"...";
571 return absl::StrFormat(
"%s - %s##session_%zu", editor_name, session_name,
575void SessionCoordinator::SetActiveSessionIndex(
size_t index) {
576 SwitchToSession(index);
579void SessionCoordinator::UpdateSessionCount() {
580 session_count_ = sessions_.size();
584void SessionCoordinator::ShowAllPanelsInActiveSession() {
585 if (window_manager_) {
586 window_manager_->ShowAllWindowsInSession(active_session_index_);
590void SessionCoordinator::HideAllPanelsInActiveSession() {
591 if (window_manager_) {
592 window_manager_->HideAllWindowsInSession(active_session_index_);
596void SessionCoordinator::ShowPanelsInCategory(
const std::string& category) {
597 if (window_manager_) {
598 window_manager_->ShowAllWindowsInCategory(active_session_index_, category);
602void SessionCoordinator::HidePanelsInCategory(
const std::string& category) {
603 if (window_manager_) {
604 window_manager_->HideAllWindowsInCategory(active_session_index_, category);
608bool SessionCoordinator::IsValidSessionIndex(
size_t index)
const {
609 return index < sessions_.size();
612void SessionCoordinator::UpdateSessions() {
613 if (sessions_.empty())
616 size_t original_session_idx = active_session_index_;
618 for (
size_t session_idx = 0; session_idx < sessions_.size(); ++session_idx) {
619 auto& session = sessions_[session_idx];
620 const bool rom_loaded = session->rom.is_loaded();
623 if (!rom_loaded && session_idx != active_session_index_) {
628 SwitchToSession(session_idx);
630 for (
auto editor : session->editors.active_editors_) {
631 if (*editor->active()) {
633 !EditorRegistry::UpdateAllowedWithoutLoadedRom(editor->type())) {
637 if (rom_loaded && editor->type() == EditorType::kOverworld) {
638 auto& overworld_editor =
static_cast<OverworldEditor&
>(*editor);
639 if (overworld_editor.jump_to_tab() != -1) {
641 session->editors.GetDungeonEditor()->add_room(
642 overworld_editor.jump_to_tab());
643 overworld_editor.jump_to_tab_ = -1;
648 bool is_card_based_editor =
649 EditorManager::IsPanelBasedEditor(editor->type());
651 if (is_card_based_editor) {
654 if (editor_manager_) {
655 editor_manager_->SetCurrentEditor(editor);
658 absl::Status status = editor->Update();
661 if (!status.ok() && toast_manager_) {
662 std::string editor_name =
664 toast_manager_->Show(
665 absl::StrFormat(
"%s Error: %s", editor_name, status.message()),
666 ToastType::kError, 8.0f);
671 std::string window_title = GenerateUniqueEditorTitle(
672 kEditorNames[
static_cast<int>(editor->type())], session_idx);
675 ImGui::SetNextWindowSize(ImGui::GetMainViewport()->WorkSize,
676 ImGuiCond_FirstUseEver);
677 ImGui::SetNextWindowPos(ImGui::GetMainViewport()->WorkPos,
678 ImGuiCond_FirstUseEver);
680 if (ImGui::Begin(window_title.c_str(), editor->active(),
681 ImGuiWindowFlags_None)) {
684 if (editor_manager_) {
685 editor_manager_->SetCurrentEditor(editor);
688 absl::Status status = editor->Update();
691 if (!status.ok() && toast_manager_) {
692 std::string editor_name =
694 toast_manager_->Show(absl::StrFormat(
"%s Error: %s", editor_name,
696 ToastType::kError, 8.0f);
706 SwitchToSession(original_session_idx);
709bool SessionCoordinator::IsSessionActive(
size_t index)
const {
710 return index == active_session_index_;
713bool SessionCoordinator::IsSessionLoaded(
size_t index)
const {
714 return IsValidSessionIndex(index) && sessions_[index]->rom.is_loaded();
717size_t SessionCoordinator::GetTotalSessionCount()
const {
718 return session_count_;
721size_t SessionCoordinator::GetLoadedSessionCount()
const {
723 for (
const auto& session : sessions_) {
724 if (session->rom.is_loaded()) {
731size_t SessionCoordinator::GetEmptySessionCount()
const {
732 return session_count_ - GetLoadedSessionCount();
735absl::Status SessionCoordinator::LoadRomIntoSession(
const std::string& filename,
736 size_t session_index) {
737 if (filename.empty()) {
738 return absl::InvalidArgumentError(
"Invalid parameters");
741 size_t target_index =
742 (session_index == SIZE_MAX) ? active_session_index_ : session_index;
743 if (!IsValidSessionIndex(target_index)) {
744 return absl::InvalidArgumentError(
"Invalid session index");
748 LOG_INFO(
"SessionCoordinator",
"LoadRomIntoSession: %s -> session %zu",
749 filename.c_str(), target_index);
751 return absl::OkStatus();
754absl::Status SessionCoordinator::SaveActiveSession(
755 const std::string& filename) {
756 if (!IsValidSessionIndex(active_session_index_)) {
757 return absl::FailedPreconditionError(
"No active session");
761 LOG_INFO(
"SessionCoordinator",
"SaveActiveSession: session %zu",
762 active_session_index_);
764 return absl::OkStatus();
767absl::Status SessionCoordinator::SaveSessionAs(
size_t session_index,
768 const std::string& filename) {
769 if (!IsValidSessionIndex(session_index) || filename.empty()) {
770 return absl::InvalidArgumentError(
"Invalid parameters");
774 LOG_INFO(
"SessionCoordinator",
"SaveSessionAs: session %zu -> %s",
775 session_index, filename.c_str());
777 return absl::OkStatus();
780absl::StatusOr<RomSession*> SessionCoordinator::CreateSessionFromRom(
781 Rom&& rom,
const std::string& filepath) {
782 size_t new_session_id = sessions_.size();
783 sessions_.push_back(std::make_unique<RomSession>(
784 std::move(rom), user_settings_, new_session_id, editor_registry_));
785 auto& session = sessions_.back();
786 session->filepath = filepath;
788 UpdateSessionCount();
789 SwitchToSession(new_session_id);
792 NotifySessionCreated(new_session_id, session.get());
793 NotifySessionRomLoaded(new_session_id, session.get());
795 return session.get();
798void SessionCoordinator::CleanupClosedSessions() {
800 size_t loaded_count = 0;
801 for (
const auto& session : sessions_) {
802 if (session->rom.is_loaded()) {
807 if (loaded_count > 0) {
808 for (
auto it = sessions_.begin(); it != sessions_.end();) {
809 if (!(*it)->rom.is_loaded() && sessions_.size() > 1) {
810 it = sessions_.erase(it);
817 UpdateSessionCount();
818 LOG_INFO(
"SessionCoordinator",
"Cleaned up closed sessions (remaining: %zu)",
822void SessionCoordinator::ClearAllSessions() {
823 if (sessions_.empty())
827 if (window_manager_) {
828 for (
size_t i = 0; i < sessions_.size(); ++i) {
829 window_manager_->UnregisterSession(i);
834 active_session_index_ = 0;
835 UpdateSessionCount();
837 LOG_INFO(
"SessionCoordinator",
"Cleared all sessions");
840void SessionCoordinator::FocusNextSession() {
841 if (sessions_.empty())
844 size_t next_index = (active_session_index_ + 1) % sessions_.size();
845 SwitchToSession(next_index);
848void SessionCoordinator::FocusPreviousSession() {
849 if (sessions_.empty())
852 size_t prev_index = (active_session_index_ == 0) ? sessions_.size() - 1
853 : active_session_index_ - 1;
854 SwitchToSession(prev_index);
857void SessionCoordinator::FocusFirstSession() {
858 if (sessions_.empty())
863void SessionCoordinator::FocusLastSession() {
864 if (sessions_.empty())
866 SwitchToSession(sessions_.size() - 1);
869void SessionCoordinator::UpdateActiveSession() {
870 if (!sessions_.empty() && active_session_index_ >= sessions_.size()) {
871 active_session_index_ = sessions_.size() - 1;
875void SessionCoordinator::ValidateSessionIndex(
size_t index)
const {
876 if (!IsValidSessionIndex(index)) {
877 throw std::out_of_range(
878 absl::StrFormat(
"Invalid session index: %zu", index));
882std::string SessionCoordinator::GenerateUniqueSessionName(
883 const std::string& base_name)
const {
884 if (sessions_.empty())
887 std::string
name = base_name;
892 for (
const auto& session : sessions_) {
893 if (session->custom_name == name) {
902 name = absl::StrFormat(
"%s %d", base_name, counter++);
908void SessionCoordinator::ShowSessionLimitWarning() {
909 if (toast_manager_) {
910 toast_manager_->Show(
911 absl::StrFormat(
"Maximum %zu sessions allowed", kMaxSessions),
912 ToastType::kWarning);
916void SessionCoordinator::ShowSessionOperationResult(
917 const std::string& operation,
bool success) {
918 if (toast_manager_) {
919 std::string message =
920 absl::StrFormat(
"%s %s", operation, success ?
"succeeded" :
"failed");
921 ToastType type = success ? ToastType::kSuccess : ToastType::kError;
922 toast_manager_->Show(message, type);
926void SessionCoordinator::DrawSessionTab(
size_t index,
bool is_active) {
927 if (index >= sessions_.size())
930 const auto& session = sessions_[index];
932 ImVec4 color = GetSessionColor(index);
933 gui::StyleColorGuard tab_color_guard(ImGuiCol_Text, color);
935 std::string tab_name = GetSessionDisplayName(index);
936 if (session->rom.is_loaded()) {
941 if (ImGui::BeginTabItem(tab_name.c_str())) {
943 SwitchToSession(index);
949void SessionCoordinator::DrawSessionContextMenu(
size_t index) {
951 absl::StrFormat(
"%s Switch to Session",
ICON_MD_TAB).c_str())) {
952 SwitchToSession(index);
955 if (ImGui::MenuItem(absl::StrFormat(
"%s Rename",
ICON_MD_EDIT).c_str())) {
956 session_to_rename_ = index;
957 strncpy(session_rename_buffer_, GetSessionDisplayName(index).c_str(),
958 sizeof(session_rename_buffer_) - 1);
959 session_rename_buffer_[
sizeof(session_rename_buffer_) - 1] =
'\0';
960 show_session_rename_dialog_ =
true;
970 if (HasMultipleSessions() &&
972 absl::StrFormat(
"%s Close Session",
ICON_MD_CLOSE).c_str())) {
977void SessionCoordinator::DrawSessionBadge(
size_t index) {
978 if (index >= sessions_.size())
981 const auto& session = sessions_[index];
982 ImVec4 color = GetSessionColor(index);
984 gui::StyleColorGuard badge_guard(ImGuiCol_Text, color);
986 if (session->rom.is_loaded()) {
993ImVec4 SessionCoordinator::GetSessionColor(
size_t index)
const {
995 static const ImVec4 colors[] = {
996 ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
997 ImVec4(0.0f, 0.5f, 1.0f, 1.0f),
998 ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
999 ImVec4(1.0f, 0.0f, 1.0f, 1.0f),
1000 ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
1001 ImVec4(0.0f, 1.0f, 1.0f, 1.0f),
1002 ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
1003 ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
1006 return colors[index % (
sizeof(colors) /
sizeof(colors[0]))];
1009std::string SessionCoordinator::GetSessionIcon(
size_t index)
const {
1010 if (index >= sessions_.size())
1013 const auto& session = sessions_[index];
1015 if (session->rom.is_loaded()) {
1022bool SessionCoordinator::IsSessionEmpty(
size_t index)
const {
1023 return IsValidSessionIndex(index) && !sessions_[index]->rom.is_loaded();
1026bool SessionCoordinator::IsSessionClosed(
size_t index)
const {
1027 return !IsValidSessionIndex(index);
1030bool SessionCoordinator::IsSessionModified(
size_t index)
const {
SessionCoordinator(WorkspaceWindowManager *window_manager, ToastManager *toast_manager, UserSettings *user_settings)
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_RADIO_BUTTON_CHECKED
#define ICON_MD_CONTENT_COPY
#define ICON_MD_RADIO_BUTTON_UNCHECKED
#define ICON_MD_ANALYTICS
#define LOG_INFO(category, format,...)
constexpr std::array< const char *, 14 > kEditorNames
ImVec4 ConvertColorToImVec4(const Color &color)