修复列表内联编辑(组名/信号名)看不到插入符与选区;把 UI 基础层迁入 Components/Shared

1) 行位图缓存键漏了插入符与选区:信号列表整行走 PaintRowCached,RowCacheKey
   在编辑态只混合“是否编辑 + 文本” ⇒ 左右方向键与鼠标框选虽然改变了 TextEdit
   状态(caret/anchor),键却不变 ⇒ 贴回旧位图。表现就是“无法部分选择、
   鼠标框选无反应、光标不动”,而绘图区的光标时间输入(无行缓存)一直正常。
   修法:GROUP_TITLE / SIGNAL_NAME 两个分支编辑态把 Caret / SelectionBegin /
   SelectionEnd 一并 mix 进键;新增 SignalPanel::EditFieldFont() 统一
   绘制(uiSmall / ui)与鼠标命中、插入符换算所用字体。

2) Theme / PaintUtil / TextEdit / PopupMenu / ColorPickerPopup 由
   Utilities/{Inc,Src} git mv 到 Components/Shared/{Inc,Src}:
   Utilities 只保留纯数据/逻辑模块(DataModel、DataTable、各 *Loader、MatH5、
   Utf8Util),Shared 成为自洽的 UI 基础层(Theme → PaintUtil → UiControls →
   PopupMenu / ColorPickerPopup)。依赖方向仍是 Components → Shared → Utilities;
   PaintUtil 一并迁移是因为它依赖 Theme(否则构成 Utilities → Shared 反向依赖)。
   Makefile 无需改动(include 平铺,两个目录都已在搜索路径),但需清理 Build/*
   里对应的旧 .o/.d。

验证(全部离屏,不占用鼠标/键盘/屏幕):
- 新增 .preflight/editcheck 20/20;A/B 修复前 6 项如实失败(键不变 + 屏幕不重绘);
- 既有 .preflight/check 137/137;
- make release / make debug 零警告。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-10-19 11:11:31 +08:00
1 parent f44f8021e3
commit 1e50494c41
15 files changed
+93 -4

No files matched your search

+61 -2
View File
@@ -2995,6 +2995,8 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
| 2026-10-17 | DeepSeek-V4.1-Flash(**本机**) | **多层加载拖拽卡顿根治 + 高亮命中线段中段 / 散点高亮 + 选区放大也高亮 + 自动点线判定与规则修正(详见 §9.45)**。① **拖拽卡顿(39.2→8.2ms 均值、47.9→10.3ms 最坏)**:**(a)** `RenderLaneLayerRegion` 每次补条都调两次 `BuildLaneVisuals()`(O(网格数))⇒ 253 网格时 `RollWideBuffer` 单帧 **26.8ms**;改为快照/拷回 `m_lanes`;**(b)** 横向“重新居中”纯属优化 ⇒ `kLayerRollQuantumX=32` + `kLayerRollsPerFrame=3`;**(c)** 位移过大时旧实现**同步整块重画**(巨型信号 20~130ms)⇒ `kLayerRollMaxShiftPixels=160` 作废图层交给底衬;`RollWideBuffer` 跳过离屏网格;**(d)** 包络带路径也支持补条裁剪(巨型信号一条 32px 竖带 5ms → 亚毫秒)。② **高亮命中**:`HitTestSignal` 横向窗口少算一个顶点 ⇒ 放大后两点**中间的连线**完全点不中(0/11 → 11/11);散点模式新增“数据点高亮环”(不含连线),列表/图例联动同源。③ **选区放大**恢复悬停高亮(仍不可拖信号),提示只显示信号名。④ **自动点线误判**:判定范围未限制在信号有数据的时段 ⇒ 长跨度文件 + 短信号时 MF4 信号默认视图全部误判(248→0);并改为**只对 `DrawMode::LINE` 生效**(SCATTER 不切换、用户手动改过不切换)。验证:新增 `.preflight/perf/hoverdrag_main.cpp` **20/20**;`verify` 49/49、`panelanim` 158/158、`datacheck` 69/69、`edgecheck` 46/46、`errcheck` 19/19、`gridanim` 93/93、`lanescroll` 23/23;`make release`/`make debug` 零警告。⚠️ 探针的绝对毫秒阈值改为**相对基准**(同一基线代码在不同时段可差 2~3 倍)。§11.2 新增第 141–150 条。 |
| 2026-10-19 | DeepSeek-V4.1-Flash(**本机**) | **修复列表内联编辑(组名/信号名)看不到插入符与选区 + `Utilities` 的 UI 基础层迁入 `Components/Shared`(详见 §12 末尾「2026-10-19 第二轮」)**。① **根因**:信号列表整行走**行位图缓存**(`SignalPanel::PaintRowCached`),而 `RowCacheKey` 只混合“是否编辑 + 编辑文本”,**没有插入符与选区** ⇒ 左右方向键、鼠标框选虽然改变了 `TextEdit` 状态,键却不变 ⇒ 贴回旧位图 ⇒ 用户看到“无法部分选择、光标不动”(绘图区光标时间输入没有行缓存,所以一直正常)。修法:编辑态把 `Caret/SelectionBegin/SelectionEnd` 混进键(分组行与信号行两处),并新增 `SignalPanel::EditFieldFont()`(分组名用 `uiSmall`、其余 `ui`)统一**绘制 / 命中 / 插入符换算**三处字体。② **目录归类**:`Theme.*` / `PaintUtil.*` / `TextEdit.*` / `PopupMenu.*` / `ColorPickerPopup.*` 由 `Utilities/{Inc,Src}` **`git mv`** 到 `Components/Shared/{Inc,Src}`(`Utilities` 只剩纯数据/逻辑;依赖方向仍 `Components → Shared → Utilities`);Makefile 无需改动,但要清掉 `Build/*` 里对应的旧 `.o/.d`。验证:新增离屏 `.preflight/editcheck`(`SW_HIDE` + 合成消息 + `BELOW_NORMAL`)**20/20**(A/B:修复前 6 项如实失败:键不变、屏幕不重绘);`make release`/`make debug` 零警告。 |
## 11. 跨设备协作须知(起源设备视角)
> **本文件是唯一权威记忆**。所有设备 / Agent 共用它,**不要再新建 `agent_mem_origin.md` 等旁支记忆文件**。
@@ -3360,8 +3362,18 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
(名称不再有“回退值”)。
88. ⚠️ **通用 UI 控件属于 `Components/Shared`**(用户 2026-10-16 要求建此组件):
图标 / 复选框 / 滑块 / 内联输入框 / 颜色样块 / 取值胶囊配色都在
`Components/Shared/Inc/UiControls.hpp`;`Utilities/PaintUtil.*` **只保留低层绘制原语**。
依赖方向固定 `Components/* → Components/Shared → Utilities`,**不得反向**。
`Components/Shared/Inc/UiControls.hpp`。
⚠️ **【2026-10-19 更新:UI 基础层整体迁入 `Shared`】**用户指出 `Utilities` 里那些“会绘制/承载
UI”的模块不属于纯粹工具范畴,现全部位于 **`Components/Shared/{Inc,Src}`**:
`Theme.*`(调色板与 `ToGdiColor/MakeArgb/WithAlpha/MixColor`)、`PaintUtil.*`(低层绘制原语)、
`TextEdit.*`(内联编辑模型)、`PopupMenu.*`、`ColorPickerPopup.*`。
⇒ **`Utilities/` 只剩纯数据/逻辑模块**(`DataModel`、`DataTable`、`CsvLoader`、`DataLoader`、
`Mf4Loader`、`MatH5`、`MatLoader`、`Utf8Util`),**不得**再往 `Utilities` 放任何包含
`gdiplus.h` 的绘制/控件代码。
依赖方向仍是单向:**`Components/* → Components/Shared → Utilities`**(`Shared` 可以消费
`Utilities` 的 `Utf8Util` 等,反向禁止)。搬移时**只需 `git mv`**:`#include "X.hpp"` 是平铺写法,
两个目录都在 `CXX_INCLUDES_PATHS` 里,**Makefile 无需改动**(但要清掉 `Build/*` 里那几个
`Theme.o/PaintUtil.o/TextEdit.o/PopupMenu.o/ColorPickerPopup.o` 及其 `.d`,否则旧依赖文件指向旧路径)。
新增组件目录要同时登记 `Makefile`(`CXX_INCLUDES_PATHS` / `CXX_SOURCES_PATHS`)与
`.preflight/perf/build.ps1`。
89. ⚠️⚠️ **新增标识符前必须确认不是 Windows 头里的宏**:`windows.h` 会引入 `nb30.h` 的
@@ -6356,3 +6368,50 @@ else if (panelOnly) { /* 只回送“本帧重绘过的区域并集” */ }
用探针从**真实产物** `LoadImageW` 逐尺寸校验,而不是只看文件能编译。
5. **任何"长时间解析"都要按阶段回报进度**(读字节 + 每个解码单元),
且 `hasBytes` 只在真正有字节可报的阶段置真,否则遮罩层会停在 0%。
---
## 本轮(2026-10-19 第二轮,本机):列表内联编辑看不到插入符/选区 + UI 基础层迁入 `Components/Shared`
> 用户报告两件事:① 信号列表里**组名**双击进入编辑后与其它输入框状态不一致 ——
> 无法部分选择、鼠标框选无反应、左右方向键也不移动插入符;② `Utilities/{Inc,Src}` 里的
> `ColorPickerPopup` / `PopupMenu` / `TextEdit` / `Theme` 等其实是会绘制的 UI 组件,应归到
> `Components/Shared`。
> 验证:新增离屏 `.preflight/editcheck`(`SW_HIDE` + 合成消息 + `BELOW_NORMAL`)**20/20**;
> **A/B:修复前 6 项如实失败**(键不变 + 屏幕不重绘)。`make release` / `make debug` 零警告。
### A. ① 的根因:行位图缓存的键漏了「插入符与选区」
- 信号列表为了流畅性把**整行**渲染进离屏 DIB 缓存(`SignalPanel::PaintRowCached`,`24f0bf8` 引入),
命中时一次 `BitBlt`。但 `RowCacheKey()` 在编辑态只混合了 **`editing` 标志 + `m_edit.Text()`**。
- 于是 **方向键 / 鼠标框选只改变 `TextEdit` 的 `caret / anchor`,文本没变 ⇒ 键没变 ⇒ 贴回旧位图**
⇒ 屏幕上插入符与选区完全不动(**输入字符**时才刷新,所以只表现为“不能部分选择/光标不动”)。
绘图区的光标时间输入没有行缓存,所以一直正常 —— 这正是用户说的“状态不一致”。
⚠️ 信号名编辑走同一套行缓存,同样有此缺陷(只是用户先注意到组名)。
- ✓ 修法:两个分支(`GROUP_TITLE` / `SIGNAL_NAME`)在编辑态把
`Caret()` / `SelectionBegin()` / `SelectionEnd()` 一并 mix 进键。
- ✓ 顺带统一字体:新增 `SignalPanel::EditFieldFont()`(分组名 = `uiSmall`,其余 = `ui`),
供 `OnEditMouseDown` / `OnEditMouseMove` 的 `UiEditOffsetAt` 使用 ——
绘制(`PaintGroupRow` 用 `uiSmall`、`PaintSignalRow` 用 `ui`)与**插入符换算必须同字体**,
否则“点哪儿插入符落在哪儿”这个不变量会被破坏。
### B. ② 的落地:`Utilities` 只保留纯数据/逻辑
| 旧位置 | 新位置 |
| --- | --- |
| `Utilities/Inc/Theme.hpp` + `Utilities/Src/Theme.cpp` | `Components/Shared/{Inc,Src}/Theme.*` |
| `Utilities/Inc/PaintUtil.hpp` + `Utilities/Src/PaintUtil.cpp` | `Components/Shared/{Inc,Src}/PaintUtil.*` |
| `Utilities/Inc/TextEdit.hpp` + `Utilities/Src/TextEdit.cpp` | `Components/Shared/{Inc,Src}/TextEdit.*` |
| `Utilities/Inc/PopupMenu.hpp` + `Utilities/Src/PopupMenu.cpp` | `Components/Shared/{Inc,Src}/PopupMenu.*` |
| `Utilities/Inc/ColorPickerPopup.hpp` + `Utilities/Src/ColorPickerPopup.cpp` | `Components/Shared/{Inc,Src}/ColorPickerPopup.*` |
- **为什么连 `PaintUtil` 一起搬**:`PaintUtil.hpp` 依赖 `Theme.hpp`(`ToGdiColor` 等)。
若只搬 `Theme`/`TextEdit`,`Utilities` 反而要包含 `Shared` 的头文件 ⇒ **反向依赖**,
违反第 88 条的单向分层。搬完之后 `Shared` 是自洽的“UI 基础层”:
`Theme`(设计令牌/颜色)→ `PaintUtil`(低层原语)→ `UiControls`(控件)→ `PopupMenu`/`ColorPickerPopup`。
- 依赖方向不变:**`Components/* → Components/Shared → Utilities`**;`Utilities` 现在只剩
`DataModel` / `DataTable` / 各 `*Loader` / `MatH5` / `Utf8Util`,**不得**再放 `gdiplus.h` 系代码。
- 搬移手法:`git mv`(保留历史)+ **Makefile 无需改动**(`#include "X.hpp"` 平铺,两个目录都已在
`CXX_INCLUDES_PATHS/CXX_SOURCES_PATHS`)。⚠️ 必须删掉 `Build/Release|Debug` 里对应的
旧 `*.o` / `*.d`(`.d` 里记着旧路径,会让 make 误判/漏依赖)。
- 文档里 §11.2 第 88 条已按本表更新(历史章节里出现的 `Utilities/PaintUtil.*` 等仅作历史记录)。