# 新增功能模块 / 模块重构 > 适用场景:新增模块、重大模块重构、核心架构能力演进。 > 不适用场景:小接口或轻量功能变更,请使用“功能变更”模板。 ## 基本信息 - 模块 ID:Module-20260415-0004 - 模块名称: 布局系统第二阶段验收与封口 - 状态:已验证 - 类型:模块重构 - 所属系统 / 子系统: GUI 框架 / Layout - 版本 / 分支: 当前工作区 / 下一版本开发中 - 环境: Windows + EasyX - 负责人: Codex 协作修改 ## 背景与目标 - 背景: - 第一阶段已完成统一锚点模型和统一解算入口。 - 第二阶段继续围绕“几何所有权收口 + 内容驱动规则收口”推进,实现几何写入口分层、内容驱动控件规则收口、局部重绘与 overlay 补画链修复。 - 在 `KEY1 / KEY5` 回归过程中,又暴露出脏子树提交、coverage 低估、TabControl 层级顺序等一组重绘链问题,需要一并收口后才能视为阶段稳定。 - 当前痛点: - 缺少一份明确的阶段验收记录,难以区分“本阶段完成项”和“明确延期项”。 - 当前主线 bug 虽已基于测试用例修复,但如果不做封口记录,后续继续推进下一主题时容易重复回头整理。 - 目标: - 明确第二阶段已经完成的主线改造和已验证的 bug 修复。 - 明确当前接受的边界与明确延期的技术债。 - 为后续“公开布局 API + 旧 demo 迁移”提供稳定起点。 - 非目标:[可选] - 本记录不新增运行时代码逻辑。 - 本记录不覆盖未来的 Tooltip 智能选位、`Table` 纵向拉伸、`Dialog` synthetic move 统一改造。 ## 模块边界 - 职责: - 汇总布局系统第二阶段的最终语义收口结果。 - 记录本阶段已完成的运行态 / 设计态几何规则、局部重绘提交规则与 overlay 补画规则。 - 明确已知延期项与后续主题边界。 - 不负责什么: - 不扩展新的布局表达能力。 - 不重写 `Dialog` 旧 synthetic move 机制。 - 不实现 `Table` 内部局部重绘体系。 - 外部依赖: - `Control / Window / Canvas / TabControl / Table / Label / Button` - EasyX 绘制与消息循环环境 - 对外能力 / API: - 保持旧 API:`setLayoutMode(...)`、`setAnchor(...)` - 保持显式设计基线提交入口:`commitCurrentGeometryAsDesignRect()` - 保持 `Label::textStyle` 公开,但要求样式修改后手动 `setDirty(true)` - 关键数据 / 状态: - `localx / localy / localWidth / localHeight` - `x / y / width / height` - `LayoutSpec / LayoutCapability / ResolvedLayoutRect` - `eventVisualChanged / dirty / coverage / overlay` ## 设计说明 - 核心流程: - 几何变化先在父局部坐标系内统一解算,再通过内部受控路径应用到运行态矩形。 - 内容驱动控件在自身受控路径中刷新运行态尺寸;设计基线不得在普通布局过程中自动漂移。 - 托管局部重绘按“脏子树提交 -> 直接分支 coverage -> 传递式 overlay 补画”收口,确保嵌套容器、Tooltip、上层兄弟遮挡链闭合。 - 关键对象 / 类关系: - [`Control.h`](D:/programming/imGUI-easyX/imGui-easyX/Control.h):统一布局解算、设计基线提交、托管重绘底座 - [`Label.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Label.cpp):内容驱动尺寸刷新前移,`draw()` 只消费运行态矩形 - [`Canvas.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Canvas.cpp):直接子树映射、脏子树提交、局部 overlay 补画 - [`TabControl.cpp`](D:/programming/imGUI-easyX/imGui-easyX/TabControl.cpp):外层统一布局,内部页签栏/页面区自管,绘制顺序与局部提交顺序统一 - [`Table.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Table.cpp):当前版本 `X Stretch / Y Fixed`、分页按钮视觉与页码重绘修复 - [`Window.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Window.cpp):顶层托管重绘、传递式 overlay 补画、顶层 coverage 收口 - 生命周期: - 普通 resize / 重排不自动回写 `local*` - 公开 setter 只写运行态,不隐式提交设计基线 - 显式设计基线提交只通过 `commitCurrentGeometryAsDesignRect()` 或控件内部受控结构刷新触发 - 事件 / 渲染 / 数据流:[按模块类型填写] - `WM_MOUSEMOVE`:真实命中分支处理事件,后续兄弟仅清理鼠标瞬时状态 - 托管局部重绘:先提交 dirty root / dirty branch,再按 coverage 传递式补画 overlay - Tooltip / 扩展绘制 coverage:通过 `getManagedRepaintCoverageRect()` 纳入托管 coverage 计算 - 关键不变量: - `local*` 只表示设计态父局部矩形 - `x / y / width / height` 只表示运行态绘制矩形 - `draw()` 不再承担新的几何决策入口 - `Table` 当前版本 `Y Fixed` 是实现边界,不是永久产品结论 - 降级 / 回退策略:[可选] - Stretch 不满足条件时降级为固定尺寸位移策略,并输出最小必要日志 - 控件能力边界拦截 Stretch 请求时,通过日志说明被拦截的轴和原因 ## 实现与影响 - 关键实现点: - 收口公开 setter、统一布局应用路径、内容驱动路径、显式设计基线提交四类几何写入口 - 修复 `WM_MOUSEMOVE` 短路后 hover / tooltip 无法及时清理的问题 - 修复局部重绘只认直接 dirty child、不认 dirty descendant 的链路缺口 - 修复 coverage 低估导致 Tooltip / overlay 漏补画的问题 - 修复 Tab 页签按钮与页面绘制顺序不一致导致 Tooltip 被页面覆盖的问题 - 修复重复激活已激活页签时的残影 / 快照链扰动问题 - 涉及文件 / 类 / 函数: - [`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) - [`Button.h`](D:/programming/imGUI-easyX/imGui-easyX/Button.h) - [`Button.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Button.cpp) - [`Canvas.h`](D:/programming/imGUI-easyX/imGui-easyX/Canvas.h) - [`Canvas.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Canvas.cpp) - [`TabControl.h`](D:/programming/imGUI-easyX/imGui-easyX/TabControl.h) - [`TabControl.cpp`](D:/programming/imGUI-easyX/imGui-easyX/TabControl.cpp) - [`Table.h`](D:/programming/imGUI-easyX/imGui-easyX/Table.h) - [`Table.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Table.cpp) - [`TextBox.h`](D:/programming/imGUI-easyX/imGui-easyX/TextBox.h) - [`TextBox.cpp`](D:/programming/imGUI-easyX/imGui-easyX/TextBox.cpp) - [`Dialog.h`](D:/programming/imGUI-easyX/imGui-easyX/Dialog.h) - [`Dialog.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Dialog.cpp) - [`Window.h`](D:/programming/imGUI-easyX/imGui-easyX/Window.h) - [`Window.cpp`](D:/programming/imGUI-easyX/imGui-easyX/Window.cpp) - [`MessageBox.h`](D:/programming/imGUI-easyX/imGui-easyX/MessageBox.h) - [`z-testDome.cpp`](D:/programming/imGUI-easyX/imGui-easyX/z-testDome.cpp) - 兼容性影响: - 旧锚点 API 仍可用,内部实现已完全转到新布局模型 - `Label::textStyle` 仍为公开字段,但要求样式修改后显式 `setDirty(true)` - `TabControl::setActiveIndex()` 和 `Button::setButtonClick()` 对重复同状态调用新增短路,不再重复触发链路 - 性能影响: - 局部重绘 coverage 和 overlay 补画会更保守,补画次数可能略增 - 相比整窗 / 整容器强制重绘,这仍是更合理的正确性与性能折中 - `Table` 分页按钮视觉变化当前仍提升为整张 `Table` 重绘,颗粒度偏粗但正确性优先 - 风险点: - `Dialog` 旧 synthetic move 机制仍与新清理模型并存 - `Table` 尚未拥有自己的内部局部重绘体系 - 公开 `AxisSizePolicy / AxisAlignPolicy` API 仍未开放,旧 demo 仍受旧入口表达能力限制 ## 测试与验证 - 测试范围: - `KEY1`:页签重复激活、表格超出页范围残影回归 - `KEY5`:三层 `Canvas` 嵌套、跨容器 hover / tooltip、overlay 补画、`TabControl`、`Table`、页码与分页按钮 - 核心源码编译级验证:布局主线、重绘主线、Tab / Table / Label / TextBox / Dialog 主线 - 验证步骤: 1. 编译 `Control.cpp / Button.cpp / Label.cpp / Canvas.cpp / TabControl.cpp / Table.cpp / TextBox.cpp / Dialog.cpp / Window.cpp` 2. 编译 `z-testDome.cpp /DKEY=1` 3. 编译 `z-testDome.cpp /DKEY=5` 4. 手动回归 `KEY1 / KEY5` 中的 tooltip、overlay、页签、分页、三层嵌套和跨容器按钮场景 - 验证结果: - 编译级验证通过 - 基于当前 `KEY1 / KEY5` 用例回归,已知 bug 已修复 - GUI 手动回归依赖本机继续确认,当前结论基于现有测试反馈成立 - 已知限制 / 遗留问题:[可选] - `Dialog` 旧 synthetic `WM_MOUSEMOVE` 机制尚未统一到新模型 - `Table` 内部局部重绘体系尚未实现 - Tooltip 智能选位明确后置 - 公开 `AxisSizePolicy / AxisAlignPolicy` API 尚未开放,`KEY2` 等旧场景仍受旧 anchor 语义限制 ## 落地信息 - 关联功能变更 ID:[可选] - `Feature-20260415-0008` - 关联 BUG / Fix:[可选] - `BUG-20260415-0005` - `Fix-BUG-20260415-0005` - `BUG-20260415-0006` - `Fix-BUG-20260415-0006` - `BUG-20260415-0007` - `Fix-BUG-20260415-0007` - `BUG-20260415-0008` - `Fix-BUG-20260415-0008` - Commit: 未提交(当前工作区) - PR:[可选] - 发布版本:[可选] - 相关文档:[可选] - [Module-20260415-0003-布局系统第二阶段收口.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/模块/Module-20260415-0003-布局系统第二阶段收口.md) - [Feature-20260415-0008-KEY5-第二阶段专项回归场景增强.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/功能变更/Feature-20260415-0008-KEY5-第二阶段专项回归场景增强.md) - [BUG-20260415-0006-托管局部重绘未正确提交脏子树导致嵌套Canvas按钮状态不刷新.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/BUG/BUG-20260415-0006-托管局部重绘未正确提交脏子树导致嵌套Canvas按钮状态不刷新.md) - [Fix-BUG-20260415-0006-托管局部重绘脏子树提交链修复.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/Fix/Fix-BUG-20260415-0006-托管局部重绘脏子树提交链修复.md) - [BUG-20260415-0007-实际绘制coverage低估导致Tooltip与overlay补画漏算.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/BUG/BUG-20260415-0007-实际绘制coverage低估导致Tooltip与overlay补画漏算.md) - [Fix-BUG-20260415-0007-实际绘制coverage与overlay补画链修复.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/Fix/Fix-BUG-20260415-0007-实际绘制coverage与overlay补画链修复.md) - [BUG-20260415-0008-TabControl页签层级与重复激活链路导致Tooltip和残影异常.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/BUG/BUG-20260415-0008-TabControl页签层级与重复激活链路导致Tooltip和残影异常.md) - [Fix-BUG-20260415-0008-TabControl页签层级与重复激活链路修复.md](D:/programming/imGUI-easyX/imGui-easyX/开发记录/Fix/Fix-BUG-20260415-0008-TabControl页签层级与重复激活链路修复.md)