Refactor main menu action shell
This commit is contained in:
@@ -107,6 +107,7 @@
|
|||||||
- `Project` 右键菜单目标已不再依赖 panel 内裸索引字段,而是改成 targeted popup state
|
- `Project` 右键菜单目标已不再依赖 panel 内裸索引字段,而是改成 targeted popup state
|
||||||
- `Inspector / Console` 的局部 action 组装也开始继续下沉到 shared router
|
- `Inspector / Console` 的局部 action 组装也开始继续下沉到 shared router
|
||||||
- `Inspector` 的 component section header 菜单已开始改成 callback/router 驱动,而不是在 widget 层硬编码动作
|
- `Inspector` 的 component section header 菜单已开始改成 callback/router 驱动,而不是在 widget 层硬编码动作
|
||||||
|
- `MenuBar` 的 File / View / Help / global shortcut 也开始继续下沉到 shared main-menu router
|
||||||
|
|
||||||
### 5. Dock / Layout 层
|
### 5. Dock / Layout 层
|
||||||
|
|
||||||
@@ -172,6 +173,8 @@
|
|||||||
- `Exit` 已通过事件驱动关闭 editor
|
- `Exit` 已通过事件驱动关闭 editor
|
||||||
- `Edit` 菜单已开始跟随 active action route 在 `Hierarchy / Project` 之间切换
|
- `Edit` 菜单已开始跟随 active action route 在 `Hierarchy / Project` 之间切换
|
||||||
- `Edit` 菜单与上下文快捷键开始共享同一套 edit action router
|
- `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
|
#pragma once
|
||||||
|
|
||||||
|
#include "AboutEditorDialog.h"
|
||||||
#include "BaseTheme.h"
|
#include "BaseTheme.h"
|
||||||
#include "ConsoleFilterState.h"
|
#include "ConsoleFilterState.h"
|
||||||
#include "ConsoleLogFormatter.h"
|
#include "ConsoleLogFormatter.h"
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include "PopupState.h"
|
#include "PopupState.h"
|
||||||
#include "PropertyGrid.h"
|
#include "PropertyGrid.h"
|
||||||
#include "ScalarControls.h"
|
#include "ScalarControls.h"
|
||||||
|
#include "SceneStatusWidget.h"
|
||||||
#include "StyleTokens.h"
|
#include "StyleTokens.h"
|
||||||
#include "VectorControls.h"
|
#include "VectorControls.h"
|
||||||
#include "Widgets.h"
|
#include "Widgets.h"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Core.h"
|
||||||
#include "StyleTokens.h"
|
#include "StyleTokens.h"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
#include "Actions/ActionRouting.h"
|
#include "Actions/ActionRouting.h"
|
||||||
#include "Actions/EditActionRouter.h"
|
#include "Actions/EditActionRouter.h"
|
||||||
#include "Actions/EditorActions.h"
|
#include "Actions/MainMenuActionRouter.h"
|
||||||
#include "Commands/SceneCommands.h"
|
|
||||||
#include "MenuBar.h"
|
#include "MenuBar.h"
|
||||||
#include "Core/EditorEvents.h"
|
|
||||||
#include "Core/EventBus.h"
|
|
||||||
#include "Core/IEditorContext.h"
|
#include "Core/IEditorContext.h"
|
||||||
#include "Core/ISceneManager.h"
|
|
||||||
#include "UI/UI.h"
|
#include "UI/UI.h"
|
||||||
#include <filesystem>
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
@@ -36,27 +31,12 @@ void MenuBar::HandleShortcuts() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Actions::ShortcutContext shortcutContext = Actions::GlobalShortcutContext();
|
Actions::HandleMainMenuShortcuts(*m_context, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::ShowFileMenu() {
|
void MenuBar::ShowFileMenu() {
|
||||||
UI::DrawMenuScope("File", [&]() {
|
UI::DrawMenuScope("File", [&]() {
|
||||||
Actions::DrawMenuAction(Actions::MakeNewSceneAction(), [&]() { Commands::NewScene(*m_context); });
|
Actions::DrawFileMenuActions(*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{});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,74 +48,25 @@ void MenuBar::ShowEditMenu() {
|
|||||||
|
|
||||||
void MenuBar::ShowViewMenu() {
|
void MenuBar::ShowViewMenu() {
|
||||||
UI::DrawMenuScope("View", [&]() {
|
UI::DrawMenuScope("View", [&]() {
|
||||||
Actions::DrawMenuAction(Actions::MakeResetLayoutAction(), [&]() {
|
Actions::DrawViewMenuActions(*m_context);
|
||||||
m_context->GetEventBus().Publish(DockLayoutResetRequestedEvent{});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::ShowHelpMenu() {
|
void MenuBar::ShowHelpMenu() {
|
||||||
UI::DrawMenuScope("Help", [&]() {
|
UI::DrawMenuScope("Help", [&]() {
|
||||||
Actions::DrawMenuAction(Actions::MakeAboutAction(), [&]() {
|
Actions::DrawHelpMenuActions(m_aboutPopup);
|
||||||
m_aboutPopup.RequestOpen();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::RenderAboutPopup() {
|
void MenuBar::RenderAboutPopup() {
|
||||||
m_aboutPopup.ConsumeOpenRequest("About XCEngine Editor");
|
UI::DrawEditorAboutDialog(m_context, m_aboutPopup);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::RenderSceneStatus() {
|
void MenuBar::RenderSceneStatus() {
|
||||||
if (!m_context) {
|
if (!m_context) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
UI::DrawSceneStatusWidget(*m_context);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user