目录规范化(Inc/Src)+「自由标记」第六轮交互调整

1) 目录规范化:所有 .hpp 只放 Inc,Src 只放 .cpp
   - 4 个 *Internal.hpp 从 Src 迁到 Inc(DataModel/Application/PlotView/SignalPanel)
   - Makefile 固化该约定(注释必须单独成行:写在同一行会把 CXX_INCLUDES_PATHS 整条注释掉)
   - include 全是扁平形式,搬家无需改任何 include

2) 常规模式 = 普通鼠标(未开启「自由标记点选取」)
   - ProbeFreeMarker 早退:不预览、不画纵向光标、单击不固定
   - 补 if (!hitCurve) continue:否则整列光标下 probe.ref 恒有效,任意位置都能固定
   - 固定点仍恒吸附到真实采样时刻;「已吸附」圆环只在稀疏判据成立时画

3) 两个显示开关:按钮改名「自由标记点选取」,其下新增「显示增量 | 显示枚举文本」
   - 默认关闭,只影响已固定点的胶囊文本;预览胶囊恒为「值 = 枚举」
   - 开关行计入面板高度与内容区高度

4) 面板六列:新增恒存在的「序号」列(组内 1 起)
   - 枚举列存在时,无枚举/对不上任何枚举项显示 N/A
   - 列与列之间画竖线;悬停某行时其它固定点封顶 50% 不透明度,移出恢复
   - 删除固定点 ✕ 的悬停浮动提示(PaintFreeMarkerTooltip 实现与声明全部移除)
   - 开启选取模式的网格上,信号悬停提示只显示信号名

5) 缓存键补齐
   - FreeMarkerContents 混入枚举表指纹(旧键会让加上枚举表后仍显示 N/A)
   - PanelSlotKey 混入两个新按钮矩形与开关状态

6) 注释/文档
   - 修正 FreeMarkerProbe、SetLaneFreeMarkerCursor、标记透明度等处的过期说明
   - 空态提示按是否开启选取模式区分文案

验证(全离屏,未占用鼠标/键盘/屏幕)
   - 新增 .preflight/mark5check 52/52
   - 回归:markcheck 67/67、mark4check 40/40、fixcheck 37/37、round3check 31/31、
     round4check 34/34、round5check 5/5、editcheck 20/20、convcheck 18/18、diag 19/19
   - check 136/137(唯一失败项为既有不稳定项,drift=15818 与改动前逐位相同)
   - make release / make debug 零警告;Release 产物 TargetCheck.exe 857,600 字节
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-23 15:50:55 +08:00
1 parent 79eebc281e
commit affb9cc340
12 files changed
+561 -187

No files matched your search

