Files
XCEngine/docs/api/XCEngine/Editor/UI/SplitterChrome/SplitterChrome.md
2026-03-29 01:36:53 +08:00

3.4 KiB
Raw Blame History

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
  • hover 或 active 时会把鼠标指针切到 ResizeEWResizeNS
  • 它只返回“这一帧用户拖了多少”,并不直接修改任何布局变量;调用者必须自己把 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不支持运行时主题切换动画。
  • 由调用者自己负责宽度约束和布局重算,没有更高层的布局容器抽象。

相关文档