收尾:LanePanelState 抽取 + 错误提示非模态化(清空上一轮的“未完成”)
一、Lane 的内聚性(上一轮建议 5,本轮完成)
- 新增 struct LanePanelState { bool open = true; double x = -1.0; double y = -1.0; };
- Lane 的 12 个平铺面板字段(edgePanelOpen/X/Y 等 × 4 类实验性功能)
→ 4 个聚合成员 edgePanel / edgeCenterPanel / meanFilterPanel / weakPeakPanel;
- 访问点全部改为 lane.edgePanel.open 形式(DataModelTab.cpp 快照拷贝、
PlotViewInteraction.cpp 面板拖拽、PlotViewPaint.cpp 面板层序绘制);
- RebuildLanes 内部的 LaneCarry 同步收敛为 4 个 LanePanelState,
12 行逐字段赋值简化为 4 行整体赋值。
- 教训:批量改名不能对“声明”和“使用”跑同一组替换对,
否则声明行会变成 `bool edgePanel.open = true;` 这类非法代码。
二、错误提示与模态阻塞解耦(上一轮建议 1,本轮完成)
- Application 新增 SetModalErrorsEnabled(bool) / ModalErrorsEnabled(),
成员 m_modalErrorsEnabled 默认 true(交互场景行为不变);
- Initialize 最先执行 SetModalErrorsEnabled(showCommand != SW_HIDE):
隐藏窗口(自动化/离屏)下没人能点掉模态框,等于把进程钉死;
- SetStatusMessage(text, isError=true):允许模态时原样 MessageBoxW,
否则改走非模态通道 m_plot.ShowPersistentHint(text)(绘图区底部浮层);
普通提示与空文本依旧被忽略;
- PlotView 新增公开接口 ShowPersistentHint(text)(内部转 SetHintSticky),
不向宿主暴露粘滞/淡出等内部细节。
三、顺带修掉一个真实缺陷
- PlotView::Paint 在 m_lanes.empty() 时提前 return,而提示浮层在其后的
叠加层绘制 ⇒ 一个信号都没勾选时任何错误都显示不出来,恰恰是
“文件加载失败”最需要提示的场景;该分支补一次 PaintHint(g)。
四、验证(全部离屏:SW_HIDE + 不注入输入 + BELOW_NORMAL)
- make release / make debug:通过,零警告;Build/Release/Target.exe = 764416 B;
- verify 49/49、datacheck 69/69、edgecheck 46/46、panelanim 156/156;
- 新增探针 .preflight/perf/errcheck 19/19:默认值 / 隐藏窗口自动降级 / 宿主显式开关;
工作线程 + 5s 超时判定“不阻塞”(旧行为会永久阻塞,判失败并 ExitProcess,
探针不会挂住);EnumWindows 统计本进程 #32770 顶层窗口数量前后不变;
错误文本进入 m_hintText / m_hintSticky / HintNeedsAnimation / m_hintShownAt;
像素级:有提示帧与无提示帧在绘图区内的差异像素 3781,且全帧差异同为 3781
(证明差异只来自提示)。
五、文档
- Documents/agent_mem.md:§9.37 新增第八节(本轮补齐)、第九节(仅剩 MF4 项)、
§11.2 新增第 93–95 条硬约束、变更日志新增一行;
- Documents/refactor_report_2026-10-16.md:§7.3 / §7.4 标记完成,新增 §九 收尾补记
(含 9.1–9.5:聚合化、解耦、探针、验证结果、变更清单)。
This commit is contained in:
1 parent
e6b7bf66ec
commit
d2e6fdd085
11 files changed
+296
-132
No files matched your search
@@ -68,7 +68,7 @@
|
||||
|
||||
> 其余结构体(`SignalStyle` / `TabConfig` / `Lane` / `TimeAxis` / `SignalRef` / `EdgeScanState` 等)
|
||||
> 逐字段核对后未发现同类“同义多字段”现象;`Lane` 的“体量过大”属**内聚性**问题而非冗余,
|
||||
> 见 §五 的 `LanePanelState` 建议。
|
||||
> 已按 §7.3 / §9.1 抽出 `LanePanelState`(本轮完成)。
|
||||
|
||||
---
|
||||
|
||||
@@ -263,16 +263,16 @@ Components/*(功能组件) ──▶ Components/Shared(UI 控件) ─
|
||||
|
||||
组件文件数(拆分后):`PlotView` 6、`Application` 5、`SignalPanel` 5、`Shared` 2、`TabBar` 2、`Toolbar` 2、`Main` 2。
|
||||
|
||||
### 7.3 `Lane` 的内聚性(上一轮建议 5)
|
||||
### 7.3 `Lane` 的内聚性 —— **已完成(本轮补齐,见 §九)**
|
||||
|
||||
`Lane` 内含 4 类实验性功能的状态 + 各自的面板坐标,已超 200 行;建议抽出
|
||||
`LanePanelState`(开关 + 每信号参数 + 面板位置),`Lane` 只保留结构与归属。
|
||||
属**结构内聚**重构而非去冗余,需同步改 `DataModel` 与 `PlotView` 的多处访问点,本轮未做。
|
||||
`Lane` 内含 4 类实验性功能的状态 + 各自的面板坐标(12 个平铺字段);已抽出
|
||||
`LanePanelState { bool open; double x; double y; }`,`Lane` 只保留「开关 + 每信号参数 + 面板状态」
|
||||
四项成员(`edgePanel` / `edgeCenterPanel` / `meanFilterPanel` / `weakPeakPanel`)。
|
||||
|
||||
### 7.4 错误提示与模态阻塞解耦(上一轮建议 1)
|
||||
### 7.4 错误提示与模态阻塞解耦 —— **已完成(本轮补齐,见 §九)**
|
||||
|
||||
`SetStatusMessage(..., isError=true)` 仍直接 `MessageBoxW`;自动化 / 离屏场景与其耦合,
|
||||
建议改为宿主级非模态提示。本轮未做(与“不影响功能”的约束存在交互设计决策,需用户拍板样式)。
|
||||
`SetStatusMessage(..., isError=true)` 不再是「无条件 `MessageBoxW`」:模态与否由宿主决定
|
||||
(`Application::SetModalErrorsEnabled`),隐藏窗口启动时**自动**降级为绘图区非模态提示。
|
||||
|
||||
### 7.5 MF4 压缩块 / 数据列表(上一轮建议 2–3)
|
||||
|
||||
@@ -318,3 +318,92 @@ Components/*(功能组件) ──▶ Components/Shared(UI 控件) ─
|
||||
* `Documents/agent_mem.md` 同步更新(§9.37 + §11.2 约束 + 变更日志)。
|
||||
* 上一轮报告 `Documents/refactor_report_2026-10-15.md` **已删除**(其有效内容已并入
|
||||
`agent_mem.md` 与本文)。
|
||||
|
||||
---
|
||||
|
||||
## 九、收尾补记(同一轮次的第二遍:把「仍未完成」清空)
|
||||
|
||||
上一版报告在 §7.3 / §7.4 留下两项「本轮未做」。这一遍把它们做完,并在过程中又发现并修掉
|
||||
一个**真实缺陷**。所有改动都是「结构内聚 + 反馈通道」类,**不改任何功能性行为**。
|
||||
|
||||
### 9.1 `LanePanelState`:`Lane` 的 12 个平铺面板字段 → 4 个聚合成员
|
||||
|
||||
```cpp
|
||||
// Utilities/Inc/DataModel.hpp
|
||||
struct LanePanelState
|
||||
{
|
||||
bool open = true; /**< 浮动面板是否展开。 */
|
||||
double x = -1.0; /**< 面板左上角 X(-1 表示尚未定位,首次绘制时自动摆放)。 */
|
||||
double y = -1.0; /**< 面板左上角 Y。 */
|
||||
};
|
||||
```
|
||||
|
||||
* `Lane` 的 `edgePanelOpen/edgePanelX/edgePanelY` 等 **12 个字段**被
|
||||
`LanePanelState edgePanel / edgeCenterPanel / meanFilterPanel / weakPeakPanel` 取代;
|
||||
访问点全部改为 `lane.edgePanel.open` 这样的**结构内聚**形式(`DataModelTab.cpp` 的快照拷贝、
|
||||
`PlotViewInteraction.cpp` 的浮动面板拖拽、`PlotViewPaint.cpp` 的面板层序绘制)。
|
||||
* `RebuildLanes` 内部的「网格自身状态携带」结构 `LaneCarry` 同步收敛:原来 12 个平铺字段
|
||||
改为 4 个 `LanePanelState`,逐字段赋值也简化为整体赋值(少 8 行、少 8 个易漏字段)。
|
||||
* **收益**:参数的归属一眼可辨(哪个坐标属于哪个功能)、新增一类实验性功能时只需加 1 个成员;
|
||||
同时把「3 个字段必须一起改」的隐式约束变成类型约束。
|
||||
* ⚠️ 教训(已写进 `agent_mem.md`):批量改名脚本**不能**在「声明」与「使用」上跑同一组替换对 ——
|
||||
对 `Lane` 使用的 `edgePanelOpen → edgePanel.open` 用在 `LaneCarry` 的**声明行**上会得到
|
||||
`bool edgePanel.open = true;` 这种非法声明。修正方式是**声明处单独重写**(4 个聚合成员),
|
||||
只让「使用处」走替换对。
|
||||
|
||||
### 9.2 错误反馈:模态对话框 → 可关闭(隐藏窗口自动降级为非模态提示)
|
||||
|
||||
* `Application` 新增 `SetModalErrorsEnabled(bool)` / `ModalErrorsEnabled()`,
|
||||
成员 `m_modalErrorsEnabled` **默认 `true`**(保持交互场景的既有行为);
|
||||
`Initialize(instance, showCommand)` 在**最先**执行 `SetModalErrorsEnabled(showCommand != SW_HIDE)`。
|
||||
理由:隐藏窗口(自动化/离屏)下弹模态框**没有人能点掉**,等于把进程钉死。
|
||||
* `SetStatusMessage(text, /*isError*/true)` 分支化:
|
||||
允许模态 → 原样 `MessageBoxW`;不允许 → `m_plot.ShowPersistentHint(text)`(绘图区底部浮层)。
|
||||
普通提示(`isError == false`)与空文本依旧被忽略 —— **交互体验与此前完全一致**。
|
||||
* `PlotView` 新增公开接口 `ShowPersistentHint(text)`(内部转 `SetHintSticky`),
|
||||
把「私有提示机制」变成「宿主可用的反馈通道」,且不暴露粘滞/淡出等内部细节。
|
||||
* **顺带修掉一个真实缺陷**:`PlotView::Paint` 在 `m_lanes.empty()` 时**提前 return**,
|
||||
而提示浮层在 return 之后的叠加层里绘制 ⇒ **「一个信号都没勾选」时任何错误都显示不出来**,
|
||||
恰恰是「文件加载失败」这一最需要提示的场景。修法是在该分支补一次 `PaintHint(g)`。
|
||||
这一条是**探针先失败、才回头发现的**(见 9.3),说明「非模态通道」本身也需要像素级验证。
|
||||
|
||||
### 9.3 新增离屏探针 `.preflight/perf/errcheck`(19/19)
|
||||
|
||||
模态/非模态无法用「截图看着对」来判断,因此写成可自动判定的断言:
|
||||
|
||||
| 断言组 | 内容 |
|
||||
| --- | --- |
|
||||
| 默认与降级 | 默认 `ModalErrorsEnabled() == true`;`Initialize(..., SW_HIDE)` 后为 `false`;宿主可显式开关 |
|
||||
| 不被打断 | 从**工作线程**调用 `SetStatusMessage(err,true)`,5 s 内必须返回(旧行为会永久阻塞 ⇒ 直接判失败并 `ExitProcess`,探针**不会挂住**) |
|
||||
| 不产生对话框 | 用 `EnumWindows` 统计**本进程**中类名 `#32770` 的顶层窗口,调用前后数量不变 |
|
||||
| 走到提示通道 | `m_hintText` 等于错误文本、`m_hintSticky == true`、`HintNeedsAnimation() == true`、`m_hintShownAt != 0` |
|
||||
| **真的画出来** | 「有提示」帧与「无提示」帧在绘图区矩形内的差异像素 **3781**,且全帧差异 3781(说明差异**只**来自提示) |
|
||||
| 提示不吞消息 | 成功提示 / 空文本错误不进入提示通道;第二条错误顶掉第一条 |
|
||||
|
||||
### 9.4 本轮验证(全部离屏,`SW_HIDE` + 无输入注入 + `BELOW_NORMAL`)
|
||||
|
||||
| 项目 | 结果 |
|
||||
| --- | --- |
|
||||
| `make release` / `make debug` | 通过,**零警告** |
|
||||
| 产物体积 | `Build/Release/Target.exe` **764 416 B**(与拆分后一致;本轮是纯结构改动,未引入新代码膨胀) |
|
||||
| `.preflight/perf/verify`(界面与像素) | **49/49** |
|
||||
| `.preflight/perf/datacheck`(数据层) | **69/69** |
|
||||
| `.preflight/perf/edgecheck`(边沿统计) | **46/46** |
|
||||
| `.preflight/perf/panelanim`(分组折起动画 + 两处 UI 修复) | **156/156** |
|
||||
| `.preflight/perf/errcheck`(本轮新增) | **19/19** |
|
||||
| 上一遍的 A/B(回退两处 UI 修复) | 如实失败 **9** 项(失败文案逐条点名「点组名不应折起」「改名框不应包住条目计数」),恢复后 156/156 |
|
||||
|
||||
### 9.5 本轮变更清单
|
||||
|
||||
```
|
||||
修改 Utilities/Inc/DataModel.hpp 新增 LanePanelState;Lane 的 12 个平铺面板字段 → 4 个聚合成员
|
||||
修改 Utilities/Src/DataModelInternal.hpp LaneCarry 同步收敛为 4 个 LanePanelState(含整体赋值简化)
|
||||
修改 Utilities/Src/DataModelTab.cpp 面板状态快照拷贝改用 .open/.x/.y
|
||||
修改 Components/PlotView/Src/PlotViewInteraction.cpp 浮动面板拖拽改用 .open/.x/.y
|
||||
修改 Components/PlotView/Src/PlotViewPaint.cpp 面板层序绘制同改;空状态分支补 PaintHint(缺陷修复)
|
||||
修改 Components/PlotView/Inc/PlotView.hpp 新增公开 ShowPersistentHint
|
||||
修改 Components/PlotView/Src/PlotViewFeatures.cpp 实现 ShowPersistentHint
|
||||
修改 Components/Application/Inc/Application.hpp SetModalErrorsEnabled / ModalErrorsEnabled / m_modalErrorsEnabled
|
||||
修改 Components/Application/Src/Application.cpp Initialize 按 showCommand 自动降级;SetStatusMessage 分支化
|
||||
新增 .preflight/perf/errcheck_main.cpp 模态/非模态解耦探针(gitignored,不随产物提交)
|
||||
```
|
||||
Reference in new issue
Block a user