Commit Graph
4 Commits
Author SHA1 Message Date
DeepSeek V4.1 Flash 8f735d51be 修复拆分网格误继承实验性功能 / 阶跃线宽 / 面板拖拽残影 / 自由标记卡顿与交互
- 拆分网格:实验性功能只由原网格的首个信号继承(LaneCarry::owner);
  SplitLane 只让第一份继承;新增 PruneLaneSignalItems 按 lane.signals 过滤四类
  逐信号条目(修复"新网格出现别人的固定点、面板里却查不到")
- 阶跃信号:包络带横向膨胀半径 ceil -> floor(1px 线宽不再把竖直沿撑成 3px)
- 浮动面板:面板位置移出 PanelGlobalKey(拖动单个面板不再重画全部面板),
  新增 vacatedRects 让"上一帧被移动/缩小/关闭的面板腾出的区域"也强制重画
- 自由标记:新增 FreeMarkerContents 内容缓存(键不含视界),大量固定点时拖光标/平移不再逐帧采样;
  透明度滑块与光标模式解耦(始终显示);悬停胶囊恢复不透明(瞄着被遮住的数据点时除外);
  胶囊与面板五列按实测文本撑开,不再省略
- 面板交互:折起指示器与信号列表组名同款三角;GX 徽标/标题栏悬停不改光标、移除徽标气泡;
  标题栏双击滚动到该网格(单击不触发,双击不再折起)
- 验证:新增离屏 .preflight/fixcheck 37/37(三处 A/B 均能如实失败);
  回归 round3check 31/31、round4check 34/34、round5check 5/5、editcheck 20/20、convcheck 18/18;
  make release/debug 零警告
2026-10-21 17:21:09 +08:00
DeepSeek-V4.1-Flash 3400ac7c29 自由标记体验重做 + 全部实验性面板可折起
- 网格内固定点:取值胶囊按已放置矩形做纵向避让(不再互相遮挡);行尾 ✕ 改为与
  胶囊同高的正方形;移除固定点的纵向半透明竖线
- 新增「标记透明度」(0–100%),作用于本网格全部固定点的圆点/胶囊/描边/文字/✕;
  半透明时文字改走 GDI+(GDI DrawTextW 忽略 alpha),100% 时像素零变化;
  ≤2% 时不绘制且不登记 ✕ 命中矩形(看不见的按钮不可点)
- 面板按信号分组:信号色托底分组栏(展开三角 + 信号名 + N 标记点 + ✕,文字/三角/✕
  一律用自适应对比色),点击分组栏收起/展开;条目五列(值/枚举/增量/时刻/间隔),
  首项增列与 Δt 显示 N/A,整个面板没有枚举文本时枚举列整列缺省;行尾仍有 ✕
- 面板内容超高时右侧出现滚动条(分组栏与条目一起滚动),滚轮在内容区翻页;
  底部按钮与「标记透明度」滑块固定在底部、不参与滚动
- 底部按钮改为「光标选取模式」切换类按钮(外观与工具栏切换按钮一致,激活高亮),
  激活时其上方出现「标记透明度」滑动条(与信号样式区的透明度滑块同款)
- 所有实验性功能浮动面板支持展开/折起:标题栏 GX 徽标左侧新增「三角 + 横线」指示器,
  单击切换、双击标题栏切换;折起的面板只有标题栏
- 数据层:LanePanelState.collapsed、Lane.freeMarkerOpacity/freeMarkerScroll/
  freeMarkerCollapsedGroups,LaneCarry 与 SplitLane 一并继承
- 验证:新增离屏 .preflight/perf/mark2check 69/69(含两组 A/B);回归 datacheck 69/69、
  verify 49/49、panelanim 158/158、errcheck 19/19;make release/debug 零警告
2026-10-21 02:59:05 +08:00
DeepSeek V4.1 Flash d2e6fdd085 收尾: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:聚合化、解耦、探针、验证结果、变更清单)。
2026-10-16 04:38:12 +08:00
DeepSeek V4.1 Flash e6b7bf66ec 按组件目录结构把四个巨型实现文件拆分为多个协作文件(PlotView / SignalPanel / Application / DataModel)
承接上一条提交(0871eb0)—— 该提交只完成了 Components/Shared 与注释/命名清理,并**主动未做**
大文件拆分;本提交把大文件拆分补齐,至此“按功能拆分逻辑块到各组件自己的 Inc/Src”已落地。

## 一、拆分结果

| 原文件 | 拆分后 |
| --- | --- |
| Components/PlotView/Src/PlotView.cpp(13 695 行 / 544 KB) | PlotView.cpp(787) + PlotViewPaint.cpp(6 367) + PlotViewInteraction.cpp(2 715) + PlotViewFeatures.cpp(3 005) + PlotViewInternal.hpp(936) |
| Components/SignalPanel/Src/SignalPanel.cpp(4 184 行) | SignalPanel.cpp(1 141) + SignalPanelPaint.cpp(697) + SignalPanelInteraction.cpp(2 095) + SignalPanelInternal.hpp |
| Components/Application/Src/Application.cpp(3 135 行) | Application.cpp(1 427) + ApplicationCommands.cpp(1 184) + ApplicationLoading.cpp(270) + ApplicationInternal.hpp |
| Utilities/Src/DataModel.cpp(2 615 行) | DataModel.cpp(1 583,含自由函数区) + DataModelTab.cpp(732) + DataModelInternal.hpp |

