Files
XCEngine/docs/plan/used/XCEditor_Dock统一与Tab拖拽停靠收口计划_2026-04-10.md

12 KiB
Raw Blame History

XCEditor Dock统一与Tab拖拽停靠收口计划

日期:2026-04-10

1. 文档定位

这份计划只解决 XCEditor 当前 dock 基础层的两个核心问题:

  1. Hierarchy / InspectorScene / Game / Console / Project 顶部 chrome 不是同一套。
  2. tab 不能像旧 editor/ 的 ImGui docking 那样拖拽重排与调整停靠位置。

这两个问题本质上是同一个根问题:当前 DockHost 的叶子语义和渲染路径没有统一,导致视觉、命中、交互、布局变更都被拆成两套,后续再堆业务面板只会继续在错误基础上加复杂度。

本计划属于 Editor 基础层收口,不属于业务面板重建计划。 在这份计划完成前,不继续推进 new_editorProject / Hierarchy / Inspector / Console 业务重建。

2. 当前问题与根因

2.1 当前现象

  • Hierarchy / Inspector 的 header 仍然走 standalone panel 外壳。
  • Scene / Game / Console / Project 走 tab stack 外壳。
  • 用户看到的直接结果是tab 高度、内边距、标题区结构、可交互区域都不一致。
  • 用户尝试拖 tab 时,没有任何重排、合并、分裂停靠反馈。

2.2 当前真实根因

当前实现里同时存在两种叶子形态:

  • Panel
  • TabStack

这使得 DockHost 的整条链路都被拆成两套:

  • 布局输出分叉
  • 绘制分叉
  • hit test 分叉
  • 交互分叉
  • 未来的 docking mutation 也无从统一落点

当前代码里的直接证据:

  • new_editor/app/Shell/ProductShellAsset.cpp
  • new_editor/include/XCEditor/Shell/UIEditorDockHost.h
  • new_editor/src/Shell/UIEditorDockHost.cpp
  • new_editor/include/XCEditor/Shell/UIEditorDockHostInteraction.h
  • new_editor/src/Shell/UIEditorDockHostInteraction.cpp
  • new_editor/include/XCEditor/Collections/UIEditorTabStripInteraction.h
  • new_editor/src/Collections/UIEditorTabStripInteraction.cpp
  • new_editor/include/XCEditor/Shell/UIEditorWorkspaceController.h
  • new_editor/src/Shell/UIEditorWorkspaceController.cpp
  • new_editor/src/Shell/UIEditorWorkspaceLayoutPersistence.cpp

当前控制器层只具备:

  • OpenPanel
  • ClosePanel
  • ShowPanel
  • HidePanel
  • ActivatePanel
  • ResetWorkspace
  • SetSplitRatio

还没有真正支撑 docking 的命令与树变更能力:

  • ReorderTab
  • MoveTabToStack
  • DockTabRelative
  • ExtractTab
  • MergeTabStack

3. 改造目标

本轮收口后的目标状态如下:

  1. 运行态叶子节点只保留一种语义:TabStack
  2. 单面板也被视为“只有一个 tab 的 tab stack”。
  3. DockHost 只保留一套统一的 DockHeader / TabWell / ContentBody 视觉结构。
  4. Hierarchy / InspectorScene / Game / Console / Project 必须走同一套 header/tab primitive。
  5. tab 至少支持:
    • 同 stack 重排
    • 跨 stack 合并
    • 向目标 leaf 的 left/right/top/bottom/center 停靠
  6. 拖拽过程中必须有明确 preview不允许“拖了但没有反馈”。
  7. workspace 布局持久化必须覆盖新结构,并兼容旧布局升级。
  8. tests/UI/Editor 中补齐单元测试与集成测试后,才允许继续推进业务面板。

4. 范围边界

4.1 本轮必须做

  • XCEditor 的 dock 叶子语义统一
  • dock chrome 统一
  • tab 拖拽状态机
  • docking drop target 与 preview overlay
  • workspace tree surgery
  • layout persistence 升级
  • tests/UI/Editor 的回归补齐

4.2 本轮明确不做

  • 多原生窗口 detached docking
  • 浮动窗口系统
  • 业务面板内部复杂逻辑重建
  • Runtime UI 相关能力
  • Editor 再做一套资源化主题体系

Editor 当前继续采用固定代码样式,不走 UI 资源那套。

5. 目标结构

5.1 统一后的 workspace 叶子模型

运行态只保留:

  • SplitNode
  • TabStackNode

