Stabilize XCEditor shell foundation widgets
This commit is contained in:
102
new_editor/include/XCEditor/Core/UIEditorMenuSession.h
Normal file
102
new_editor/include/XCEditor/Core/UIEditorMenuSession.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/UI/Input/UIInputPath.h>
|
||||
#include <XCEngine/UI/Widgets/UIPopupOverlayModel.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine::UI::Editor {
|
||||
|
||||
struct UIEditorMenuPopupState {
|
||||
std::string popupId = {};
|
||||
std::string menuId = {};
|
||||
std::string itemId = {};
|
||||
|
||||
[[nodiscard]] bool IsRootPopup() const {
|
||||
return itemId.empty();
|
||||
}
|
||||
};
|
||||
|
||||
struct UIEditorMenuSessionMutationResult {
|
||||
bool changed = false;
|
||||
std::string openRootMenuId = {};
|
||||
std::string openedPopupId = {};
|
||||
std::vector<std::string> closedPopupIds = {};
|
||||
Widgets::UIPopupDismissReason dismissReason =
|
||||
Widgets::UIPopupDismissReason::None;
|
||||
|
||||
[[nodiscard]] bool HasOpenMenu() const {
|
||||
return !openRootMenuId.empty();
|
||||
}
|
||||
};
|
||||
|
||||
class UIEditorMenuSession {
|
||||
public:
|
||||
const Widgets::UIPopupOverlayModel& GetPopupOverlayModel() const {
|
||||
return m_popupOverlayModel;
|
||||
}
|
||||
|
||||
const std::vector<UIEditorMenuPopupState>& GetPopupStates() const {
|
||||
return m_popupStates;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& GetOpenSubmenuItemIds() const {
|
||||
return m_openSubmenuItemIds;
|
||||
}
|
||||
|
||||
std::string_view GetOpenRootMenuId() const {
|
||||
return m_openRootMenuId;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool HasOpenMenu() const {
|
||||
return !m_openRootMenuId.empty();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsMenuOpen(std::string_view menuId) const {
|
||||
return !m_openRootMenuId.empty() && m_openRootMenuId == menuId;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsPopupOpen(std::string_view popupId) const;
|
||||
|
||||
const UIEditorMenuPopupState* FindPopupState(std::string_view popupId) const;
|
||||
|
||||
void Reset();
|
||||
|
||||
UIEditorMenuSessionMutationResult OpenMenuBarRoot(
|
||||
std::string_view menuId,
|
||||
Widgets::UIPopupOverlayEntry entry);
|
||||
|
||||
UIEditorMenuSessionMutationResult HoverMenuBarRoot(
|
||||
std::string_view menuId,
|
||||
Widgets::UIPopupOverlayEntry entry);
|
||||
|
||||
UIEditorMenuSessionMutationResult HoverSubmenu(
|
||||
std::string_view itemId,
|
||||
Widgets::UIPopupOverlayEntry entry);
|
||||
|
||||
UIEditorMenuSessionMutationResult CloseAll(
|
||||
Widgets::UIPopupDismissReason dismissReason =
|
||||
Widgets::UIPopupDismissReason::Programmatic);
|
||||
|
||||
UIEditorMenuSessionMutationResult DismissFromEscape();
|
||||
UIEditorMenuSessionMutationResult DismissFromPointerDown(
|
||||
const UIInputPath& hitPath);
|
||||
UIEditorMenuSessionMutationResult DismissFromFocusLoss(
|
||||
const UIInputPath& focusedPath);
|
||||
|
||||
private:
|
||||
UIEditorMenuSessionMutationResult BuildResult(
|
||||
const Widgets::UIPopupOverlayMutationResult& mutation) const;
|
||||
|
||||
void RemoveClosedPopupStates(const std::vector<std::string>& closedPopupIds);
|
||||
void RebuildDerivedState();
|
||||
|
||||
std::string m_openRootMenuId = {};
|
||||
Widgets::UIPopupOverlayModel m_popupOverlayModel = {};
|
||||
std::vector<UIEditorMenuPopupState> m_popupStates = {};
|
||||
std::vector<std::string> m_openSubmenuItemIds = {};
|
||||
};
|
||||
|
||||
} // namespace XCEngine::UI::Editor
|
||||
160
new_editor/include/XCEditor/Widgets/UIEditorPanelFrame.h
Normal file
160
new_editor/include/XCEditor/Widgets/UIEditorPanelFrame.h
Normal file
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
namespace XCEngine::UI::Editor::Widgets {
|
||||
|
||||
enum class UIEditorPanelFrameAction : std::uint8_t {
|
||||
None = 0,
|
||||
Pin,
|
||||
Close
|
||||
};
|
||||
|
||||
enum class UIEditorPanelFrameHitTarget : std::uint8_t {
|
||||
None = 0,
|
||||
Header,
|
||||
Body,
|
||||
Footer,
|
||||
PinButton,
|
||||
CloseButton
|
||||
};
|
||||
|
||||
struct UIEditorPanelFrameState {
|
||||
bool active = false;
|
||||
bool hovered = false;
|
||||
bool focused = false;
|
||||
bool pinned = false;
|
||||
bool closable = true;
|
||||
bool pinnable = true;
|
||||
bool showFooter = false;
|
||||
bool pinHovered = false;
|
||||
bool closeHovered = false;
|
||||
};
|
||||
|
||||
struct UIEditorPanelFrameText {
|
||||
std::string_view title = {};
|
||||
std::string_view subtitle = {};
|
||||
std::string_view footer = {};
|
||||
};
|
||||
|
||||
struct UIEditorPanelFrameMetrics {
|
||||
float cornerRounding = 10.0f;
|
||||
float headerHeight = 36.0f;
|
||||
float footerHeight = 24.0f;
|
||||
float contentPadding = 12.0f;
|
||||
float titleInsetX = 14.0f;
|
||||
float titleInsetY = 9.0f;
|
||||
float subtitleInsetY = 22.0f;
|
||||
float footerInsetX = 14.0f;
|
||||
float footerInsetY = 6.0f;
|
||||
float actionButtonExtent = 18.0f;
|
||||
float actionInsetX = 12.0f;
|
||||
float actionGap = 6.0f;
|
||||
float baseBorderThickness = 1.0f;
|
||||
float hoveredBorderThickness = 1.25f;
|
||||
float activeBorderThickness = 1.5f;
|
||||
float focusedBorderThickness = 2.0f;
|
||||
};
|
||||
|
||||
struct UIEditorPanelFramePalette {
|
||||
::XCEngine::UI::UIColor surfaceColor =
|
||||
::XCEngine::UI::UIColor(0.16f, 0.16f, 0.16f, 1.0f);
|
||||
::XCEngine::UI::UIColor headerColor =
|
||||
::XCEngine::UI::UIColor(0.20f, 0.20f, 0.20f, 1.0f);
|
||||
::XCEngine::UI::UIColor footerColor =
|
||||
::XCEngine::UI::UIColor(0.19f, 0.19f, 0.19f, 1.0f);
|
||||
::XCEngine::UI::UIColor borderColor =
|
||||
::XCEngine::UI::UIColor(0.30f, 0.30f, 0.30f, 1.0f);
|
||||
::XCEngine::UI::UIColor hoveredBorderColor =
|
||||
::XCEngine::UI::UIColor(0.42f, 0.42f, 0.42f, 1.0f);
|
||||
::XCEngine::UI::UIColor activeBorderColor =
|
||||
::XCEngine::UI::UIColor(0.58f, 0.58f, 0.58f, 1.0f);
|
||||
::XCEngine::UI::UIColor focusedBorderColor =
|
||||
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
|
||||
::XCEngine::UI::UIColor textPrimary =
|
||||
::XCEngine::UI::UIColor(0.94f, 0.94f, 0.94f, 1.0f);
|
||||
::XCEngine::UI::UIColor textSecondary =
|
||||
::XCEngine::UI::UIColor(0.71f, 0.71f, 0.71f, 1.0f);
|
||||
::XCEngine::UI::UIColor textMuted =
|
||||
::XCEngine::UI::UIColor(0.60f, 0.60f, 0.60f, 1.0f);
|
||||
::XCEngine::UI::UIColor actionButtonColor =
|
||||
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
|
||||
::XCEngine::UI::UIColor actionButtonHoveredColor =
|
||||
::XCEngine::UI::UIColor(0.34f, 0.34f, 0.34f, 1.0f);
|
||||
::XCEngine::UI::UIColor actionButtonSelectedColor =
|
||||
::XCEngine::UI::UIColor(0.48f, 0.48f, 0.48f, 1.0f);
|
||||
::XCEngine::UI::UIColor actionButtonBorderColor =
|
||||
::XCEngine::UI::UIColor(0.52f, 0.52f, 0.52f, 1.0f);
|
||||
::XCEngine::UI::UIColor actionGlyphColor =
|
||||
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
|
||||
};
|
||||
|
||||
struct UIEditorPanelFrameLayout {
|
||||
::XCEngine::UI::UIRect frameRect = {};
|
||||
::XCEngine::UI::UIRect headerRect = {};
|
||||
::XCEngine::UI::UIRect bodyRect = {};
|
||||
::XCEngine::UI::UIRect footerRect = {};
|
||||
::XCEngine::UI::UIRect pinButtonRect = {};
|
||||
::XCEngine::UI::UIRect closeButtonRect = {};
|
||||
bool hasFooter = false;
|
||||
bool showPinButton = false;
|
||||
bool showCloseButton = false;
|
||||
};
|
||||
|
||||
bool IsUIEditorPanelFramePointInside(
|
||||
const ::XCEngine::UI::UIRect& rect,
|
||||
const ::XCEngine::UI::UIPoint& point);
|
||||
|
||||
bool IsUIEditorPanelFramePinButtonVisible(const UIEditorPanelFrameState& state);
|
||||
bool IsUIEditorPanelFrameCloseButtonVisible(const UIEditorPanelFrameState& state);
|
||||
|
||||
UIEditorPanelFrameLayout BuildUIEditorPanelFrameLayout(
|
||||
const ::XCEngine::UI::UIRect& frameRect,
|
||||
const UIEditorPanelFrameState& state,
|
||||
const UIEditorPanelFrameMetrics& metrics = {});
|
||||
|
||||
::XCEngine::UI::UIColor ResolveUIEditorPanelFrameBorderColor(
|
||||
const UIEditorPanelFrameState& state,
|
||||
const UIEditorPanelFramePalette& palette = {});
|
||||
|
||||
float ResolveUIEditorPanelFrameBorderThickness(
|
||||
const UIEditorPanelFrameState& state,
|
||||
const UIEditorPanelFrameMetrics& metrics = {});
|
||||
|
||||
UIEditorPanelFrameAction HitTestUIEditorPanelFrameAction(
|
||||
const UIEditorPanelFrameLayout& layout,
|
||||
const UIEditorPanelFrameState& state,
|
||||
const ::XCEngine::UI::UIPoint& point);
|
||||
|
||||
UIEditorPanelFrameHitTarget HitTestUIEditorPanelFrame(
|
||||
const UIEditorPanelFrameLayout& layout,
|
||||
const UIEditorPanelFrameState& state,
|
||||
const ::XCEngine::UI::UIPoint& point);
|
||||
|
||||
void AppendUIEditorPanelFrameBackground(
|
||||
::XCEngine::UI::UIDrawList& drawList,
|
||||
const UIEditorPanelFrameLayout& layout,
|
||||
const UIEditorPanelFrameState& state,
|
||||
const UIEditorPanelFramePalette& palette = {},
|
||||
const UIEditorPanelFrameMetrics& metrics = {});
|
||||
|
||||
void AppendUIEditorPanelFrameForeground(
|
||||
::XCEngine::UI::UIDrawList& drawList,
|
||||
const UIEditorPanelFrameLayout& layout,
|
||||
const UIEditorPanelFrameState& state,
|
||||
const UIEditorPanelFrameText& text,
|
||||
const UIEditorPanelFramePalette& palette = {},
|
||||
const UIEditorPanelFrameMetrics& metrics = {});
|
||||
|
||||
void AppendUIEditorPanelFrame(
|
||||
::XCEngine::UI::UIDrawList& drawList,
|
||||
const ::XCEngine::UI::UIRect& frameRect,
|
||||
const UIEditorPanelFrameState& state,
|
||||
const UIEditorPanelFrameText& text,
|
||||
const UIEditorPanelFramePalette& palette = {},
|
||||
const UIEditorPanelFrameMetrics& metrics = {});
|
||||
|
||||
} // namespace XCEngine::UI::Editor::Widgets
|
||||
157
new_editor/include/XCEditor/Widgets/UIEditorTabStrip.h
Normal file
157
new_editor/include/XCEditor/Widgets/UIEditorTabStrip.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
#include <XCEngine/UI/Layout/UITabStripLayout.h>
|
||||
#include <XCEngine/UI/Widgets/UITabStripModel.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine::UI::Editor::Widgets {
|
||||
|
||||
inline constexpr std::size_t UIEditorTabStripInvalidIndex =
|
||||
::XCEngine::UI::Widgets::UITabStripModel::InvalidIndex;
|
||||
|
||||
struct UIEditorTabStripItem {
|
||||
std::string tabId = {};
|
||||
std::string title = {};
|
||||
bool closable = true;
|
||||
float desiredHeaderLabelWidth = 0.0f;
|
||||
};
|
||||
|
||||
struct UIEditorTabStripState {
|
||||
std::size_t selectedIndex = UIEditorTabStripInvalidIndex;
|
||||
std::size_t hoveredIndex = UIEditorTabStripInvalidIndex;
|
||||
std::size_t closeHoveredIndex = UIEditorTabStripInvalidIndex;
|
||||
bool focused = false;
|
||||
};
|
||||
|
||||
struct UIEditorTabStripMetrics {
|
||||
::XCEngine::UI::Layout::UITabStripMetrics layoutMetrics =
|
||||
::XCEngine::UI::Layout::UITabStripMetrics{ 32.0f, 88.0f, 12.0f, 1.0f };
|
||||
float estimatedGlyphWidth = 7.0f;
|
||||
float closeButtonExtent = 14.0f;
|
||||
float closeButtonGap = 8.0f;
|
||||
float closeInsetRight = 12.0f;
|
||||
float closeInsetY = 0.0f;
|
||||
float labelInsetX = 12.0f;
|
||||
float labelInsetY = -1.0f;
|
||||
float baseBorderThickness = 1.0f;
|
||||
float selectedBorderThickness = 1.5f;
|
||||
float focusedBorderThickness = 2.0f;
|
||||
};
|
||||
|
||||
struct UIEditorTabStripPalette {
|
||||
::XCEngine::UI::UIColor stripBackgroundColor =
|
||||
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
|
||||
::XCEngine::UI::UIColor headerBackgroundColor =
|
||||
::XCEngine::UI::UIColor(0.20f, 0.20f, 0.20f, 1.0f);
|
||||
::XCEngine::UI::UIColor contentBackgroundColor =
|
||||
::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f);
|
||||
::XCEngine::UI::UIColor stripBorderColor =
|
||||
::XCEngine::UI::UIColor(0.30f, 0.30f, 0.30f, 1.0f);
|
||||
::XCEngine::UI::UIColor focusedBorderColor =
|
||||
::XCEngine::UI::UIColor(0.86f, 0.86f, 0.86f, 1.0f);
|
||||
::XCEngine::UI::UIColor tabColor =
|
||||
::XCEngine::UI::UIColor(0.23f, 0.23f, 0.23f, 1.0f);
|
||||
::XCEngine::UI::UIColor tabHoveredColor =
|
||||
::XCEngine::UI::UIColor(0.27f, 0.27f, 0.27f, 1.0f);
|
||||
::XCEngine::UI::UIColor tabSelectedColor =
|
||||
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
|
||||
::XCEngine::UI::UIColor tabBorderColor =
|
||||
::XCEngine::UI::UIColor(0.32f, 0.32f, 0.32f, 1.0f);
|
||||
::XCEngine::UI::UIColor tabHoveredBorderColor =
|
||||
::XCEngine::UI::UIColor(0.46f, 0.46f, 0.46f, 1.0f);
|
||||
::XCEngine::UI::UIColor tabSelectedBorderColor =
|
||||
::XCEngine::UI::UIColor(0.72f, 0.72f, 0.72f, 1.0f);
|
||||
::XCEngine::UI::UIColor textPrimary =
|
||||
::XCEngine::UI::UIColor(0.94f, 0.94f, 0.94f, 1.0f);
|
||||
::XCEngine::UI::UIColor textSecondary =
|
||||
::XCEngine::UI::UIColor(0.76f, 0.76f, 0.76f, 1.0f);
|
||||
::XCEngine::UI::UIColor textMuted =
|
||||
::XCEngine::UI::UIColor(0.60f, 0.60f, 0.60f, 1.0f);
|
||||
::XCEngine::UI::UIColor closeButtonColor =
|
||||
::XCEngine::UI::UIColor(0.25f, 0.25f, 0.25f, 1.0f);
|
||||
::XCEngine::UI::UIColor closeButtonHoveredColor =
|
||||
::XCEngine::UI::UIColor(0.36f, 0.36f, 0.36f, 1.0f);
|
||||
::XCEngine::UI::UIColor closeButtonBorderColor =
|
||||
::XCEngine::UI::UIColor(0.44f, 0.44f, 0.44f, 1.0f);
|
||||
::XCEngine::UI::UIColor closeGlyphColor =
|
||||
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
|
||||
};
|
||||
|
||||
struct UIEditorTabStripLayout {
|
||||
::XCEngine::UI::UIRect bounds = {};
|
||||
::XCEngine::UI::UIRect headerRect = {};
|
||||
::XCEngine::UI::UIRect contentRect = {};
|
||||
std::vector<::XCEngine::UI::UIRect> tabHeaderRects = {};
|
||||
std::vector<::XCEngine::UI::UIRect> closeButtonRects = {};
|
||||
std::vector<bool> showCloseButtons = {};
|
||||
std::size_t selectedIndex = UIEditorTabStripInvalidIndex;
|
||||
};
|
||||
|
||||
enum class UIEditorTabStripHitTargetKind : std::uint8_t {
|
||||
None = 0,
|
||||
HeaderBackground,
|
||||
Tab,
|
||||
CloseButton,
|
||||
Content
|
||||
};
|
||||
|
||||
struct UIEditorTabStripHitTarget {
|
||||
UIEditorTabStripHitTargetKind kind = UIEditorTabStripHitTargetKind::None;
|
||||
std::size_t index = UIEditorTabStripInvalidIndex;
|
||||
};
|
||||
|
||||
float ResolveUIEditorTabStripDesiredHeaderLabelWidth(
|
||||
const UIEditorTabStripItem& item,
|
||||
const UIEditorTabStripMetrics& metrics = {});
|
||||
|
||||
std::size_t ResolveUIEditorTabStripSelectedIndex(
|
||||
const std::vector<UIEditorTabStripItem>& items,
|
||||
std::string_view selectedTabId,
|
||||
std::size_t fallbackIndex = UIEditorTabStripInvalidIndex);
|
||||
|
||||
std::size_t ResolveUIEditorTabStripSelectedIndexAfterClose(
|
||||
std::size_t selectedIndex,
|
||||
std::size_t closedIndex,
|
||||
std::size_t itemCountBeforeClose);
|
||||
|
||||
UIEditorTabStripLayout BuildUIEditorTabStripLayout(
|
||||
const ::XCEngine::UI::UIRect& bounds,
|
||||
const std::vector<UIEditorTabStripItem>& items,
|
||||
const UIEditorTabStripState& state,
|
||||
const UIEditorTabStripMetrics& metrics = {});
|
||||
|
||||
UIEditorTabStripHitTarget HitTestUIEditorTabStrip(
|
||||
const UIEditorTabStripLayout& layout,
|
||||
const UIEditorTabStripState& state,
|
||||
const ::XCEngine::UI::UIPoint& point);
|
||||
|
||||
void AppendUIEditorTabStripBackground(
|
||||
::XCEngine::UI::UIDrawList& drawList,
|
||||
const UIEditorTabStripLayout& layout,
|
||||
const UIEditorTabStripState& state,
|
||||
const UIEditorTabStripPalette& palette = {},
|
||||
const UIEditorTabStripMetrics& metrics = {});
|
||||
|
||||
void AppendUIEditorTabStripForeground(
|
||||
::XCEngine::UI::UIDrawList& drawList,
|
||||
const UIEditorTabStripLayout& layout,
|
||||
const std::vector<UIEditorTabStripItem>& items,
|
||||
const UIEditorTabStripState& state,
|
||||
const UIEditorTabStripPalette& palette = {},
|
||||
const UIEditorTabStripMetrics& metrics = {});
|
||||
|
||||
void AppendUIEditorTabStrip(
|
||||
::XCEngine::UI::UIDrawList& drawList,
|
||||
const ::XCEngine::UI::UIRect& bounds,
|
||||
const std::vector<UIEditorTabStripItem>& items,
|
||||
const UIEditorTabStripState& state,
|
||||
const UIEditorTabStripPalette& palette = {},
|
||||
const UIEditorTabStripMetrics& metrics = {});
|
||||
|
||||
} // namespace XCEngine::UI::Editor::Widgets
|
||||
Reference in New Issue
Block a user