3.4 KiB
3.4 KiB
SplitterChrome
命名空间: XCEngine::Editor::UI
类型: header-helper + enum class + struct
源文件: editor/src/UI/SplitterChrome.h
描述: 为编辑器面板提供统一的 splitter 主题颜色与拖拽分隔条绘制 / 交互结果。
概述
SplitterChrome.h 处理的是“两个区域之间如何被拖拽改变尺寸”这个问题。和 DividerChrome 不同,它不只是画一条视觉边界线,而是同时承担:
- 交互命中区域创建。
- hover / active 状态计算。
- 鼠标光标切换。
- 拖拽位移返回。
当前源码中,最直接的使用者是 ProjectPanel:左侧目录树和右侧资源浏览区之间的宽度调节完全依赖这层 helper。
公开 API
| 成员 | 说明 |
|---|---|
enum class SplitterAxis { Vertical, Horizontal } |
定义 splitter 的主轴方向。 |
struct SplitterResult |
返回当前 splitter 的 hover、active 与拖拽增量。 |
ApplySplitterThemeColors(ImVec4* colors) |
用当前 token 覆盖 ImGui separator / resize grip 相关颜色。 |
DrawSplitter(...) |
绘制 splitter 并返回本帧交互结果。 |
当前实现行为
按 editor/src/UI/SplitterChrome.h 的实现:
DrawSplitter(...)使用ImGui::InvisibleButton(...)创建命中区域。- 命中区域厚度默认来自
PanelSplitterHitThickness(),而真正画出来的线宽来自PanelSplitterVisibleThickness()。 - 当 splitter 处于 active 状态时:
- 纵向 splitter 返回
MouseDelta.x - 横向 splitter 返回
MouseDelta.y
- 纵向 splitter 返回
- hover 或 active 时会把鼠标指针切到
ResizeEW或ResizeNS。 - 它只返回“这一帧用户拖了多少”,并不直接修改任何布局变量;调用者必须自己把
delta累加到宽度 / 高度并做 clamp。
因此,这层是“交互采样 + 视觉呈现”,不是完整的布局管理器。
设计说明
把 splitter 从具体面板里抽出来是非常典型的商业编辑器实践:
- 面板只关心自己的布局状态,例如
m_navigationWidth。 - splitter helper 只关心拖拽命中、光标和线条绘制。
- 主题层通过
StyleTokens统一控制 splitter 粗细、颜色和命中区宽度。
这样 ProjectPanel、后续的多列 Inspector 或资源导入面板都能使用相同的分隔条行为,而不会出现每个面板“拖动手感都不一样”的问题。
典型用法
const UI::SplitterResult splitter =
UI::DrawSplitter("##ProjectPaneSplitter", UI::SplitterAxis::Vertical, totalHeight);
if (splitter.active) {
m_navigationWidth += splitter.delta;
}
调用者通常还应该把结果夹紧到合理区间,例如:
- 最小导航宽度
- 最小内容区宽度
线程语义
- 只能在 ImGui UI 线程使用。
- 每帧结果是即时的,不会自动跨帧缓存。
ApplySplitterThemeColors(...)修改的是调用方传入的颜色数组,通常应在同一帧、同一上下文中使用。
当前限制
- 当前只提供基础 hover / active 与位移返回,不提供吸附、双击重置、动画过渡等高级行为。
- 颜色仍然是静态 token,不支持运行时主题切换动画。
- 由调用者自己负责宽度约束和布局重算,没有更高层的布局容器抽象。