其中 TabStackNode 内部包含:

  • tabs
  • selectedTabId
  • activePanelId

不再保留“裸 Panel 叶子节点”这种视觉语义。

5.2 统一后的 dock 布局输出

DockHost 最终应面向统一 leaf 输出:

  • tabWellRect
  • contentBodyRect
  • selectedPanelId
  • tabItems
  • dropPreview

不再分成:

  • panelLayouts
  • tabStackLayouts

两套平行分支。

5.3 统一后的交互分层

交互链路收口为:

  1. UIEditorTabStripInteraction
    • 负责 tab press / armed / drag / release / cancel
  2. UIEditorDockHostInteraction
    • 负责把 tab 拖拽映射为 docking preview 与 docking command
  3. UIEditorWorkspaceController
    • 负责真正修改 workspace tree
  4. UIEditorWorkspaceLayoutPersistence
    • 负责新旧布局读写与升级

6. 分阶段执行计划

Phase A统一叶子语义

目标

把 workspace 运行态的叶子语义统一到 TabStackNode,彻底消除 standalone panel 叶子。

任务

  • 调整 UIEditorWorkspaceModel,明确叶子节点只允许 TabStackNode
  • 调整 ProductShellAsset 与默认 workspace 构建逻辑,让单面板默认也生成单-tab stack。
  • 调整 UIEditorWorkspaceSession,保证 active/selected 状态都围绕 tab stack 工作。
  • 调整 UIEditorWorkspaceLayoutPersistence,读旧格式时自动升级为统一 leaf 结构。
  • 增加 degenerate tree cleanup
    • 空 stack 删除
    • 单子 split 折叠
    • 非法 selectedTab 修正

完成标准

  • 运行态 workspace 中不再出现 standalone panel 叶子。
  • 旧布局能被自动升级并正常显示。

Phase B统一 dock chrome 与布局输出

目标

让所有 panel 顶部都走同一套 dock header / tab well primitive。

任务

  • 重构 UIEditorDockHost 的 layout 输出结构,改为统一 leaf 布局。
  • 删除 standalone panel 与 tab stack 的渲染分叉。
  • UIEditorPanelFrame 缩回“边框与 body 外壳”职责,不再自带独立 header 风格。
  • UIEditorTabStrip 成为唯一 tab/header 渲染入口。
  • UIEditorPanelContentHost 只根据统一 leaf layout 定位 panel body。
  • 统一 hit target 语义,保证 header/tab/body 命中都来自同一套结构。

完成标准

  • Hierarchy / Inspector / Scene / Game / Console / Project 顶部结构完全统一。
  • tab 高度、padding、命中区域、激活态样式只由一套 metric/palette 控制。

Phase C同 stack tab 拖拽重排

目标

先把最小闭环做稳:同一个 stack 内 tab 可拖拽重排。

任务

  • UIEditorTabStripInteraction 增加拖拽状态机:
    • pressed
    • armed
    • dragging
    • cancelled
    • committed
  • 增加 drag threshold、pointer capture、Esc cancel、release commit。
  • 在同 stack 内计算插入位置与 preview insertion marker。
  • UIEditorWorkspaceController 增加 ReorderTab(...)
  • 保证 selected/active/focus 状态在重排后仍然正确。

完成标准

  • 同一 tab strip 内可拖拽重排。
  • 有明确插入线 preview。
  • 无闪烁、无丢焦、无错误激活。

Phase D跨 stack 合并与 split docking

目标

把 tab 从“只能在本组重排”扩展到“可跨组移动并形成新停靠布局”。

任务

  • DockHostInteraction 中引入 drop target 解析:
    • center
    • left
    • right
    • top
    • bottom
    • root empty area
  • 增加 preview overlay
    • center merge 预览
    • edge split 高亮预览
    • 同 stack reorder 线性预览
  • WorkspaceController 中增加:
    • MoveTabToStack(...)
    • DockTabRelative(...)
    • ExtractTab(...)
    • MergeTabStack(...)
  • 增加 tree surgery
    • 从源 stack 抽 tab
    • 插入目标 stack
    • 围绕目标 leaf 生成 split
    • 空 stack 清理
    • 单子 split 折叠

完成标准

  • tab 可从一个 stack 拖到另一个 stack。
  • 可通过 left/right/top/bottom/center 形成新布局。
  • 交互有实时 preview。

Phase E持久化、回归与测试体系补齐

目标

把新 docking 结构正式纳入 tests/UI/Editor 的标准回归。