+112
View File
@@ -3019,6 +3019,8 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
| 2026-10-22 | DeepSeek-V4.1-Flash(**本机**) | **「自由标记」面板表头 / 吸顶 / 行选中与悬停联动 + 固定点原位显示 + 探测容差与阶跃吸附(详见 §12 末尾「2026-10-22 第四轮」与 §11.2 第 213–220 条)**。① **列表头**:每个展开分组下方新增一行列标题(标记值 / 枚举文本 / 增量 / 时间点 / 时间间隔),与数据行共用列边界;列宽还需容纳列标题;内容总高与面板高度计入表头行;全部无枚举文本时整列缺省。② **吸顶**:分组栏与表头**各自**按 `y = max(自然, min(吸顶, 本组下边界 − 自身高度))` 钉住 ⇒ 组末尾按「表头先走 → 条目 → 分组栏最后离场」;绘制顺序改为「条目 → 表头 → 吸顶分组栏」,被盖住的条目不绘制也不可命中。③ **行交互**:`Lane::freeMarkerSelected`(单击选中/再点取消,`PanelSlotKey` 混入)+ 独立的整行悬停状态(整行悬停不会把 ✕ 变成 danger 色),悬停时网格内对应固定点整体高亮(数据点圆环 + 胶囊强制不透明 + accent 描边)。④ **固定点恢复原位显示**:删除 2026-10-21 的纵向避让,允许互相遮挡。⑤ **探测判据重写**:改为“鼠标到画出来的折线的垂直距离 ≤ `kSignalHitTolerance`”(与曲线高亮同源,复用 `AcquirePolyline` 顶点 + 点到线段距离),命中后吸附到最近采样时刻 ⇒ 修复 `SCATTER_TEST.csv` 阶跃竖直跳变线无法探测/固定的问题;删除 `kFreeMarkerHoverTolerance`。⑥ **滚动文字串到标题栏**:MARK 面板内全部文字改走 `UiTextClipped(..., content)`(GDI 文本不认 GDI+ 裁剪)。验证:新增离屏 `.preflight/mark4check` **38/38**(三组 A/B 均如实失败);回归 `markcheck` 61/61、`fixcheck` 37/37、`round3check` 31/31、`round4check` 34/34、`round5check` 5/5、`editcheck` 20/20、`convcheck` 18/18;`make release`/`make debug` 零警告;`TargetCheck.exe` **855,552 字节**。 |
| 2026-10-23 | DeepSeek-V4.1-Flash(**本机**) | **目录规范化(Inc/Src)+「自由标记」常规模式回归普通鼠标 + 两个显示开关 + 序号列/列分隔线 + 行悬停压暗(详见 §12 末尾「2026-10-23 第五轮」与 §11.2 第 221–229 条)**。① **目录规范化**:四个 `*Internal.hpp` 从 `Src` 迁到 `Inc`(`DataModelInternal` / `ApplicationInternal` / `PlotViewInternal` / `SignalPanelInternal`),并在 `Makefile` 固化「`Inc` 只放头文件、`Src` 只放 `.cpp`」;因 include 全是扁平形式,无需改任何 include。② **常规模式 = 普通鼠标**:`ProbeFreeMarker` 在未开启「自由标记点选取」时直接早退(不预览/不画纵向光标/单击不固定),并补上 `if (!hitCurve) continue;`(否则纵向光标整列都在时 `probe.ref` 恒有效 ⇒ 任意位置都能固定);固定点仍恒吸附到真实采样时刻,但“已吸附”圆环只在稀疏判据成立时画。③ **两个显示开关**:「自由标记点选取」下方新增「显示增量 | 显示枚举文本」(默认关闭,半宽同行),只影响已固定点胶囊,预览胶囊恒为“值 = 枚举”。④ **面板六列**:新增恒存在的「序号」列(组内 1 起),枚举列存在时无枚举/对不上的点显示 `N/A`,列间画竖线;悬停某行时其它固定点(数据点 + 胶囊)封顶 50% 不透明度、移出恢复。⑤ **移除固定点 ✕ 的悬停浮动提示**(`PaintFreeMarkerTooltip` 实现与声明全部删除);开启选取模式的网格上信号悬停提示只显示信号名。⑥ **两处缓存键补齐**:`FreeMarkerContents` 混入枚举表指纹(旧键会让加上枚举表后仍显示 `N/A`)、`PanelSlotKey` 混入两个新按钮矩形与开关状态。验证:新增离屏 `.preflight/mark5check` **52/52**(含“预览胶囊像素差 = 0”“行悬停压暗 848px → 移出恢复 0”“选取模式气泡变窄 1023→830”);回归 `markcheck` 67/67、`mark4check` 40/40、`fixcheck` 37/37、`round3check` 31/31、`round4check` 34/34、`round5check` 5/5、`editcheck` 20/20、`convcheck` 18/18、`diag` 19/19,`check` 136/137(唯一失败项为该探针既有的不稳定项,`drift=15818` 与改动前逐位相同);`make release`/`make debug` 零警告;`TargetCheck.exe` **857,600 字节(837.5 KiB)**。 |
## 11. 跨设备协作须知(起源设备视角)
> **本文件是唯一权威记忆**。所有设备 / Agent 共用它,**不要再新建 `agent_mem_origin.md` 等旁支记忆文件**。
@@ -4022,6 +4024,39 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
220. ⚠️⚠️ **面板内的文字一律用 `UiTextClipped(..., layout.content)`**:GDI `DrawTextW`
**不认 GDI+ 裁剪**,滚动时“部分可见”的条目会把文字画到标题栏上(用户 2026-10-22 报告)。
这条同时适用于分组栏名称/计数、表头列标题与空内容提示。
221. ⚠️⚠️ **目录约定:`Inc` 只放头文件、`Src` 只放 `.cpp`**(含 `*Internal.hpp` —— 它也是头文件)。
历史上 `*Internal.hpp` 放在 `Src` 也能编译,只是因为 `#include "..."` 会先找源文件所在目录;
一旦文件被搬走就无声失效。所有 include 都是扁平形式,靠 `-I.../Inc` 解析 ⇒ **搬家不要改 include**。
⚠️ `Makefile` 里 `CXX_INCLUDES_PATHS` 前的注释块必须单独成行(写成同一行会把整个变量注释掉,
症状是 `fatal error: CsvLoader.hpp: No such file or directory`)。
222. ⚠️⚠️ **未开启「自由标记点选取」时鼠标就是普通鼠标**(用户 2026-10-23 要求):
`ProbeFreeMarker` 必须 `if (!lane.freeMarkerCursor) return probe;` 早退 ⇒ 不预览数据点、
不画网格私有纵向光标、`OnLButtonDown` 不登记固定意图、单击也不固定。
⚠️ 开启后纵向光标**整列都在**(`probe.valid` 恒为真),因此“能否固定”只看 `probe.ref.IsValid()`:
`ProbeFreeMarker` 里必须有 `if (!hitCurve) continue;`(否则 `ref` 一直有效,
鼠标在全网格任意位置单击都能固定出一个离曲线很远的点)。
223. ⚠️ **「显示增量」「显示枚举文本」两个开关只影响已固定点的胶囊文本**
(`Lane::freeMarkerShowDelta/freeMarkerShowEnum`,默认 `false`,`LaneCarry` 双向携带):
跟随鼠标的预览胶囊恒为 `FreeMarkerValueText(value,false,false,0,true,enumText)`(值 = 枚举);
面板统计列也不看这两个开关。开关行独占底部最后一行、左右各半宽,与主按钮间距 `kFreeMarkerButtonGap`,
`switchRow` 必须计入面板高度**和**内容区高度。
224. ⚠️ **面板列序固定为 `序号 / 标记值 / 枚举文本 / 增量 / 时间点 / 时间间隔`**(六列):
序号列**恒存在**(`MarkerRow::serial` 组内 1 起);枚举列只在存在枚举表时出现,出现后
**无枚举/对不上任何枚举项一律显示 `N/A`**;列与列之间必须画竖线分隔。
任何“列数”都散落在 `markerColumns`、`kFreeMarkerColumnLabels/Widths`、`Lane::freeMarkerColumnWidths`
与各处 `column < N` 循环里 —— **改列数必须一次性全改**。
225. ⚠️ **悬停面板某行时,网格内其它固定点的不透明度封顶 50%**(原本 ≤ 50% 的不变;目标行强制 100%),
移出立即恢复;命中也必须按压暗后的 alpha 判定(否则“看不见还能点”)。
226. ⚠️ **固定点 ✕ 的悬停浮动提示已删除**(`PaintFreeMarkerTooltip` 实现与声明均已移除,不要加回来);
该网格开启「自由标记点选取」时,信号悬停提示只显示信号名(不再提示“可按住拖拽”)。
227. ⚠️⚠️ **`FreeMarkerContents` 的内容缓存键必须混入枚举表指纹**
(`values/texts/rangeMin` 规模 + `texts.data()` 地址):只混信号指针与采样数量时,
给信号加上枚举表后条目里仍然是 `N/A`(离屏探针实测复现)。
228. ⚠️ **`PanelSlotKey` 必须混入 `layout.showDelta/showEnum` 与两个开关布尔值**:
否则点击开关 / 布局变化后会把旧像素贴回来。
229. ⚠️ **固定点必须落在真实采样时刻上**:`ProbeFreeMarker` 命中曲线时**始终**吸附到最近采样点
(`snapToNearestSample`);只有“已吸附”圆环(`probe.snapped`)仍只在稀疏判据 `sparse` 成立时才显示
(密采样时吸附量 < 1 像素,圆环常驻会像是画错了)。
### 11.3 离屏验证方法学(本机偏好,强烈建议沿用)
@@ -7682,3 +7717,80 @@ DG3 data=0 cycle=0 (空组,一个字符串通道)
- ⚠️ 探针坑:两条信号同网格时阶跃幅度更小(阈值取 40 逻辑像素);
吸顶“离场”必须在**两组**内容上验证(单组且内容超高时分组栏数学上会一直钉住);
滚动扫描步长按设备像素(`step*2`),再乘 `m_scale` 会扫不到组末尾。
## 本轮(2026-10-23 第五轮,本机):「自由标记」常规模式回归普通鼠标 + 两个显示开关 + 序号列/列分隔线 + 行悬停压暗 + 目录规范化
### A. 目录规范化(§11.2 第 221 条)
- `Inc` 只放**头文件**(含 `*Internal.hpp`),`Src` 只放 `.cpp`。四个 `*Internal.hpp` 已 `git mv` 到 `Inc`:
`Utilities/Inc/DataModelInternal.hpp`、`Components/Application/Inc/ApplicationInternal.hpp`、
`Components/PlotView/Inc/PlotViewInternal.hpp`、`Components/SignalPanel/Inc/SignalPanelInternal.hpp`。
- 历史原因:它们原来放在 `Src` 也能编译,因为 `#include "XxxInternal.hpp"` 会先找**源文件所在目录** ——
一旦文件被搬走就无声失效。所有 include 都是扁平形式,靠 `-I.../Inc` 解析,因此搬家**无需改任何 include**。
- ⚠️ `Makefile` 里 `CXX_INCLUDES_PATHS` 上方新增的注释块**不能和该变量写在同一行**(写在同一行会把整个变量注释掉,
症状是 `fatal error: CsvLoader.hpp: No such file or directory`)。本轮踩过一次,已修。
- ⚠️ `Makefile` 是所有 `.o` 的前置依赖 ⇒ 改注释也会触发全量重编(`-MP` 已加 phony 目标,`.d` 不会把构建卡死)。
### B. 常规模式 = 普通鼠标(§11.2 第 222 条)
- `ProbeFreeMarker` 开头新增早退:`if (!lane.freeMarkerCursor) return probe;`(未开启「自由标记点选取」时
不预览数据点、不画纵向光标、`OnLButtonUp` 也不会固定任何点)。`OnLButtonDown` 的固定意图登记同样加上该前提。
- 面板空提示文案按状态区分:未开启 ⇒「开启「自由标记点选取」后单击网格可固定数据点」;已开启 ⇒「在网格内单击以固定数据点」。
- ⚠️ 只有**贴着曲线**(点到折线距离 ≤ `kSignalHitTolerance`)的信号才是可标注目标:`ProbeFreeMarker` 里
`if (!hitCurve) continue;`。少了这一句,纵向光标“整列都在”时 `probe.ref` 会一直有效 ⇒ 任意位置单击都能固定。
### C. 两个显示开关(§11.2 第 223 条)
- 按钮文案「光标选取模式」→「自由标记点选取」(功能不变,`kFreeMarkerCursorModeLabel`)。
其下方新增一行两个半宽切换按钮「显示增量 | 显示枚举文本」,`Lane::freeMarkerShowDelta/freeMarkerShowEnum`
(默认 `false`,`LaneCarry` 双向携带,`SplitLane` 复制到 primary 分支)。
- **只影响已固定点**的胶囊文本;跟随鼠标的预览胶囊恒为 `FreeMarkerValueText(value,false,false,0,true,enumText)`
(即“值 = 枚举”,不受开关影响)。面板统计列不看这两个开关。
- 布局:`EdgePanelLayout` 新增 `showDelta/showEnum`;底部固定区自上而下 = 透明度滑块 → 主按钮 → 开关行,
行间距 `kFreeMarkerButtonGap = 4`;`switchRow` 计入面板高度与内容区高度
(`height = title + pad + view + pad + footer + pad`,`footer = sliderRow + buttonH + gap + switchRow`)。
### D. 六列 / 序号 / N/A / 列分隔线(§11.2 第 224 条)
- 列序:`序号 / 标记值 / 枚举文本 / 增量 / 时间点 / 时间间隔`(`kFreeMarkerColumnLabels[6]`、
`kFreeMarkerColumnWidths[6] = {34,74,80,60,72,78}`、`Lane::freeMarkerColumnWidths` 由 5 → 6)。
- `MarkerRow::serial`(组内 1 起);序号列**恒存在**,用 `m_theme->textMuted` 绘制。
- 枚举列:只有当**某个有固定点的可见信号**带枚举表时才出现;出现时其它无枚举的点、以及数值对不上任何枚举项的点
一律显示 `N/A`(`kFreeMarkerNotAvailable`)。
- 列与列之间画竖线:`cell.left + cell.width + gap*0.5`,颜色 `WithAlpha(borderStrong, 0x6C)`、1px,
数据行与表头都画。
### E. 行悬停压暗 / ✕ 提示移除(§11.2 第 225–226 条)
- 悬停面板某行 ⇒ 该网格其它固定点(数据点 + 胶囊)不透明度封顶 **50%**(原本就 ≤ 50% 的不变),
目标行强制 100%(并保留 accent 圆环 + 2px 描边);移出立即恢复。
⚠️ 命中登记(`m_freeMarkerHits`)也要用压暗后的 alpha 判定,否则会出现“看不见却能点”。
- 删除固定点 ✕ 的悬停浮动提示:`PaintFreeMarkerTooltip` 的**实现与声明都已删除**,不要加回来。
- 信号悬停提示(`PaintSignalInteraction`):该网格开启「自由标记点选取」时文案**只显示信号名**
(与「选区放大」模式同理:左键已专用于固定标记点,拖动也不再是拖信号)。
### F. 缓存键两处补齐(§11.2 第 227–228 条)
- `FreeMarkerContents` 的内容缓存键新增**枚举表的规模与 `texts.data()` 地址**:
旧键只混信号指针与采样数量 ⇒ 给信号加枚举表之后条目里仍然是 `N/A`(离屏探针实测复现)。
- `PanelSlotKey` 新增 `mixRect(layout.showDelta/showEnum)` 与两个开关布尔值:
否则点开关 / 布局变化后会贴回旧像素。
### G. 验证(全离屏,未占用鼠标/键盘/屏幕)
- 新增 `.preflight/mark5check` **52/52**:[A] 常规模式无探测/不固定;[B] 三按钮几何、
两个开关默认关闭且点击可双向切换、点击开关不穿透、不启动拖动;[C] 六列 + 序号 1 起 + 无枚举时缺省枚举列;
[D] 枚举命中 LOW/HIGH、对不上 ⇒ `N/A`;[E] 开关只改已固定点胶囊(默认 `1` / `+增量` `1(+2)` /
`+枚举` `1 = HIGH` / 全开 `1(+2) = HIGH`),**预览胶囊区域像素差 = 0**;[F] 每个列边界都检测到竖线;
[G] 行悬停时另一固定点胶囊像素变化 848px,移出恢复为 0;[H] 选取模式下悬停气泡变窄(1023 → 830,拖拽提示已去掉)。
- 回归(探针已按新语义更新,全部重新链接当天代码):`markcheck` **67/67**(A 段改为“普通鼠标不探测/不固定/拖动仍平移”,
D 段改为“按钮双向切换”,C 段左边缘断言改为序号列)、`fixcheck` **37/37**(列宽断言扩到 6 列含序号)、
`mark4check` **40/40**(E 段先开启选取模式,且“远离曲线”改判 `probe.ref` 无效)、
`round3check` 31/31、`round4check` 34/34、`round5check` 5/5、`editcheck` 20/20、`convcheck` 18/18、
`diag` 19/19;`check` **136/137**(唯一失败项 `the plot is not corrupted by a panel-animated frame` 的
`drift=15818` 与**本轮改动前逐位相同**,是该探针既有的不稳定项)。
- `make release` / `make debug` **零警告**;`TargetCheck.exe` **857,600 字节(837.5 KiB)**。
- ⚠️ 探针坑:`PlotView::FreeMarkerProbe::valid` 在选取模式下**恒为真**(纵向光标整列都在),
判断“是否命中曲线/是否有可固定的点”必须看 `probe.ref.IsValid()`;
在固定点上做像素 A/B 时,固定点若落在悬浮面板下方(绘图区右侧)像素永远不会变 ⇒ 固定点的时间要放在左侧。