自由标记改进:默认不启用光标模式 + 面板四列对齐 + 光标模式切换按钮

用户需求(逐条落地):
1) 默认不启用网格私有光标,只有鼠标处于信号上方时才显示数据点数值;命中
   「自动点线」稀疏判据的信号,只有靠近数据点时才有数值显示;
2) 有数值预览时左键单击固定该数据点(固定点样式不变:半透明纵向细线);鼠标
   下方没有信号曲线时,按下/拖动就是普通的平移视界(选区放大模式下照旧框选);
3) 浮动面板最下方新增切换按钮「启用光标模式」↔「关闭光标模式」;启用后与最初
   实现一致(跟随鼠标的纵向自由光标),并修掉「光标模式下拖不动浮动面板」;
   鼠标处于浮动面板上时网格不画自由光标,面板上的操作不穿透到网格;
4) 面板只列出确实有固定点的信号(否则该信号名条目不出现);
5) 每个信息元素纵向对齐:取值 / 增量 / 时刻 / 间隔各自一列。

数据层
- Lane 新增 bool freeMarkerCursor(默认 false,功能总开关仍是 freeMarker);
  LaneCarry 同步携带。
- PlotView 新增 SetLaneFreeMarkerCursor / LaneFreeMarkerCursor /
  ToggleLaneFreeMarkerCursor,切换时立即作废属于该网格的探针。

探针与绘制
- FreeMarkerProbe 新增 cursorMode。
- 非光标模式:稀疏判据成立但吸附失败 ⇒ 跳过该信号;其余要求鼠标与曲线纵向距离
  在 kFreeMarkerHoverTolerance(8 逻辑像素)以内;都不满足 ⇒ 探针无效 ⇒ 按下即
  普通平移/框选,不会误固定数据点。
- 光标模式:与之前实现一致(网格内始终有效)。
- PaintFreeMarker:纵向线 + 上下把手只在光标模式绘制;取值胶囊/数据点/吸附圆环
  两种模式都画。

浮动面板
- 底部新增「启用光标模式 / 关闭光标模式」切换按钮(layout.button),手型光标 +
  悬停高亮,PanelSlotKey 混入 freeMarkerCursor。
- 只给有固定点的信号发名称行(高度分支与矩形分支同步跳过空信号)。
- 四列固定横坐标(EdgePanelLayout::markerColumns:取值 / 增量 / 时刻 / 间隔),
  面板宽度 340 → 415(= 4 列 + 间隙 + 行 ✕ + 两侧内边距);绘制一律左对齐 +
  省略号截断,双击分行改按列边界判断(不再用 xxxRight - 40*scale 反推)。

修复的缺陷(用户报告)
- 「光标模式下拖不动浮动面板」的真因不是命中判定,而是 OnMouseMove 的
  EDGE_PANEL_MOVE 分支里 switch (m_edgePanelDragKind) 漏了 MARK:拖动坐标被写进
  lane.edgePanel,而布局从 lane.freeMarkerPanel 读 ⇒ 面板纹丝不动。已补 case。
- 鼠标压在浮动面板上时:OnMouseMove 先 TopPanelAtPoint,命中即清空探针并跳过固定
  点 ✕ 的悬停判定;OnLButtonDown 的自由标记分支增加 freeOverPanel 守卫,
  确保面板操作不穿透到网格(也不再绘制穿过面板的自由光标)。

验证(全程离屏,不占用鼠标/键盘/屏幕)
- .preflight/markcheck 重写并扩到 61/61:默认无光标、贴近曲线才有效、远离曲线单击
  不固定且拖动仍是平移、四列几何对齐、按钮切换光标模式、光标模式下拖动面板确实
  移动、面板上不画光标、选区放大共存、Δt 编辑重排、两处 ✕、空信号不出行、深度
  放大吸附、视界外固定点不绘制。
- 回归:editcheck 20/20、round3check 31/31、round4check 34/34、round5check 5/5、
  convcheck 18/18、check 136/137(唯一失败项是此前就存在的不稳定断言)、真实
  MF4-Record.MF4 仍 283 条信号。
- make release / make debug 零警告;Build/Release/Target.exe 834,560 字节。
- 同步更新 Documents/agent_mem.md(§11.2 第 189–193 条 + 文末本轮章节)。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-20 20:39:42 +08:00
1 parent dd8f63aa0e
commit 067128f46c
8 files changed
+412 -86

No files matched your search