任务

  • 更新 layout serialization稳定写回统一 leaf 结构。
  • 旧布局读取时自动升级。
  • 补齐 tests/UI/Editor/unit
    • 旧布局升级
    • 同 stack reorder
    • 跨 stack merge
    • split docking
    • cleanup collapse
    • active/selected 同步
    • persistence round-trip
  • 补齐 tests/UI/Editor/integration
    • shell/dock_header_unified
    • shell/dock_tab_reorder_same_stack
    • shell/dock_tab_move_between_stacks
    • shell/dock_tab_split_targets
    • state/dock_layout_persistence
  • 每个集成测试 exe 顶部写清楚当前验证目标,不再只写模糊状态文本。

完成标准

  • tests/UI/Editor 对新 docking 具备完整回归入口。
  • 后续业务面板接入时,不需要再倒回头修基础 docking 架构。

7. 代码落点

本轮预计主要改动路径:

  • new_editor/include/XCEditor/Shell/UIEditorWorkspaceModel.h
  • new_editor/src/Shell/UIEditorWorkspaceModel.cpp
  • new_editor/include/XCEditor/Shell/UIEditorWorkspaceController.h
  • new_editor/src/Shell/UIEditorWorkspaceController.cpp
  • new_editor/include/XCEditor/Shell/UIEditorWorkspaceLayoutPersistence.h
  • new_editor/src/Shell/UIEditorWorkspaceLayoutPersistence.cpp
  • new_editor/include/XCEditor/Shell/UIEditorWorkspaceSession.h
  • new_editor/src/Shell/UIEditorWorkspaceSession.cpp
  • new_editor/include/XCEditor/Shell/UIEditorDockHost.h
  • new_editor/src/Shell/UIEditorDockHost.cpp
  • new_editor/include/XCEditor/Shell/UIEditorDockHostInteraction.h
  • new_editor/src/Shell/UIEditorDockHostInteraction.cpp
  • new_editor/include/XCEditor/Collections/UIEditorTabStripInteraction.h
  • new_editor/src/Collections/UIEditorTabStripInteraction.cpp
  • new_editor/include/XCEditor/Shell/UIEditorPanelFrame.h
  • new_editor/src/Shell/UIEditorPanelFrame.cpp
  • new_editor/include/XCEditor/Shell/UIEditorPanelContentHost.h
  • new_editor/src/Shell/UIEditorPanelContentHost.cpp
  • new_editor/app/Shell/ProductShellAsset.cpp
  • tests/UI/Editor/unit/*dock*
  • tests/UI/Editor/unit/*workspace*
  • tests/UI/Editor/integration/shell/*dock*
  • tests/UI/Editor/integration/state/layout_persistence/*

8. 并行拆分建议

这轮改造可以拆成 4 条可并行子线,但必须按主从顺序集成:

  1. WorkspaceModel / Controller / Persistence
  2. DockHost layout / render / hit-test 统一
  3. TabStripInteraction / DockHostInteraction 拖拽状态机
  4. tests/UI/Editor 单元与集成回归补齐

并行原则:

  • 先以 Phase A 的统一 leaf 语义为总前提。
  • Phase BPhase C 可以在统一模型落定后并行推进。
  • Phase E 可以在 Phase C / D 功能接口稳定后并行补齐。

9. 风险与控制

9.1 最大风险

  • 旧布局兼容被打断
  • 统一叶子后现有 panel body 定位错位
  • 拖拽状态机与 focus/capture 冲突
  • split tree surgery 产生退化树或悬空 active panel

9.2 控制方式

  • 先做模型统一,再做交互,不反过来堆补丁
  • 每个 mutation 先补 unit 再补 integration
  • 任何旧布局兼容问题都在 persistence 层处理,不在渲染层写兼容分叉
  • 任何单面板特殊视觉都回收为单-tab stack不再恢复 standalone panel 路径

10. 收口判定

只有同时满足以下条件,才算这轮 dock 基础层真正收口:

  1. 所有 dock 叶子统一为 TabStackNode
  2. Hierarchy / InspectorScene / Game / Console / Project 头部视觉完全统一。
  3. tab 可同组重排、跨组合并、左右上下停靠。
  4. 拖拽过程有稳定 preview释放后结果正确。
  5. 布局可持久化,旧布局可升级。
  6. tests/UI/Editor/unit + integration 已覆盖关键回归。

在这 6 条完成前,不进入下一轮业务面板重建。