Files
Just-DataInspector/Documents/agent_mem.md
T
DeepSeek V4.1 Flash 2322e76d8c 修复二级菜单移向途中被误关闭;新增项目记忆文档 agent_mem.md
网格右键菜单「实验性功能」展开二级菜单后,鼠标从父项移向子菜单途中经过内边距窄带会被立即收起。改为子菜单展开期间只要指针仍在主菜单∪子菜单范围内且未落到其它可点击条目即保持展开并高亮父项。
2026-10-11 02:59:41 +08:00

167 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Just DataInspector — Agent 记忆与项目须知
> 本文件是本仓库的**权威上下文备忘录**,供任何接手的 AI Agent 在动手前阅读。
> **每次完成任务后必须同步更新本文件**(补充新需求、修复记录、约定变更等)。
> 保持内容**精确、明细、简练**;多台设备协作时,可将各自的记忆合并到本文件。
---
## 1. 项目目标
- 使用 **C++17 + Win32 API(GDI/GDI+)** 从零构建的桌面数据查看器,项目名 **Just DataInspector**。
- 定位:替代 MATLAB/Simulink 的 `Simulink.sdi.view` 仿真数据检查器,用于更方便地查看**带时间轴的 CSV** 仿真数据。
- 目标数据特征(参考 MathWorks 导入 CSV 的说明):CSV 中存在**一个或多个时间轴列**,其余列表示各时间点上的信号值。
- 产物为 **GUI 程序**(非 CUI)。
---
## 2. 构建与工具链
- 工具链:**MinGW-w64**(`x86_64-win32-seh-rev0`, MinGW-Builds 16.1.0),可直接用 `make`。
- 构建入口:根目录 `Makefile`(C / C++ / windres 混合构建)。
- 常用命令:
- `make release` → `Build/Release/Target.exe`(`-Os`,strip:`-s`)。
- `make debug` → `Build/Debug/Target.exe`(`-O0 -g`)。
- `make` → 同时构建 Release 与 Debug。
- `make clean` → 删除 `Build/`。
- 关键编译设置:`-std=c++17`;`-finput-charset=UTF-8 -fexec-charset=GBK -fwide-exec-charset=UTF-16LE`;`-static`;`-mwindows`(GUI);链接 `gdi32 gdiplus comdlg32 d3d11 dwmapi d3dcompiler`。
- **新增组件/工具目录后,必须在 `Makefile` 的 `CXX_INCLUDES_PATHS` 与 `CXX_SOURCES_PATHS` 中登记**(源文件按目录通配自动收集)。
- 构建产物统一在 `Build/`,已由 `.gitignore` 忽略;同时忽略 `*.o/*.d/*.lst/*.map/*.exe` 与 `TestData/`。
---
## 3. 目录结构与约定
```
Components/ 功能组件块(每块 Inc/ 放 .hpp,Src/ 放 .cpp)
Application/ 应用主框架:窗口、布局、消息分发、标签页、绘制合成
Main/ 程序入口(WinMain → Application::Run)
TabBar/ 顶部多标签栏
Toolbar/ 顶部工具栏(导入文件 / 适应视图 / 时间轴自适应 / Y 轴自适应 / 选区放大 / 光标 / 合并·拆分·清空网格)
SignalPanel/ 左侧信号面板:按文件分组的信号树、可见性勾选、样式编辑
PlotView/ 波形绘图区:网格、时间轴、光标、缩放、拖拽、实验性功能面板
Utilities/ 工具与辅助模块(Inc/ + Src/)
Application/ ... (见上)
CsvTable/ CSV 流式解析(列优先)
DataModel/ 数据层:DataSet / DataFile / SignalData / 显示配置
PaintUtil/ GDI+ 绘制与文本/控件辅助(含 UiPointInRect、UiMeasureTextWidth 等)
PopupMenu/ 主题化自绘弹出菜单(含二级子菜单、内联编辑)
ColorPickerPopup/ 浮动拾色器
TextEdit/ 内联文本编辑模型
Theme/ 主题色板(Solarised Light)与波形默认配色
Utf8Util/ 编码转换(UTF-8 ↔ UTF-16 等)
Resources/ 图标、清单(.manifest)、版本信息(.rc)、ResourceIds.h
TestData/ 本地测试 CSV(**不纳入版本控制**)
Documents/ 项目文档(含本文件)
```
- **命名硬性约束**:源文件/头文件**不得含空格**,只能字母与下划线组合。
- **头文件后缀**:C 用 `.h`,C++ 用 `.hpp`;C 源 `.c`,C++ 源 `.cpp`。
- **防重复包含**:每个头文件必须 `#ifndef __XXX_XX_HPP__ / #define __XXX_XX_HPP__ / ... / #endif`;宏名 = 文件名的双边双下划线 + 全大写。
- **宏定义与枚举常量必须全大写 + 下划线**。
- 所有对外函数/方法声明用 Doxygen 风格注释:`@brief`、`@param [IN/OUT]`、`@return`(中文说明)。
- 代码风格统一,强调**解耦**与清晰的分层。
---
## 4. 架构要点
- **数据层共享、视图配置分标签页**:全局 `DataSet`(已加载文件、信号、时间轴)被所有标签页共享;每个标签页仅持有各自的 `TabConfig`(信号可见性、配色、分组、网格等),互不影响。
- `Application` 是总编排者:创建窗口、`Relayout` 布局、`HandleMessage` 分发消息、合成绘制、把菜单/拾色器结果派发回组件。
- 自定义绘制的浮动控件(`PopupMenu`、`ColorPickerPopup`)**不创建独立窗口**,作为宿主绘制的**最上层内容**直接画进后备缓冲区,保证外观与主界面统一(不出现系统默认菜单样式)。
- 消息优先级:菜单打开 > 拾色器打开 > 常规组件交互(见 `Application::HandleMessage`)。
- DPI 感知:`ApplyDpi` 重建字体与布局;浮动控件通过 `SetScale` 缩放。
### 数据模型(`Utilities/Inc/DataModel.hpp`)
- `SignalData`:单条信号元数据 + 采样值。
- `DataFile`:一个已加载文件及其**自有时间轴**(`timeColumnName` / `time` / `minTime` / `maxTime` / `timeMonotonic`)。
- `DataSet`:文件集合与全局时间范围查询(`MinTime/MaxTime`、最近采样点查找等)。
- `DrawMode`:`LINE`(插值折线) / `SCATTER`(散点) / `LINE_SCATTER`(两者)。
- `LaneMode`:`PER_SIGNAL` / `MERGED` / `CUSTOM`(网格划分策略)。
- `PlotCursorMode`:`NONE` / `SINGLE` / `DOUBLE`(时间光标三态)。
- 各网格自身状态(Y 轴范围、自适应开关、实验性功能开关等)随信号继承。
### CSV 解析(`Utilities/Src/DataModel.cpp`)
- 列优先存储(每条信号一整块连续内存):避免百万行级按行存储的堆分配放大,并支持整列**移动**进 `SignalData`。
- 流式分块读取,可携带真实字节进度(`CsvProgressInfo`),支持取消。
- **时间列判定** `LooksLikeTimeHeader`:小写匹配 `t / time / timestamp / simulation time`,或包含 `time` / `时间`;未命中时回退第 0 列。
- 缺失值以 `NaN` 表示;要求时间列有效数值 ≥ 2,否则报错。
- 分隔符自动探测(默认 `,`)。
---
## 5. 功能需求清单(来自需求交互,持续补充)
### 5.1 基础功能(首轮构建目标,已实现)
- 波形网格(多网格);时间轴。
- 光标(单/双光标,含差值读数)。
- 缩放与自适应(适应视图、Y 轴自适应、选区放大)。
- 导入并加载符合要求(带时间轴列)的 CSV,**解析出信号名**。
- 信号样式:**修改颜色、粗细、散点/插值线段显示方式**(`DrawMode`)。
- 信号可绘制到**同一网格**或**不同网格**。
### 5.2 后续扩展(已在代码中实现,供接手参考)
- 多标签页(新建/关闭/重命名/拖拽排序)。
- 工具栏:合并网格 / 拆分网格 / 清空网格;时间轴自适应。
- 信号面板:按文件分组、勾选可见性、仅显示/全部显示/隐藏全部、移除文件。
- 绘图区拖拽:平移、选区放大(按首个明显位移方向决定横/纵轴)、网格滚动、光标拖拽、**把信号曲线拖到其它网格**、网格图例 GX 徽标上下重排。
- 图例:悬停高亮、内联重命名、信号删除按钮。
### 5.3 「实验性功能」二级菜单(网格右键菜单内,横线上方)
包含且仅包含以下可勾选项(每网格独立状态):
- **边沿计数**
- **边沿计数(中心轴)**
- **均值滤波**
- **弱波增强**
这些功能开关会联动绘图区的浮动参数面板;部分支持「构建为新信号」。
> 注意:新增/改名实验性功能时,需同步 `PlotView.hpp` 的 `PLOT_CMD_LANE_*`、`Application.cpp` 的菜单构建与派发、`PlotView`/`DataModel` 的状态位与面板绘制。
---
## 6. UI / 交互设计语言
- 参考 **VS Code** 与 **WinUI** 的设计语言;配色为 **VS Code 的 Solarised Light** 方案(`Theme::SolarizedLight()`,强调色 `accent`)。
- 全部界面与交互用 **Win32 API** 自绘,不用系统默认控件样式。
- 文本对齐、菜单内边距、圆角、阴影等在各浮动控件内保持统一风格。
---
## 7. 交付与 Git 规范
- 工作区由**本地 git** 管辖。
- **仅在功能完善(可验证)后才提交**;提交信息用简洁中文描述修改内容。
- 提交时**仅对本工作区**生效(`git config --local`),**不得影响全局设置**:
- `user.name` = 当前模型全称。
- `user.email` = `<>`(留空尖括号)。
- `TestData/`、`Build/` 等不提交(见 `.gitignore`)。
---
## 8. Agent 工作流要求
1. 接手前先**探索工作区/提交历史/代码**建立认知(本文件应作为第一参考)。
2. 完成需求后**编译验证**(`make release` 至少成功),必要时用 `TestData/` 数据功能验证。
3. **验证与探索时尽量不占用用户的鼠标/屏幕/键盘**(后台构建为主)。
4. 本地仓库提交完成后,**不要在未经指示的情况下继续探索或优化**,等待用户下一步指令。
5. **每次完成任务后更新本文件**(需求、修复、约定变更)。
---
## 9. 已知问题与修复记录
### 9.1 网格右键菜单「实验性功能」二级菜单瞬间关闭(已修复)
- **症状**:在网格右键菜单里把鼠标从「实验性功能」移向右侧二级菜单的途中,只要指针短暂离开父项交互区域,二级菜单立即关闭,用户来不及完成选择。旧设备 CPU 较慢、鼠标移动事件稀疏,指针可能"跳"进二级菜单而未暴露该问题;CPU 更快、事件更密集时必然复现。
- **根因**(`Utilities/Src/PopupMenu.cpp` 的 `PopupMenu::OnMouseMove`):
- 子菜单展开后,只要指针**不在子菜单矩形内**且**未命中任何可点击条目**,就无条件 `CloseSubmenu()`。
- 主菜单条目矩形的右缘为 `menu.right - kPadH`,而子菜单左缘为 `menu.right - kSubOverlap`,两者之间存在约 3px 的**内边距"死区"**(位于主菜单矩形内但落在任何条目之外)。鼠标事件密集时指针必然落入该窄带,从而触发误关闭。
- **修复**:子菜单展开期间,若指针仍位于「主菜单 ∪ 子菜单」矩形范围内、且尚未落到**其它可点击条目**上(例如掠过内边距窄带、分隔线、禁用项),则保持子菜单展开并维持父项高亮;只有明确移动到其它条目或完全离开上述范围时才收起。
---
## 10. 变更日志(本文件维护记录)
| 日期 | 设备/模型 | 摘要 |
| --- | --- | --- |
| 2026-10-11 | DeepSeek-V4.1-Flash | 新建本文件;记录项目要点与规范;修复「实验性功能」二级菜单瞬间关闭问题。 |