+94
View File
@@ -3900,6 +3900,24 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
绘制时重建、`OnMouseMove`/`OnLButtonDown` 读取。
188. ⚠️ **`PaintFreeMarker` 必须画在 `PaintEdgeCursor`(浮动面板)之前**:面板在最上层,
自由标记的胶囊/✕ 不得盖住面板;接入点是 `paintOverlays()`(三个绘制分支共用)。
189. ⚠️⚠️ **`EDGE_PANEL_MOVE` 的 `switch (m_edgePanelDragKind)` 必须为每个新面板加一个 case**:
新增面板种类时若漏掉,拖动会把坐标写进 `edgePanel`,而布局又从 `xxxPanel` 读 ⇒
症状是"面板**完全拖不动**"(不是"拖动后回弹",容易误判成命中问题)。新增 `MARK` 时就踩了这个坑。
190. ⚠️⚠️ **「自由标记」默认不显示网格私有光标**:`Lane::freeMarkerCursor`(默认 false)才决定
是否画那条纵向线。默认模式下 `ProbeFreeMarker` 仅在鼠标**纵向贴近某条曲线**
(`kFreeMarkerHoverTolerance`)时有效;命中「自动点线」稀疏判据的信号还要求
`SnapTimeToSample` 成功(即靠近真实数据点)。鼠标下方没有曲线 ⇒ 探针无效 ⇒
按下就是普通平移/框选,**不会误固定数据点**(用户明确要求)。
191. ⚠️⚠️ **鼠标压在浮动面板上时必须清空自由标记探针**(`OnMouseMove` 里先 `TopPanelAtPoint`,
命中就把 `m_freeMarker` 置默认):否则光标模式下纵向光标会**穿过面板**,
且固定点的 ✕ 命中矩形可能抢走面板上的点击("面板上的操作穿透到网格")。
`OnLButtonDown` 的自由标记分支也要用同一守卫兜一层。
192. ⚠️⚠️ **面板里的"列"必须在 `EdgePanelLayout` 里给定横坐标**(`markerColumns`),
绘制侧只读不反推:这样"同一信息纵向对齐"是几何保证,而不是靠文本测量的巧合;
双击分行(编辑时刻 / 编辑 Δt)也必须用这些列边界,不能再用 `xxxRight - 40*scale` 之类的近似值。
193. ⚠️ **面板里"没有内容的条目"不要出现在布局里**:自由标记面板现在只给**确实有固定点**的
信号发名称行(`SortedFreeMarkerIndices` 为空就 `continue`),高度分支与矩形分支必须同步
跳过,否则面板会多出空白行。
### 11.3 离屏验证方法学(本机偏好,强烈建议沿用)
@@ -7200,5 +7218,81 @@ DG3 data=0 cycle=0 (空组,一个字符串通道)
胶囊绘制去重。剩余体积是新功能的真实代码量(~800 行新代码 / ~30 B 每行)——
若必须回到 800 KiB 以内,需要用户决策(动态 CRT / UPX / 砍其它功能),本轮按"实现功能优先"未动。
---
## 本轮(2026-10-20 第八轮,本机):「自由标记」体验改进(默认无光标 + 四列对齐 + 光标模式按钮)
> 用户需求(逐条):
> ① **默认不启用**网格私有光标,只有鼠标处于信号上方时才显示数据点数值;命中「自动点线」稀疏判据的
> 信号要"只有靠近数据点时"才显示;② 有数值预览时左键单击固定该点(固定点样式不变:半透明纵向细线);
> 鼠标下方没有信号曲线时就是普通拖拽平移(选区放大模式下照旧框选);
> ③ 浮动面板**最下方**加一个切换按钮「启用光标模式」↔「关闭光标模式」,启用后与最初实现一致
> (纵向自由光标),但**必须修掉"光标模式下拖不动面板"**,且鼠标在面板上时网格不画光标、
> 面板上的操作不穿透到网格;④ 面板只列**有固定点**的信号(信号名条目否则不出现);
> ⑤ 每个信息元素**纵向对齐**(当前值 / 增量 / 当前时间 / 相对时间各自一列)。
### A. 数据层
- `Lane` 新增 `bool freeMarkerCursor = false`(**光标模式**开关,默认关闭)。
`freeMarker` 仍是功能总开关;`LaneCarry` 同步携带(增删信号导致网格重建时不丢状态)。
- `PlotView` 新增 `SetLaneFreeMarkerCursor / LaneFreeMarkerCursor / ToggleLaneFreeMarkerCursor`;
切换时若探针属于该网格就**立即作废**(否则关闭后仍残留纵向光标、开启后要等鼠标动一下)。
### B. 探针与绘制(默认模式 vs 光标模式)
- `FreeMarkerProbe` 新增 `cursor.cursorMode`。`ProbeFreeMarker`:
* **默认(非光标)**:同一信号若命中 `MinorCellSparse` 判据却**吸附失败** ⇒ 直接跳过
(两点之间不出预览);其余信号要求 `|y - mouseY| <= kFreeMarkerHoverTolerance`(8 逻辑像素);
一个都不满足 ⇒ `valid == false`(无预览 ⇒ 单击/拖动回到普通平移/框选)。
* **光标模式**:与原实现一致(网格内恒 `valid`,能取到点时才标注取值)。
- `PaintFreeMarker`:纵向线 + 上下把手**只在光标模式**绘制;取值胶囊 / 数据点 / 吸附圆环两种模式都画。
### C. 浮动面板
- 底部新增切换按钮(`layout.button`,高度 `kEdgePanelButtonHeight` + 上下 `pad`),
文案由 `lane.freeMarkerCursor` 决定(`kFreeMarkerCursorOnLabel` / `kFreeMarkerCursorOffLabel`),
手型光标 + 悬停高亮;`PanelSlotKey` 里 mix `freeMarkerCursor`(否则开关后贴回旧像素)。
- **只列有固定点的信号**:高度分支与矩形分支都用 `SortedFreeMarkerIndices(...).empty()` 跳过。
- **四列对齐**:`EdgePanelLayout::markerColumns[4]`(取值 / 增量 / 时刻 / 间隔)给定固定左边界与列宽
(`kFreeMarkerColumnWidths`,列间 `kFreeMarkerColumnGap`),面板宽度改为
`kFreeMarkerPanelWidth = 415`(= 4 列 + 间隙 + 行 ✕ + 两侧 pad,正好不多不少)。
绘制一律左对齐 + `UiEllipsize`;**不再**用"左文 + 右对齐两列"的混排。
- 双击分行改为按列边界判断(≥ Δt 列左边界 ⇒ 编辑间隔;否则编辑时刻),不再用 `xxxRight - 40*scale`。
### D. 修掉的 BUG(用户报告:"光标模式下拖不动浮动面板")
根因**不是**命中判定,而是 `OnMouseMove` 的 `case PlotDragMode::EDGE_PANEL_MOVE` 里
`switch (m_edgePanelDragKind)` **漏了 `MARK` 分支**:拖动时坐标被写进 `lane.edgePanel`,
而 `EdgePanelLayoutFor` 从 `lane.freeMarkerPanel` 读位置 ⇒ 面板纹丝不动
(既没移动也没报错,看起来像"拖拽没生效")。补上 `case EdgePanelKind::MARK` ⇒ 写入 `freeMarkerPanel`。
### E. 面板与网格的隔离
- `OnMouseMove`:先 `TopPanelAtPoint`,命中则把探针置空(光标模式下不再画穿过面板的光标),
固定点 ✕ 的悬停判定也一并跳过。
- `OnLButtonDown`:自由标记的两个分支(固定点 ✕ / 登记固定意图)都加了 `freeOverPanel` 守卫,
确保面板上的按下永远不会被网格抢走。
### F. 验证
- `.preflight/markcheck` 重写并扩到 **61/61**:
[A] 默认无光标(`LaneFreeMarkerCursor == false`)、贴近曲线才有效、远离曲线单击不固定、
拖动仍是平移、预览点落在悬停容差内; [B] 贴近曲线单击恰好固定 1 个点,再补 2 个共 3 个;
[C] 面板只给有固定点的信号发名称行、四列有宽度/不重叠/首列与信号名同左边界/全在行 ✕ 左侧、
行按时间升序、首项无增量;
[D] 底部按钮首次点击 → 光标模式开启(远离曲线也有效、`cursorMode == true`)、再点关闭、
按钮点击不会固定任何点;
[E] 光标模式下拖标题栏**确实移动面板**、拖动不固定点、内容不丢;
[F] 鼠标移到面板上 ⇒ 探针被清空(不画光标);
[G] 关掉光标模式后:选区放大里原地单击=固定且不缩放、拖动=缩放且不固定;
[H] 编辑 Δt 后该点移动并在越过后续点时变成最右项;
[I] 行尾 ✕ 只删 1 项、信号名 ✕ 清空该信号全部、清空后面板不再发任何信号行;
[J] 深度放大 `snapped == true` 且时刻精确等于采样时刻、视界外固定点不绘制。
- 回归:`editcheck` 20/20、`round3check` 31/31、`round4check` 34/34、`round5check` 5/5、
`convcheck` 18/18、`check` **136/137**(唯一失败项仍是那条已知不稳定项)、
真实 MF4 仍 **283** 条信号。
- `make release` / `make debug` **零警告**;`Build/Release/Target.exe` **834,560 字节(815.0 KiB)**。