Refactor main menu action shell
This commit is contained in:
@@ -107,6 +107,7 @@
|
||||
- `Project` 右键菜单目标已不再依赖 panel 内裸索引字段,而是改成 targeted popup state
|
||||
- `Inspector / Console` 的局部 action 组装也开始继续下沉到 shared router
|
||||
- `Inspector` 的 component section header 菜单已开始改成 callback/router 驱动,而不是在 widget 层硬编码动作
|
||||
- `MenuBar` 的 File / View / Help / global shortcut 也开始继续下沉到 shared main-menu router
|
||||
|
||||
### 5. Dock / Layout 层
|
||||
|
||||
@@ -172,6 +173,8 @@
|
||||
- `Exit` 已通过事件驱动关闭 editor
|
||||
- `Edit` 菜单已开始跟随 active action route 在 `Hierarchy / Project` 之间切换
|
||||
- `Edit` 菜单与上下文快捷键开始共享同一套 edit action router
|
||||
- `File / View / Help / global shortcut` 已开始继续从 panel 下沉到 shared main-menu router
|
||||
- scene status 与 about dialog 已开始继续从 panel 下沉到共享 UI widget/dialog
|
||||
|
||||
仍待完成:
|
||||
|
||||
|
||||
50
editor/src/Actions/MainMenuActionRouter.h
Normal file
50
editor/src/Actions/MainMenuActionRouter.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "EditActionRouter.h"
|
||||
#include "EditorActions.h"
|
||||
#include "Commands/SceneCommands.h"
|
||||
#include "Core/EditorEvents.h"
|
||||
#include "Core/EventBus.h"
|
||||
#include "Core/IEditorContext.h"
|
||||
#include "UI/PopupState.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace Actions {
|
||||
|
||||
inline void HandleMainMenuShortcuts(IEditorContext& context, const ShortcutContext& shortcutContext) {
|
||||
HandleShortcut(MakeNewSceneAction(), shortcutContext, [&]() { Commands::NewScene(context); });
|
||||
HandleShortcut(MakeOpenSceneAction(), shortcutContext, [&]() { Commands::OpenSceneWithDialog(context); });
|
||||
HandleShortcut(MakeSaveSceneAction(), shortcutContext, [&]() { Commands::SaveCurrentScene(context); });
|
||||
HandleShortcut(MakeSaveSceneAsAction(), shortcutContext, [&]() { Commands::SaveSceneAsWithDialog(context); });
|
||||
HandleShortcut(MakeUndoAction(context), shortcutContext, [&]() { context.GetUndoManager().Undo(); });
|
||||
HandleShortcut(MakeRedoAction(context), shortcutContext, [&]() { context.GetUndoManager().Redo(); });
|
||||
HandleEditShortcuts(context, shortcutContext);
|
||||
}
|
||||
|
||||
inline void DrawFileMenuActions(IEditorContext& context) {
|
||||
DrawMenuAction(MakeNewSceneAction(), [&]() { Commands::NewScene(context); });
|
||||
DrawMenuAction(MakeOpenSceneAction(), [&]() { Commands::OpenSceneWithDialog(context); });
|
||||
DrawMenuAction(MakeSaveSceneAction(), [&]() { Commands::SaveCurrentScene(context); });
|
||||
DrawMenuAction(MakeSaveSceneAsAction(), [&]() { Commands::SaveSceneAsWithDialog(context); });
|
||||
DrawMenuSeparator();
|
||||
DrawMenuAction(MakeExitAction(), [&]() {
|
||||
context.GetEventBus().Publish(EditorExitRequestedEvent{});
|
||||
});
|
||||
}
|
||||
|
||||
inline void DrawViewMenuActions(IEditorContext& context) {
|
||||
DrawMenuAction(MakeResetLayoutAction(), [&]() {
|
||||
context.GetEventBus().Publish(DockLayoutResetRequestedEvent{});
|
||||
});
|
||||
}
|
||||
|
||||
inline void DrawHelpMenuActions(UI::DeferredPopupState& aboutPopup) {
|
||||
DrawMenuAction(MakeAboutAction(), [&]() {
|
||||
aboutPopup.RequestOpen();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Actions
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
39
editor/src/UI/AboutEditorDialog.h
Normal file
39
editor/src/UI/AboutEditorDialog.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "PopupState.h"
|
||||
#include "Widgets.h"
|
||||
|
||||
#include "Core/IEditorContext.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace UI {
|
||||
|
||||
inline void DrawEditorAboutDialog(const IEditorContext* context, DeferredPopupState& popupState) {
|
||||
popupState.ConsumeOpenRequest("About XCEngine Editor");
|
||||
|
||||
if (!BeginModalPopup("About XCEngine Editor")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("XCEngine Editor");
|
||||
ImGui::Separator();
|
||||
DrawHintText("Unity-like editor shell built on Dear ImGui.");
|
||||
ImGui::Spacing();
|
||||
ImGui::Text("Date: 2026-03-27");
|
||||
ImGui::Text("UI Refactor: Actions / Commands / Layout in progress");
|
||||
if (context) {
|
||||
ImGui::Text("Project: %s", context->GetProjectPath().c_str());
|
||||
}
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Button("Close", DialogActionButtonSize())) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
} // namespace UI
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
46
editor/src/UI/SceneStatusWidget.h
Normal file
46
editor/src/UI/SceneStatusWidget.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "Widgets.h"
|
||||
|
||||
#include "Core/IEditorContext.h"
|
||||
#include "Core/ISceneManager.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace UI {
|
||||
|
||||
inline void DrawSceneStatusWidget(IEditorContext& context) {
|
||||
auto& sceneManager = context.GetSceneManager();
|
||||
std::string sceneLabel = sceneManager.HasActiveScene() ? sceneManager.GetCurrentSceneName() : "No Scene";
|
||||
if (sceneLabel.empty()) {
|
||||
sceneLabel = "Untitled Scene";
|
||||
}
|
||||
|
||||
const std::string fileLabel = sceneManager.GetCurrentScenePath().empty()
|
||||
? "Unsaved.xc"
|
||||
: std::filesystem::path(sceneManager.GetCurrentScenePath()).filename().string();
|
||||
|
||||
const bool dirty = sceneManager.IsSceneDirty();
|
||||
const std::string statusText = dirty ? (std::string("* ") + fileLabel) : fileLabel;
|
||||
DrawRightAlignedText(
|
||||
statusText.c_str(),
|
||||
dirty ? MenuBarStatusDirtyColor() : MenuBarStatusIdleColor());
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
BeginTitledTooltip("Scene");
|
||||
ImGui::Text("Name: %s", sceneLabel.c_str());
|
||||
ImGui::Text("File: %s", fileLabel.c_str());
|
||||
ImGui::Text("State: %s", dirty ? "Modified" : "Saved");
|
||||
ImGui::Text(
|
||||
"Path: %s",
|
||||
sceneManager.GetCurrentScenePath().empty() ? "(not saved yet)" : sceneManager.GetCurrentScenePath().c_str());
|
||||
EndTitledTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UI
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "AboutEditorDialog.h"
|
||||
#include "BaseTheme.h"
|
||||
#include "ConsoleFilterState.h"
|
||||
#include "ConsoleLogFormatter.h"
|
||||
@@ -9,6 +10,7 @@
|
||||
#include "PopupState.h"
|
||||
#include "PropertyGrid.h"
|
||||
#include "ScalarControls.h"
|
||||
#include "SceneStatusWidget.h"
|
||||
#include "StyleTokens.h"
|
||||
#include "VectorControls.h"
|
||||
#include "Widgets.h"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Core.h"
|
||||
#include "StyleTokens.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
#include "Actions/ActionRouting.h"
|
||||
#include "Actions/EditActionRouter.h"
|
||||
#include "Actions/EditorActions.h"
|
||||
#include "Commands/SceneCommands.h"
|
||||
#include "Actions/MainMenuActionRouter.h"
|
||||
#include "MenuBar.h"
|
||||
#include "Core/EditorEvents.h"
|
||||
#include "Core/EventBus.h"
|
||||
#include "Core/IEditorContext.h"
|
||||
#include "Core/ISceneManager.h"
|
||||
#include "UI/UI.h"
|
||||
#include <filesystem>
|
||||
#include <imgui.h>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -36,27 +31,12 @@ void MenuBar::HandleShortcuts() {
|
||||
return;
|
||||
}
|
||||
|
||||
const Actions::ShortcutContext shortcutContext = Actions::GlobalShortcutContext();
|
||||
|
||||
Actions::HandleShortcut(Actions::MakeNewSceneAction(), shortcutContext, [&]() { Commands::NewScene(*m_context); });
|
||||
Actions::HandleShortcut(Actions::MakeOpenSceneAction(), shortcutContext, [&]() { Commands::OpenSceneWithDialog(*m_context); });
|
||||
Actions::HandleShortcut(Actions::MakeSaveSceneAction(), shortcutContext, [&]() { Commands::SaveCurrentScene(*m_context); });
|
||||
Actions::HandleShortcut(Actions::MakeSaveSceneAsAction(), shortcutContext, [&]() { Commands::SaveSceneAsWithDialog(*m_context); });
|
||||
Actions::HandleShortcut(Actions::MakeUndoAction(*m_context), shortcutContext, [&]() { m_context->GetUndoManager().Undo(); });
|
||||
Actions::HandleShortcut(Actions::MakeRedoAction(*m_context), shortcutContext, [&]() { m_context->GetUndoManager().Redo(); });
|
||||
Actions::HandleEditShortcuts(*m_context, shortcutContext);
|
||||
Actions::HandleMainMenuShortcuts(*m_context, Actions::GlobalShortcutContext());
|
||||
}
|
||||
|
||||
void MenuBar::ShowFileMenu() {
|
||||
UI::DrawMenuScope("File", [&]() {
|
||||
Actions::DrawMenuAction(Actions::MakeNewSceneAction(), [&]() { Commands::NewScene(*m_context); });
|
||||
Actions::DrawMenuAction(Actions::MakeOpenSceneAction(), [&]() { Commands::OpenSceneWithDialog(*m_context); });
|
||||
Actions::DrawMenuAction(Actions::MakeSaveSceneAction(), [&]() { Commands::SaveCurrentScene(*m_context); });
|
||||
Actions::DrawMenuAction(Actions::MakeSaveSceneAsAction(), [&]() { Commands::SaveSceneAsWithDialog(*m_context); });
|
||||
Actions::DrawMenuSeparator();
|
||||
Actions::DrawMenuAction(Actions::MakeExitAction(), [&]() {
|
||||
m_context->GetEventBus().Publish(EditorExitRequestedEvent{});
|
||||
});
|
||||
Actions::DrawFileMenuActions(*m_context);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,74 +48,25 @@ void MenuBar::ShowEditMenu() {
|
||||
|
||||
void MenuBar::ShowViewMenu() {
|
||||
UI::DrawMenuScope("View", [&]() {
|
||||
Actions::DrawMenuAction(Actions::MakeResetLayoutAction(), [&]() {
|
||||
m_context->GetEventBus().Publish(DockLayoutResetRequestedEvent{});
|
||||
});
|
||||
Actions::DrawViewMenuActions(*m_context);
|
||||
});
|
||||
}
|
||||
|
||||
void MenuBar::ShowHelpMenu() {
|
||||
UI::DrawMenuScope("Help", [&]() {
|
||||
Actions::DrawMenuAction(Actions::MakeAboutAction(), [&]() {
|
||||
m_aboutPopup.RequestOpen();
|
||||
});
|
||||
Actions::DrawHelpMenuActions(m_aboutPopup);
|
||||
});
|
||||
}
|
||||
|
||||
void MenuBar::RenderAboutPopup() {
|
||||
m_aboutPopup.ConsumeOpenRequest("About XCEngine Editor");
|
||||
|
||||
if (!UI::BeginModalPopup("About XCEngine Editor")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("XCEngine Editor");
|
||||
ImGui::Separator();
|
||||
UI::DrawHintText("Unity-like editor shell built on Dear ImGui.");
|
||||
ImGui::Spacing();
|
||||
ImGui::Text("Date: 2026-03-26");
|
||||
ImGui::Text("UI Refactor: Actions / Commands / Layout in progress");
|
||||
if (m_context) {
|
||||
ImGui::Text("Project: %s", m_context->GetProjectPath().c_str());
|
||||
}
|
||||
ImGui::Spacing();
|
||||
|
||||
if (Actions::DrawButtonAction(Actions::MakeAction("Close"), UI::DialogActionButtonSize())) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
UI::EndPopup();
|
||||
UI::DrawEditorAboutDialog(m_context, m_aboutPopup);
|
||||
}
|
||||
|
||||
void MenuBar::RenderSceneStatus() {
|
||||
if (!m_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& sceneManager = m_context->GetSceneManager();
|
||||
std::string sceneLabel = sceneManager.HasActiveScene() ? sceneManager.GetCurrentSceneName() : "No Scene";
|
||||
if (sceneLabel.empty()) {
|
||||
sceneLabel = "Untitled Scene";
|
||||
}
|
||||
|
||||
std::string fileLabel = sceneManager.GetCurrentScenePath().empty()
|
||||
? "Unsaved.xc"
|
||||
: std::filesystem::path(sceneManager.GetCurrentScenePath()).filename().string();
|
||||
|
||||
const bool dirty = sceneManager.IsSceneDirty();
|
||||
const std::string statusText = dirty ? (std::string("* ") + fileLabel) : fileLabel;
|
||||
UI::DrawRightAlignedText(
|
||||
statusText.c_str(),
|
||||
dirty ? UI::MenuBarStatusDirtyColor() : UI::MenuBarStatusIdleColor());
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
UI::BeginTitledTooltip("Scene");
|
||||
ImGui::Text("Name: %s", sceneLabel.c_str());
|
||||
ImGui::Text("File: %s", fileLabel.c_str());
|
||||
ImGui::Text("State: %s", dirty ? "Modified" : "Saved");
|
||||
ImGui::Text("Path: %s", sceneManager.GetCurrentScenePath().empty() ? "(not saved yet)" : sceneManager.GetCurrentScenePath().c_str());
|
||||
UI::EndTitledTooltip();
|
||||
}
|
||||
UI::DrawSceneStatusWidget(*m_context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user