分片职责(以 PlotView 为例):
  core        视图核心:构造/析构、上下文、布局、坐标映射、视界与平移、网格结构与归属
  paint       渲染与像素缓存:全部绘制、场景/装饰缓存、每网格图层、宽基底与滚动补条
  interaction 交互与编辑:命中测试、鼠标/键盘、光标形状、内联输入框、浮动面板层序
  features    视图特性与派生数据:光标读数/提示/缩放、自适应、吸附、单点、派生曲线线程池、
              边沿统计、实验性功能参数
(SignalPanel 为 core/paint/interaction;Application 为 core/commands/loading;
  DataModel 为 core/tab。)

## 二、关键手法(这是能安全拆开的前提)

原文件的辅助区都是**匿名命名空间**(PlotView 约 870 行常量与工具函数),被所有成员函数广泛引用。
直接拆文件会让各 .cpp 拿不到这些工具,因此:

1. 把该块整块搬进 `<组件>Internal.hpp`,从 `namespace { }` 改为**具名**命名空间
   (pvdetail / spdetail / appdetail / dmdetail);
2. 块内**每个函数与常量都标 inline** ⇒ 多个翻译单元共用同一个定义:既不重复符号,
   也不产生 N 份函数定义;
3. 头部末尾 `using namespace <ns>;` ⇒ 各 .cpp 函数体里原有的非限定调用(IntersectRect /
   NiceStep / ClampDouble …)**一行都不用改**;
4. 成员定义按「方法名 → 分片」归类后**整块搬移** —— 全程**纯代码搬移**,没有改动任何一行函数体。

## 三、拆分过程中踩到并修正的四个坑(已固化到 .preflight/perf/split_component.ps1)

1. `[[maybe_unused]]` 等属性**必须排在 inline 之前**(`inline [[x]] T` 非法);
   单独的 `{`/`}` 行、注释行、`struct`/`enum`/`using`/`template` 行不能加 inline。
2. 匿名命名空间的**结束行可能带注释**(`} // namespace`),只认 `^\t}$` 会一路匹配到后面
   某个成员函数的结束括号,把大段成员定义误当成“辅助区”搬走。
3. **首个成员定义之前的所有行**必须跟着进核心文件:DataModel.cpp 在匿名命名空间之后、
   首个成员定义之前还有约 390 行命名空间外的自由函数(SignalStats / ComputeStats /
   CacheSparseSamples / ApplySinglePointDefaultStyle …),漏掉会被静默丢弃。
4. 内部头必须带上原文件真正用到的全部头:DataModel 需要 Theme.hpp / <cstring> / <cstdio> /
   <deque> / <atomic> / <cwctype> / <new>(原文件靠这些头才编译得过)。

## 四、附带完成的命名审计

PlotView 中残留的 File 语义命名一并修正:LaneSpansMultipleFiles → LaneSpansMultipleGroups、
firstFile → firstGroup、multiFile → multiGroup、SceneCacheKey::haloFile → haloGroup。

## 五、验证(全部离屏:SW_HIDE + 不注入真实输入 + 进程/线程 BELOW_NORMAL)

- .preflight/perf/verify.exe(PlotView 渲染/交互,含逐像素断言)49/49
- .preflight/perf/panelanim.exe(信号面板:卷尺式折起/展开、筛选态、悬浮组名、目标行)156/156
- .preflight/perf/datacheck.exe(数据层:单轴/多时间轴 CSV、MF4、重命名语义)69/69
- .preflight/perf/edgecheck.exe(边沿统计与面板排版)46/46
- make release / make debug 零警告。
即:拆分后**行为与拆分前完全一致**(纯代码搬移,四套探针全绿)。

## 六、体积(诚实记录)

  Target.exe: 754 176 → 764 416 B(+10 240 B,+1.4%)
因为 inline 工具函数会在每个引用它的翻译单元里各生成一份(PE/COFF 链接器没有 ICF 合并)。
这再次印证:拆分解决的是**可维护性**,不是体积(本轮的 −24.6% 全部来自 ICO 256×256 条目改 PNG)。

## 七、文档

Documents/agent_mem.md:§9.37 新增“七、多文件拆分(已完成)”与“八、仍未完成”(只剩
Lane → LanePanelState、模态提示解耦、MF4 压缩块三项);§11.2 新增第 91、92 条(多文件化的
唯一安全手法 + 体积代价)。Documents/refactor_report_2026-10-16.md 同步更新 §五/§七/§八。
2026-10-16 04:02:36 +08:00