Build XCEditor menu and status shell widgets

This commit is contained in:
2026-04-07 03:51:26 +08:00
parent 5f9f3386ab
commit 8eeb7af56e
25 changed files with 3708 additions and 106 deletions

View File

@@ -64,6 +64,10 @@ public:
void Reset();
UIEditorMenuSessionMutationResult OpenRootMenu(
std::string_view menuId,
Widgets::UIPopupOverlayEntry entry);
UIEditorMenuSessionMutationResult OpenMenuBarRoot(
std::string_view menuId,
Widgets::UIPopupOverlayEntry entry);

View File

@@ -0,0 +1,120 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace XCEngine::UI::Editor::Widgets {
inline constexpr std::size_t UIEditorMenuBarInvalidIndex =
static_cast<std::size_t>(-1);
struct UIEditorMenuBarItem {
std::string menuId = {};
std::string label = {};
bool enabled = true;
float desiredLabelWidth = 0.0f;
};
struct UIEditorMenuBarState {
std::size_t openIndex = UIEditorMenuBarInvalidIndex;
std::size_t hoveredIndex = UIEditorMenuBarInvalidIndex;
bool focused = false;
};
struct UIEditorMenuBarMetrics {
float barHeight = 34.0f;
float horizontalInset = 10.0f;
float verticalInset = 4.0f;
float buttonGap = 6.0f;
float buttonPaddingX = 14.0f;
float estimatedGlyphWidth = 7.0f;
float labelInsetY = -1.0f;
float barCornerRounding = 8.0f;
float buttonCornerRounding = 7.0f;
float baseBorderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
float openBorderThickness = 1.5f;
};
struct UIEditorMenuBarPalette {
::XCEngine::UI::UIColor barColor =
::XCEngine::UI::UIColor(0.16f, 0.16f, 0.16f, 1.0f);
::XCEngine::UI::UIColor buttonColor =
::XCEngine::UI::UIColor(0.23f, 0.23f, 0.23f, 1.0f);
::XCEngine::UI::UIColor buttonHoveredColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor buttonOpenColor =
::XCEngine::UI::UIColor(0.35f, 0.35f, 0.35f, 1.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.30f, 0.30f, 0.30f, 1.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor openBorderColor =
::XCEngine::UI::UIColor(0.68f, 0.68f, 0.68f, 1.0f);
::XCEngine::UI::UIColor textPrimary =
::XCEngine::UI::UIColor(0.94f, 0.94f, 0.94f, 1.0f);
::XCEngine::UI::UIColor textMuted =
::XCEngine::UI::UIColor(0.74f, 0.74f, 0.74f, 1.0f);
::XCEngine::UI::UIColor textDisabled =
::XCEngine::UI::UIColor(0.52f, 0.52f, 0.52f, 1.0f);
};
struct UIEditorMenuBarLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect contentRect = {};
std::vector<::XCEngine::UI::UIRect> buttonRects = {};
};
enum class UIEditorMenuBarHitTargetKind : std::uint8_t {
None = 0,
BarBackground,
Button
};
struct UIEditorMenuBarHitTarget {
UIEditorMenuBarHitTargetKind kind = UIEditorMenuBarHitTargetKind::None;
std::size_t index = UIEditorMenuBarInvalidIndex;
};
float ResolveUIEditorMenuBarDesiredButtonWidth(
const UIEditorMenuBarItem& item,
const UIEditorMenuBarMetrics& metrics = {});
UIEditorMenuBarLayout BuildUIEditorMenuBarLayout(
const ::XCEngine::UI::UIRect& bounds,
const std::vector<UIEditorMenuBarItem>& items,
const UIEditorMenuBarMetrics& metrics = {});
UIEditorMenuBarHitTarget HitTestUIEditorMenuBar(
const UIEditorMenuBarLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorMenuBarBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorMenuBarLayout& layout,
const std::vector<UIEditorMenuBarItem>& items,
const UIEditorMenuBarState& state,
const UIEditorMenuBarPalette& palette = {},
const UIEditorMenuBarMetrics& metrics = {});
void AppendUIEditorMenuBarForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorMenuBarLayout& layout,
const std::vector<UIEditorMenuBarItem>& items,
const UIEditorMenuBarState& state,
const UIEditorMenuBarPalette& palette = {},
const UIEditorMenuBarMetrics& metrics = {});
void AppendUIEditorMenuBar(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<UIEditorMenuBarItem>& items,
const UIEditorMenuBarState& state,
const UIEditorMenuBarPalette& palette = {},
const UIEditorMenuBarMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,134 @@
#pragma once
#include <XCEditor/Core/UIEditorMenuModel.h>
#include <XCEngine/UI/DrawData.h>
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor::Widgets {
inline constexpr std::size_t UIEditorMenuPopupInvalidIndex =
static_cast<std::size_t>(-1);
struct UIEditorMenuPopupItem {
std::string itemId = {};
::XCEngine::UI::Editor::UIEditorMenuItemKind kind =
::XCEngine::UI::Editor::UIEditorMenuItemKind::Command;
std::string label = {};
std::string shortcutText = {};
bool enabled = true;
bool checked = false;
bool hasSubmenu = false;
float desiredLabelWidth = 0.0f;
float desiredShortcutWidth = 0.0f;
};
struct UIEditorMenuPopupState {
std::size_t hoveredIndex = UIEditorMenuPopupInvalidIndex;
std::size_t submenuOpenIndex = UIEditorMenuPopupInvalidIndex;
bool focused = false;
};
struct UIEditorMenuPopupMetrics {
float contentPaddingX = 6.0f;
float contentPaddingY = 6.0f;
float itemHeight = 28.0f;
float separatorHeight = 9.0f;
float checkColumnWidth = 18.0f;
float shortcutGap = 20.0f;
float submenuIndicatorWidth = 14.0f;
float rowCornerRounding = 5.0f;
float popupCornerRounding = 8.0f;
float labelInsetX = 14.0f;
float labelInsetY = -1.0f;
float shortcutInsetRight = 24.0f;
float estimatedGlyphWidth = 7.0f;
float separatorThickness = 1.0f;
float borderThickness = 1.0f;
};
struct UIEditorMenuPopupPalette {
::XCEngine::UI::UIColor popupColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.31f, 0.31f, 0.31f, 1.0f);
::XCEngine::UI::UIColor itemHoverColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor itemOpenColor =
::XCEngine::UI::UIColor(0.34f, 0.34f, 0.34f, 1.0f);
::XCEngine::UI::UIColor separatorColor =
::XCEngine::UI::UIColor(0.32f, 0.32f, 0.32f, 1.0f);
::XCEngine::UI::UIColor textPrimary =
::XCEngine::UI::UIColor(0.94f, 0.94f, 0.94f, 1.0f);
::XCEngine::UI::UIColor textMuted =
::XCEngine::UI::UIColor(0.76f, 0.76f, 0.76f, 1.0f);
::XCEngine::UI::UIColor textDisabled =
::XCEngine::UI::UIColor(0.50f, 0.50f, 0.50f, 1.0f);
::XCEngine::UI::UIColor glyphColor =
::XCEngine::UI::UIColor(0.90f, 0.90f, 0.90f, 1.0f);
};
struct UIEditorMenuPopupLayout {
::XCEngine::UI::UIRect popupRect = {};
::XCEngine::UI::UIRect contentRect = {};
std::vector<::XCEngine::UI::UIRect> itemRects = {};
};
enum class UIEditorMenuPopupHitTargetKind : std::uint8_t {
None = 0,
PopupSurface,
Item
};
struct UIEditorMenuPopupHitTarget {
UIEditorMenuPopupHitTargetKind kind = UIEditorMenuPopupHitTargetKind::None;
std::size_t index = UIEditorMenuPopupInvalidIndex;
};
float ResolveUIEditorMenuPopupDesiredWidth(
const std::vector<UIEditorMenuPopupItem>& items,
const UIEditorMenuPopupMetrics& metrics = {});
float MeasureUIEditorMenuPopupHeight(
const std::vector<UIEditorMenuPopupItem>& items,
const UIEditorMenuPopupMetrics& metrics = {});
UIEditorMenuPopupLayout BuildUIEditorMenuPopupLayout(
const ::XCEngine::UI::UIRect& popupRect,
const std::vector<UIEditorMenuPopupItem>& items,
const UIEditorMenuPopupMetrics& metrics = {});
UIEditorMenuPopupHitTarget HitTestUIEditorMenuPopup(
const UIEditorMenuPopupLayout& layout,
const std::vector<UIEditorMenuPopupItem>& items,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorMenuPopupBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorMenuPopupLayout& layout,
const std::vector<UIEditorMenuPopupItem>& items,
const UIEditorMenuPopupState& state,
const UIEditorMenuPopupPalette& palette = {},
const UIEditorMenuPopupMetrics& metrics = {});
void AppendUIEditorMenuPopupForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorMenuPopupLayout& layout,
const std::vector<UIEditorMenuPopupItem>& items,
const UIEditorMenuPopupState& state,
const UIEditorMenuPopupPalette& palette = {},
const UIEditorMenuPopupMetrics& metrics = {});
void AppendUIEditorMenuPopup(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& popupRect,
const std::vector<UIEditorMenuPopupItem>& items,
const UIEditorMenuPopupState& state,
const UIEditorMenuPopupPalette& palette = {},
const UIEditorMenuPopupMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,144 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace XCEngine::UI::Editor::Widgets {
inline constexpr std::size_t UIEditorStatusBarInvalidIndex =
static_cast<std::size_t>(-1);
enum class UIEditorStatusBarSlot : std::uint8_t {
Leading = 0,
Trailing
};
enum class UIEditorStatusBarTextTone : std::uint8_t {
Primary = 0,
Muted,
Accent
};
enum class UIEditorStatusBarHitTargetKind : std::uint8_t {
None = 0,
Background,
Segment,
Separator
};
struct UIEditorStatusBarSegment {
std::string segmentId = {};
std::string label = {};
UIEditorStatusBarSlot slot = UIEditorStatusBarSlot::Leading;
UIEditorStatusBarTextTone tone = UIEditorStatusBarTextTone::Primary;
bool interactive = true;
bool showSeparator = false;
float desiredWidth = 0.0f;
};
struct UIEditorStatusBarState {
std::size_t hoveredIndex = UIEditorStatusBarInvalidIndex;
std::size_t activeIndex = UIEditorStatusBarInvalidIndex;
bool focused = false;
};
struct UIEditorStatusBarMetrics {
float barHeight = 28.0f;
float outerPaddingX = 10.0f;
float segmentPaddingX = 10.0f;
float segmentPaddingY = 6.0f;
float segmentGap = 4.0f;
float separatorWidth = 1.0f;
float separatorInsetY = 6.0f;
float slotGapMin = 18.0f;
float cornerRounding = 8.0f;
float estimatedGlyphWidth = 7.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 1.5f;
};
struct UIEditorStatusBarPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.78f, 0.78f, 0.78f, 1.0f);
::XCEngine::UI::UIColor segmentColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor segmentHoveredColor =
::XCEngine::UI::UIColor(0.23f, 0.23f, 0.23f, 1.0f);
::XCEngine::UI::UIColor segmentActiveColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor segmentBorderColor =
::XCEngine::UI::UIColor(0.35f, 0.35f, 0.35f, 1.0f);
::XCEngine::UI::UIColor separatorColor =
::XCEngine::UI::UIColor(0.32f, 0.32f, 0.32f, 1.0f);
::XCEngine::UI::UIColor textPrimary =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor textMuted =
::XCEngine::UI::UIColor(0.66f, 0.66f, 0.66f, 1.0f);
::XCEngine::UI::UIColor textAccent =
::XCEngine::UI::UIColor(0.94f, 0.94f, 0.94f, 1.0f);
};
struct UIEditorStatusBarLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect leadingSlotRect = {};
::XCEngine::UI::UIRect trailingSlotRect = {};
std::vector<::XCEngine::UI::UIRect> segmentRects = {};
std::vector<::XCEngine::UI::UIRect> separatorRects = {};
};
struct UIEditorStatusBarHitTarget {
UIEditorStatusBarHitTargetKind kind = UIEditorStatusBarHitTargetKind::None;
std::size_t index = UIEditorStatusBarInvalidIndex;
};
float ResolveUIEditorStatusBarDesiredSegmentWidth(
const UIEditorStatusBarSegment& segment,
const UIEditorStatusBarMetrics& metrics = {});
UIEditorStatusBarLayout BuildUIEditorStatusBarLayout(
const ::XCEngine::UI::UIRect& bounds,
const std::vector<UIEditorStatusBarSegment>& segments,
const UIEditorStatusBarMetrics& metrics = {});
UIEditorStatusBarHitTarget HitTestUIEditorStatusBar(
const UIEditorStatusBarLayout& layout,
const ::XCEngine::UI::UIPoint& point);
::XCEngine::UI::UIColor ResolveUIEditorStatusBarTextColor(
UIEditorStatusBarTextTone tone,
const UIEditorStatusBarPalette& palette = {});
void AppendUIEditorStatusBarBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorStatusBarLayout& layout,
const std::vector<UIEditorStatusBarSegment>& segments,
const UIEditorStatusBarState& state,
const UIEditorStatusBarPalette& palette = {},
const UIEditorStatusBarMetrics& metrics = {});
void AppendUIEditorStatusBarForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorStatusBarLayout& layout,
const std::vector<UIEditorStatusBarSegment>& segments,
const UIEditorStatusBarState& state,
const UIEditorStatusBarPalette& palette = {},
const UIEditorStatusBarMetrics& metrics = {});
void AppendUIEditorStatusBar(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<UIEditorStatusBarSegment>& segments,
const UIEditorStatusBarState& state,
const UIEditorStatusBarPalette& palette = {},
const UIEditorStatusBarMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets