Files
StellarX-kaifa/开发记录/模块/Module-20260415-0003-布局系统第二阶段收口.md
T

158 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 新增功能模块 / 模块重构
> 适用场景:新增模块、重大模块重构、核心架构能力演进。
> 不适用场景:小接口或轻量功能变更,请使用“功能变更”模板。
## 基本信息
- 模块 IDModule-20260415-0003
- 模块名称: 布局系统第二阶段收口
- 状态:已完成
- 类型:模块重构
- 所属系统 / 子系统: GUI 框架 / Layout
- 版本 / 分支: 当前工作区 / 下一版本开发中
- 环境: Windows + EasyX
- 负责人: Codex 协作修改
## 背景与目标
- 背景:
- 第一阶段已经完成统一布局链路打通,但几何写入口、内容驱动控件规则、复合控件职责边界仍有残留混用。
- `Label` 曾在 `draw()` 阶段临时决定尺寸,`TabControl``Canvas` 在子树几何映射上也存在职责重叠。
- `WM_MOUSEMOVE` 的容器分发和局部重绘合成,在复杂遮挡场景下容易暴露 hover/tooltip 与 overlay 残留问题。
- 当前痛点:
- 几何语义还不够制度化,后续继续演进布局系统时容易再次混回“draw 阶段改几何”。
- 内容驱动控件和复合控件没有完全落成可解释的边界。
- 局部重绘与上层兄弟补画机制不完整时,会直接破坏遮挡正确性。
- 目标:
- 收口几何写入口语义,明确公开 setter、统一布局应用路径、内容驱动路径、显式设计基线提交。
- 收口 `Label / Table` 的内容驱动规则与设计基线边界。
- 收口 `TabControl / Canvas` 的职责边界,不重写页签系统,但消除页内子控件手工回填。
- 建立轻量级鼠标瞬时状态清理路径和 overlay 补画机制,保证 hover / tooltip / 局部重绘链正确。
- 非目标:[可选]
- 不做字体缩放。
- 不做 `Table` 纵向拉伸。
- 不做 `Dialog` 旧 synthetic move 机制统一。
- 不做 `Table` 内部局部重绘体系。
## 模块边界
- 职责:
- 定义并收口布局系统第二阶段的运行态 / 设计态几何语义。
- 为当前主线控件显式写出能力边界和默认策略。
- 收口局部重绘下的 overlay 补画规则。
- 不负责什么:
- 不扩展新的布局表达能力。
- 不处理字体、图标、DPI 自适应。
- 不把所有控件都改造成内容驱动或局部重绘型复合控件。
- 外部依赖:
- EasyX 绘制环境
- 现有 `Control / Window / Canvas / TabControl / Table / Label / Button` 体系
- 对外能力 / API:
- 保留 `setLayoutMode(...)`
- 保留 `setAnchor(a1, a2)`
- 保留 `commitCurrentGeometryAsDesignRect()`
- `Label::textStyle` 继续保持公开,但要求样式修改后显式 `setDirty(true)`
- 关键数据 / 状态:
- `localx / localy / localWidth / localHeight`
- `x / y / width / height`
- `LayoutSpec / LayoutCapability / ResolvedLayoutRect`
- `eventVisualChanged`
## 设计说明
- 核心流程:
- 先在父局部坐标系内完成统一布局解算。
- 再由内部受控路径把运行态矩形应用到控件。
- 内容驱动控件在自己的受控路径里刷新运行态尺寸。
- 局部重绘提交后,由父容器按实际绘制顺序补画 coverage 上方的 overlay 兄弟。
- 关键对象 / 类关系:
- [`Control`](D:/programming/imGUI-easyX/imGui-easyX/Control.h):几何语义、解算入口、设计基线提交入口。
- [`Label`](D:/programming/imGUI-easyX/imGui-easyX/Label.cpp):内容驱动尺寸,`draw()` 只消费运行态矩形。
- [`Canvas`](D:/programming/imGUI-easyX/imGui-easyX/Canvas.cpp):管理直接子控件的世界坐标映射与局部 overlay 补画。
- [`TabControl`](D:/programming/imGUI-easyX/imGui-easyX/TabControl.cpp):外层接统一解算,内部页签栏 / 页面区继续自管。
- [`Table`](D:/programming/imGUI-easyX/imGui-easyX/Table.cpp):当前版本 `X Stretch / Y Fixed`,并保留内部受控结构尺寸基线刷新。
- [`Window`](D:/programming/imGUI-easyX/imGui-easyX/Window.cpp):顶层托管重绘收口与 overlay 兄弟补画。
- 生命周期:
- 普通 resize / 父容器重排不自动回写 `local*`
- 显式设计基线提交只通过 `commitCurrentGeometryAsDesignRect()` 或控件内部受控结构刷新点发生。
- 内容驱动尺寸刷新优先发生在 `draw()` 之前。
- 事件 / 渲染 / 数据流:[按模块类型填写]
- `WM_MOUSEMOVE`:第一个命中的兄弟收到真实消息,后续兄弟只清理瞬时鼠标状态。
- 局部重绘:先画本次 dirty 单元,再补画 coverage 上方相交 overlay。
- 运行态几何:统一解算或内容驱动路径写入;设计基线不自动漂移。
- 关键不变量:
- `local*` 始终表示设计态父局部矩形。
- `x / y / width / height` 始终表示运行态绘制矩形。
- `draw()` 不再承担新的几何决策入口。
- `Table` 当前版本 `Y Fixed` 是实现边界,不是永久产品结论。
- 降级 / 回退策略:[可选]
- Stretch 条件不满足时自然降级为固定尺寸位置策略。
- 控件能力边界禁止 Stretch 时,通过日志输出拦截原因。
## 实现与影响
- 关键实现点:
- 在 [`Control.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Control.cpp) 增加布局降级日志、能力边界拦截日志、显式设计基线提交日志。
- 在 [`Label.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Label.cpp) 收口内容驱动尺寸刷新,并显式关闭双轴 Stretch。
- 在 [`Canvas.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Canvas.cpp)、[`TabControl.cpp`](D:/programming/imGUI-easyX/imGui-easyX/TabControl.cpp)、[`Window.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Window.cpp) 收口 overlay 补画。
- 在 [`Table.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Table.cpp) 收口 `Y Fixed`、分页按钮视觉链与页码重绘。
- 涉及文件 / 类 / 函数:
- [`Control.h`](D:/programming/imGUI-easyX/imGui-easyX/Control.h)
- [`Control.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Control.cpp)
- [`Label.h`](D:/programming/imGUI-easyX/imGui-easyX/Label.h)
- [`Label.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Label.cpp)
- [`Canvas.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Canvas.cpp)
- [`TabControl.cpp`](D:/programming/imGUI-easyX/imGui-easyX/TabControl.cpp)
- [`Table.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Table.cpp)
- [`TextBox.cpp`](D:/programming/imGUI-easyX/imGui-easyX/TextBox.cpp)
- [`Dialog.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Dialog.cpp)
- [`Window.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Window.cpp)
- 兼容性影响:
- 对旧锚点 API 保持兼容。
- `Label::textStyle` 仍为公开字段,但使用约定更严格。
- 性能影响:
- `WM_MOUSEMOVE` 和 overlay 补画路径增加了必要的状态清理与补画,但避免了整窗级重绘。
- `Table` 分页按钮视觉变化当前仍提升为整表重绘,颗粒度偏粗,但正确性优先。
- 风险点:
- `Dialog` 旧 synthetic move 机制仍与新清理模型并存。
- `Table` 内部局部重绘体系尚未建立,分页区仍偏重。
## 测试与验证
- 测试范围:
- 顶层 resize
- 三层 `Canvas` 嵌套
- `TabControl` 外层 resize 与页内稳定性
- overlay 补画
- `Table` 横向拉伸、分页按钮、页码重绘
- `Label` 文本 / 字体样式变化
- 验证步骤:
1. 编译 `Control.cpp / Label.cpp / Canvas.cpp / TabControl.cpp / Table.cpp / TextBox.cpp / Dialog.cpp`
2. 编译 `z-testDome.cpp /DKEY=5`
3. 手动回归 `KEY5` 的 hover、tooltip、overlay、分页与页码场景
- 验证结果:
- 编译级验证通过。
- 手动 GUI 回归依赖本机继续执行。
- 已知限制 / 遗留问题:[可选]
- `Dialog` 旧 synthetic move 机制暂未统一。
- `Table` 尚未引入内部局部重绘模型。
- 全项目所有控件的能力边界总审计未做。
## 落地信息
- 关联功能变更 ID[可选]
- `Feature-20260415-0008`
- 关联 BUG / Fix[可选]
- `BUG-20260415-0005`
- `Fix-BUG-20260415-0005`
- Commit: 未提交(当前工作区)
- PR[可选]
- 发布版本:[可选]
- 相关文档:[可选]
- [Feature-20260415-0008-KEY5-第二阶段专项回归场景增强.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/功能变更/Feature-20260415-0008-KEY5-第二阶段专项回归场景增强.md)
- [BUG-20260415-0005-局部重绘未补画上层兄弟导致遮挡错误.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/BUG/BUG-20260415-0005-局部重绘未补画上层兄弟导致遮挡错误.md)
- [Fix-BUG-20260415-0005-局部重绘补画上层兄弟修复.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/Fix/Fix-BUG-20260415-0005-局部重绘补画上层兄弟修复.md)