输入框鼠标编辑、图例省略、信号跨视图共享选择与网格菜单布局修复

- 输入框:支持鼠标左键点击定位插入符、拖拽框选区域,并且不再限制字符长度
- 输入框:长文本使用 ETO_CLIPPED 裁剪绘制,避免字符溢出到编辑区域之外
- 图例:信号名称超过 200px 时省略号截断,不再挤压标尺区域
- 选中状态从 TabConfig 迁移到 DataSet,切换视图后信号选中状态保持一致
- 网格右键菜单:Y 轴最大值/最小值直接显示当前值,点击后原位置弹出内联编辑框
- 标尺数值改为绘制在图例下层,不再因避让图例而隐藏
- 移除已无用的 LegendBandRect,新增共享的编辑框布局与命中检测工具
- .gitignore 忽略 TestData 测试数据目录
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-09-30 17:10:23 +08:00
1 parent e3744f3eff
commit 12b3531485
19 files changed
+790 -186

No files matched your search

+21
View File
@@ -124,6 +124,27 @@ namespace jdi
*/
bool CollapseEditSelectionToEnd();
/**
* @brief 编辑态下在输入框内按下鼠标左键:定位插入符并开始拖拽框选。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @return 命中输入框返回 true。
*/
bool OnEditMouseDown(int x, int y);
/**
* @brief 编辑态下拖拽鼠标:扩展选区。
* @param [IN] x 客户区横坐标。
* @return 选区发生变化返回 true。
*/
bool OnEditMouseMove(int x);
/**
* @brief 编辑态下松开鼠标左键:结束拖拽框选。
* @return 之前处于拖拽中返回 true。
*/
bool OnEditMouseUp();
/**
* @brief 设置剪贴板所有者窗口句柄(用于输入框的复制/粘贴)。
* @param [IN] owner 宿主窗口句柄,允许为空。
+25 -13
View File
@@ -249,8 +249,33 @@ namespace jdi
*/
double MaxTime() const;
/**
* @brief 获取当前选中的信号(全标签页共享)。
* @return 信号引用。
*/
const SignalRef& Selected() const { return m_selected; }
/**
* @brief 设置当前选中的信号(全标签页共享)。
* @param [IN] ref 信号引用;传入无效值表示取消选择。
*/
void SetSelected(const SignalRef& ref) { m_selected = ref; }
/**
* @brief 在数据层移除某文件之前,按旧下标修正选中引用。
* @param [IN] fileIndex 即将被移除的文件下标。
*/
void RemapSelectionAfterFileRemoval(int fileIndex);
/**
* @brief 校验选中引用是否仍指向存在的信号,失效则取消选中。
* @return 选中状态发生变化返回 true。
*/
bool ValidateSelection();
private:
std::vector<DataFile> m_files; /**< 已加载文件集合。 */
SignalRef m_selected; /**< 当前选中信号(跨标签页共享)。 */
};
/**
@@ -452,18 +477,6 @@ namespace jdi
*/
void ToggleCollapsed(int fileIndex);
/**
* @brief 获取当前选中的信号引用。
* @return 信号引用。
*/
SignalRef Selected() const { return m_selected; }
/**
* @brief 设置当前选中的信号。
* @param [IN] ref 信号引用,无效值表示取消选择。
*/
void SetSelected(const SignalRef& ref) { m_selected = ref; }
/**
* @brief 计算某网格的 Y 轴显示范围。
* @param [IN] dataSet 数据集合。
@@ -513,7 +526,6 @@ namespace jdi
std::vector<bool> m_collapsed; /**< 文件分组折叠状态,按文件索引。 */
std::vector<Lane> m_lanes; /**< 网格划分。 */
LaneMode m_laneMode = LaneMode::PER_SIGNAL; /**< 网格划分策略。 */
SignalRef m_selected; /**< 当前选中信号。 */
double m_viewMin = 0.0; /**< 视图左边界时间。 */
double m_viewMax = 1.0; /**< 视图右边界时间。 */
bool m_viewInitialized = false; /**< 视图范围是否已初始化。 */
+61
View File
@@ -154,6 +154,44 @@ namespace jdi
*/
float UiMeasureTextWidth(HFONT font, const std::wstring& text);
/**
* @brief 在指定裁剪矩形内以显式起点绘制一段文本(使用 GDI ExtTextOut 裁剪)。
*
* `UiText` 走 `DrawTextW`,**不遵循 GDI+ 裁剪区**;输入框在长内容、水平滚动的情况下
* 会把字符画到框体之外。本函数用 `ETO_CLIPPING` 让 GDI 自己裁剪,彻底避免越界绘制。
*
* @param [IN,OUT] g 绘图上下文。
* @param [IN] text 文本内容。
* @param [IN] font 字体句柄。
* @param [IN] x 文本起始横坐标。
* @param [IN] rect 垂直居中参考矩形。
* @param [IN] argb 文本颜色。
* @param [IN] clipRect 裁剪矩形(超出部分不绘制)。
*/
void UiTextAtClipped(gd::Graphics& g, const std::wstring& text, HFONT font, float x, const gd::RectF& rect,
std::uint32_t argb, const gd::RectF& clipRect);
/**
* @brief 计算输入框文本的绘制起点(已考虑超出框宽时的水平滚动)。
* @param [IN] rect 输入框矩形。
* @param [IN] edit 编辑模型。
* @param [IN] font 字体句柄。
* @param [IN] scale 缩放比例。
* @param [OUT] innerWidth 框内可用宽度输出。
* @return 文本绘制起点横坐标。
*/
float UiEditTextLeft(const gd::RectF& rect, const TextEdit& edit, HFONT font, float scale,
float& innerWidth);
/**
* @brief 把输入框内的横坐标换算为字符偏移(就近取整,用于鼠标定位插入符)。
* @param [IN] font 字体句柄。
* @param [IN] text 当前文本。
* @param [IN] localX 相对文本起点的横坐标(可超出 [0, 文本宽度])。
* @return 字符偏移。
*/
std::size_t UiEditOffsetAt(HFONT font, const std::wstring& text, float localX);
/**
* @brief 在超出可用宽度时对文本做尾部省略截断。
* @param [IN,OUT] g 绘图上下文。
@@ -164,6 +202,29 @@ namespace jdi
*/
std::wstring UiEllipsize(gd::Graphics& g, const std::wstring& text, HFONT font, float maxWidth);
/**
* @brief 处理输入框内的鼠标按下:命中则把插入符定位到最近的字符边界并开始拖拽框选。
* @param [IN] font 字体句柄。
* @param [IN] rect 输入框矩形。
* @param [IN,OUT] edit 编辑模型。
* @param [IN] scale 缩放比例。
* @param [IN] x 客户区横坐标。
* @param [IN] y 客户区纵坐标。
* @return 命中输入框并开始拖拽返回 true。
*/
bool UiEditFieldMouseDown(HFONT font, const gd::RectF& rect, TextEdit& edit, float scale, int x, int y);
/**
* @brief 处理输入框内的鼠标拖拽移动(扩展选区)。
* @param [IN] font 字体句柄。
* @param [IN] rect 输入框矩形。
* @param [IN,OUT] edit 编辑模型。
* @param [IN] scale 缩放比例。
* @param [IN] x 客户区横坐标。
* @return 选区发生变化返回 true。
*/
bool UiEditFieldMouseMove(HFONT font, const gd::RectF& rect, TextEdit& edit, float scale, int x);
/**
* @brief 在矩形中心绘制一个加号图标。
* @param [IN,OUT] g 绘图上下文。
+1
View File
@@ -61,6 +61,7 @@ namespace jdi
MenuScope scope = MenuScope::NONE; /**< 来源组件。 */
int id = 0; /**< 被选中项的命令标识。 */
int swatchIndex = -1; /**< 被选中的色块下标(非色块行为 -1)。 */
gd::RectF itemRect; /**< 被点击条目的矩形(客户区坐标),供就近弹出输入框。 */
};
/**
+32
View File
@@ -144,6 +144,37 @@ namespace jdi
*/
bool DeselectToEnd();
/**
* @brief 把插入符定位到指定偏移(单击输入框内时使用),并清除选区。
* @param [IN] offset 目标偏移(内部会夹到合法范围)。
* @return 光标或选区发生变化返回 true。
*/
bool PlaceCaret(std::size_t offset);
/**
* @brief 开始鼠标拖拽框选:把锚点与插入符都放在给定偏移。
* @param [IN] offset 起始偏移。
*/
void BeginDrag(std::size_t offset);
/**
* @brief 拖拽过程中更新插入符(锚点保持不变 → 形成选区)。
* @param [IN] offset 当前偏移。
* @return 光标或选区发生变化返回 true。
*/
bool UpdateDrag(std::size_t offset);
/**
* @brief 结束鼠标拖拽。
*/
void EndDrag() { m_dragging = false; }
/**
* @brief 判断是否正在鼠标拖拽框选。
* @return 正在拖拽返回 true。
*/
bool Dragging() const { return m_dragging; }
/**
* @brief 复制当前内容到剪贴板(存在选区时只复制选区)。
* @param [IN] owner 剪贴板所有者窗口句柄,允许为空。
@@ -204,6 +235,7 @@ namespace jdi
bool m_active = false; /**< 是否处于编辑状态。 */
bool m_fresh = false; /**< 是否处于“首次输入整体替换”状态。 */
bool m_dragging = false; /**< 是否正在鼠标拖拽框选。 */
std::wstring m_text; /**< 当前文本。 */
std::size_t m_caret = 0; /**< 光标位置。 */
std::size_t m_anchor = 0; /**< 选区锚点。 */