Build XCEditor editor shell compose foundation

This commit is contained in:
2026-04-07 06:30:34 +08:00
parent 3c0dedcc5f
commit 945420f3bd
11 changed files with 1109 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ add_library(XCUIEditorLib STATIC
src/Core/UIEditorMenuModel.cpp
src/Core/UIEditorMenuSession.cpp
src/Core/UIEditorPanelRegistry.cpp
src/Core/UIEditorShellCompose.cpp
src/Core/UIEditorShortcutManager.cpp
src/Core/UIEditorViewportInputBridge.cpp
src/Core/UIEditorViewportShell.cpp

View File

@@ -0,0 +1,95 @@
#pragma once
#include <XCEditor/Core/UIEditorWorkspaceCompose.h>
#include <XCEditor/Widgets/UIEditorMenuBar.h>
#include <XCEditor/Widgets/UIEditorStatusBar.h>
namespace XCEngine::UI::Editor {
struct UIEditorShellComposeModel {
std::vector<Widgets::UIEditorMenuBarItem> menuBarItems = {};
std::vector<Widgets::UIEditorStatusBarSegment> statusSegments = {};
std::vector<UIEditorWorkspacePanelPresentationModel> workspacePresentations = {};
};
struct UIEditorShellComposeState {
Widgets::UIEditorMenuBarState menuBarState = {};
UIEditorWorkspaceComposeState workspaceState = {};
Widgets::UIEditorStatusBarState statusBarState = {};
};
struct UIEditorShellComposeMetrics {
float outerPadding = 12.0f;
float sectionGap = 8.0f;
float surfaceCornerRounding = 10.0f;
Widgets::UIEditorMenuBarMetrics menuBarMetrics = {};
Widgets::UIEditorDockHostMetrics dockHostMetrics = {};
Widgets::UIEditorStatusBarMetrics statusBarMetrics = {};
};
struct UIEditorShellComposePalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor surfaceBorderColor =
::XCEngine::UI::UIColor(0.27f, 0.27f, 0.27f, 1.0f);
Widgets::UIEditorMenuBarPalette menuBarPalette = {};
Widgets::UIEditorDockHostPalette dockHostPalette = {};
Widgets::UIEditorStatusBarPalette statusBarPalette = {};
};
struct UIEditorShellComposeLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect contentRect = {};
::XCEngine::UI::UIRect menuBarRect = {};
::XCEngine::UI::UIRect workspaceRect = {};
::XCEngine::UI::UIRect statusBarRect = {};
Widgets::UIEditorMenuBarLayout menuBarLayout = {};
Widgets::UIEditorStatusBarLayout statusBarLayout = {};
};
struct UIEditorShellComposeRequest {
UIEditorShellComposeLayout layout = {};
UIEditorWorkspaceComposeRequest workspaceRequest = {};
};
struct UIEditorShellComposeFrame {
UIEditorShellComposeLayout layout = {};
UIEditorWorkspaceComposeFrame workspaceFrame = {};
};
UIEditorShellComposeLayout BuildUIEditorShellComposeLayout(
const ::XCEngine::UI::UIRect& bounds,
const std::vector<Widgets::UIEditorMenuBarItem>& menuBarItems,
const std::vector<Widgets::UIEditorStatusBarSegment>& statusSegments,
const UIEditorShellComposeMetrics& metrics = {});
UIEditorShellComposeRequest ResolveUIEditorShellComposeRequest(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
const UIEditorShellComposeModel& model,
const Widgets::UIEditorDockHostState& dockHostState = {},
const UIEditorShellComposeState& state = {},
const UIEditorShellComposeMetrics& metrics = {});
UIEditorShellComposeFrame UpdateUIEditorShellCompose(
UIEditorShellComposeState& state,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
const UIEditorShellComposeModel& model,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorDockHostState& dockHostState = {},
const UIEditorShellComposeMetrics& metrics = {});
void AppendUIEditorShellCompose(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorShellComposeFrame& frame,
const UIEditorShellComposeModel& model,
const UIEditorShellComposeState& state,
const UIEditorShellComposePalette& palette = {},
const UIEditorShellComposeMetrics& metrics = {});
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,214 @@
#include <XCEditor/Core/UIEditorShellCompose.h>
#include <algorithm>
namespace XCEngine::UI::Editor {
namespace {
using ::XCEngine::UI::UIRect;
using Widgets::AppendUIEditorMenuBarBackground;
using Widgets::AppendUIEditorMenuBarForeground;
using Widgets::AppendUIEditorStatusBarBackground;
using Widgets::AppendUIEditorStatusBarForeground;
using Widgets::BuildUIEditorMenuBarLayout;
using Widgets::BuildUIEditorStatusBarLayout;
float ClampNonNegative(float value) {
return (std::max)(value, 0.0f);
}
UIRect InsetRect(const UIRect& rect, float inset) {
const float clampedInset = ClampNonNegative(inset);
const float insetX = (std::min)(clampedInset, rect.width * 0.5f);
const float insetY = (std::min)(clampedInset, rect.height * 0.5f);
return UIRect(
rect.x + insetX,
rect.y + insetY,
(std::max)(0.0f, rect.width - insetX * 2.0f),
(std::max)(0.0f, rect.height - insetY * 2.0f));
}
} // namespace
UIEditorShellComposeLayout BuildUIEditorShellComposeLayout(
const UIRect& bounds,
const std::vector<Widgets::UIEditorMenuBarItem>& menuBarItems,
const std::vector<Widgets::UIEditorStatusBarSegment>& statusSegments,
const UIEditorShellComposeMetrics& metrics) {
UIEditorShellComposeLayout layout = {};
layout.bounds = UIRect(
bounds.x,
bounds.y,
ClampNonNegative(bounds.width),
ClampNonNegative(bounds.height));
layout.contentRect = InsetRect(layout.bounds, metrics.outerPadding);
const float menuBarHeight = ClampNonNegative(metrics.menuBarMetrics.barHeight);
const float statusBarHeight = ClampNonNegative(metrics.statusBarMetrics.barHeight);
const float sectionGap = ClampNonNegative(metrics.sectionGap);
const float availableHeight = layout.contentRect.height;
const float combinedBars = menuBarHeight + statusBarHeight;
const float gapBudget = combinedBars > 0.0f ? sectionGap * 2.0f : 0.0f;
const float clampedGapBudget = (std::min)(gapBudget, availableHeight);
const float workspaceHeight =
(std::max)(0.0f, availableHeight - combinedBars - clampedGapBudget);
float cursorY = layout.contentRect.y;
if (menuBarHeight > 0.0f) {
layout.menuBarRect = UIRect(
layout.contentRect.x,
cursorY,
layout.contentRect.width,
menuBarHeight);
cursorY += menuBarHeight + sectionGap;
}
layout.workspaceRect = UIRect(
layout.contentRect.x,
cursorY,
layout.contentRect.width,
workspaceHeight);
if (statusBarHeight > 0.0f) {
layout.statusBarRect = UIRect(
layout.contentRect.x,
layout.contentRect.y + layout.contentRect.height - statusBarHeight,
layout.contentRect.width,
statusBarHeight);
}
layout.menuBarLayout =
BuildUIEditorMenuBarLayout(layout.menuBarRect, menuBarItems, metrics.menuBarMetrics);
layout.statusBarLayout =
BuildUIEditorStatusBarLayout(layout.statusBarRect, statusSegments, metrics.statusBarMetrics);
return layout;
}
UIEditorShellComposeRequest ResolveUIEditorShellComposeRequest(
const UIRect& bounds,
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
const UIEditorShellComposeModel& model,
const Widgets::UIEditorDockHostState& dockHostState,
const UIEditorShellComposeState& state,
const UIEditorShellComposeMetrics& metrics) {
UIEditorShellComposeRequest request = {};
request.layout = BuildUIEditorShellComposeLayout(
bounds,
model.menuBarItems,
model.statusSegments,
metrics);
request.workspaceRequest = ResolveUIEditorWorkspaceComposeRequest(
request.layout.workspaceRect,
panelRegistry,
workspace,
session,
model.workspacePresentations,
dockHostState,
metrics.dockHostMetrics);
request.layout.menuBarLayout = BuildUIEditorMenuBarLayout(
request.layout.menuBarRect,
model.menuBarItems,
metrics.menuBarMetrics);
request.layout.statusBarLayout = BuildUIEditorStatusBarLayout(
request.layout.statusBarRect,
model.statusSegments,
metrics.statusBarMetrics);
(void)state;
return request;
}
UIEditorShellComposeFrame UpdateUIEditorShellCompose(
UIEditorShellComposeState& state,
const UIRect& bounds,
const UIEditorPanelRegistry& panelRegistry,
const UIEditorWorkspaceModel& workspace,
const UIEditorWorkspaceSession& session,
const UIEditorShellComposeModel& model,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorDockHostState& dockHostState,
const UIEditorShellComposeMetrics& metrics) {
UIEditorShellComposeFrame frame = {};
frame.layout = BuildUIEditorShellComposeLayout(
bounds,
model.menuBarItems,
model.statusSegments,
metrics);
frame.workspaceFrame = UpdateUIEditorWorkspaceCompose(
state.workspaceState,
frame.layout.workspaceRect,
panelRegistry,
workspace,
session,
model.workspacePresentations,
inputEvents,
dockHostState,
metrics.dockHostMetrics);
frame.layout.menuBarLayout = BuildUIEditorMenuBarLayout(
frame.layout.menuBarRect,
model.menuBarItems,
metrics.menuBarMetrics);
frame.layout.statusBarLayout = BuildUIEditorStatusBarLayout(
frame.layout.statusBarRect,
model.statusSegments,
metrics.statusBarMetrics);
return frame;
}
void AppendUIEditorShellCompose(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorShellComposeFrame& frame,
const UIEditorShellComposeModel& model,
const UIEditorShellComposeState& state,
const UIEditorShellComposePalette& palette,
const UIEditorShellComposeMetrics& metrics) {
drawList.AddFilledRect(
frame.layout.bounds,
palette.surfaceColor,
metrics.surfaceCornerRounding);
drawList.AddRectOutline(
frame.layout.bounds,
palette.surfaceBorderColor,
1.0f,
metrics.surfaceCornerRounding);
AppendUIEditorMenuBarBackground(
drawList,
frame.layout.menuBarLayout,
model.menuBarItems,
state.menuBarState,
palette.menuBarPalette,
metrics.menuBarMetrics);
AppendUIEditorMenuBarForeground(
drawList,
frame.layout.menuBarLayout,
model.menuBarItems,
state.menuBarState,
palette.menuBarPalette,
metrics.menuBarMetrics);
AppendUIEditorWorkspaceCompose(
drawList,
frame.workspaceFrame,
palette.dockHostPalette,
metrics.dockHostMetrics);
AppendUIEditorStatusBarBackground(
drawList,
frame.layout.statusBarLayout,
model.statusSegments,
state.statusBarState,
palette.statusBarPalette,
metrics.statusBarMetrics);
AppendUIEditorStatusBarForeground(
drawList,
frame.layout.statusBarLayout,
model.statusSegments,
state.statusBarState,
palette.statusBarPalette,
metrics.statusBarMetrics);
}
} // namespace XCEngine::UI::Editor