feat: 重构信号样式区并统一主题化弹出菜单

样式编辑区:
- 移除顶部「样式 + 信号名 + 文件名」标题行,选中信号即代表编辑目标。
- 绘制方式取消阶梯选项,仅保留线段/散点/点线,标签由「方式」改为「样式」。
- 线宽改为「最细预设 + 数值旋钮 + 最粗预设」:中间为带左右增减箭头的输入框,
  步进 0.2px,取值范围 0.5-6.0px,并标注单位为 px。
- 颜色在 10 个预设色块后新增带加号图标的方格,点击展开 RGB 三通道滑块面板,
  可实时预览并显示十六进制值;点击面板外任意位置收起。
- 移除网格归属下拉框,改由每条信号行末尾的 G 徽标承载,点击弹出网格归属菜单。

信号面板与菜单:
- 文件分组行新增关闭按钮,可直接从工作区移除该文件,与整体风格保持一致。
- 新增 PopupMenu 组件:绘制在窗口后备缓冲区内的自绘菜单,含圆角、投影、悬停高亮、
  单选对勾、色块行与分组标题,彻底替换系统默认弹出菜单;
  菜单打开期间接管鼠标与键盘(Esc / 上下键 / 回车),失焦或在菜单外释放时自动关闭。
- 信号、文件、网格、标签页四类右键菜单全部改用该组件。

其他修复:
- 信号名称不再保留尾部单位括号,避免名称后再重复显示单位。
- 数据模型移除 DrawMode::STEP 枚举。
- 标签栏与信号面板弹出菜单后补充重绘请求,修复菜单不显示的问题。
This commit is contained in:
DeepSeek V4.1 Flash committed 2026-09-29 16:30:48 +08:00
1 parent 9c6c374cce
commit eb868b2679
12 files changed
+2148 -531

No files matched your search

+1 -2
View File
@@ -338,11 +338,10 @@ namespace jdi
* @brief 构建单条信号在当前视图下的折线点序列。
* @param [IN] resolved 已解析的信号视图。
* @param [IN] lane 所属网格绘制信息。
* @param [IN] stepMode 是否使用阶梯保持连线。
* @param [OUT] points 输出点序列。
* @param [OUT] breaks 输出每段折线的起始下标(用于处理缺失值断线)。
*/
void BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane, bool stepMode,
void BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane,
std::vector<gd::PointF>& points, std::vector<std::size_t>& breaks) const;
/**
+3 -12
View File
@@ -864,7 +864,7 @@ namespace jdi
return changed;
}
void PlotView::BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane, bool stepMode,
void PlotView::BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane,
std::vector<gd::PointF>& points, std::vector<std::size_t>& breaks) const
{
points.clear();
@@ -921,7 +921,6 @@ namespace jdi
const float limitBottom = lane.rect.Y + lane.rect.Height * 5.0f;
bool inSegment = false;
double previousY = 0.0;
for (std::size_t index = begin; index < end; index += stride)
{
@@ -943,17 +942,10 @@ namespace jdi
points.push_back(gd::PointF(x, y));
inSegment = true;
}
else if (stepMode)
{
points.push_back(gd::PointF(x, static_cast<float>(previousY)));
points.push_back(gd::PointF(x, y));
}
else
{
points.push_back(gd::PointF(x, y));
}
previousY = y;
}
}
@@ -1097,8 +1089,7 @@ namespace jdi
}
const DrawMode mode = resolved.style->mode;
const bool stepMode = (mode == DrawMode::STEP);
BuildPolyline(resolved, lane, stepMode, points, breaks);
BuildPolyline(resolved, lane, points, breaks);
const bool drawLine = (mode != DrawMode::SCATTER);
const bool drawScatter = (mode == DrawMode::SCATTER || mode == DrawMode::LINE_SCATTER);
@@ -1106,7 +1097,7 @@ namespace jdi
if (drawLine && !breaks.empty())
{
gd::Pen pen(ToGdiColor(resolved.style->color), resolved.style->lineWidth * m_scale);
pen.SetLineJoin(stepMode ? gd::LineJoinMiter : gd::LineJoinRound);
pen.SetLineJoin(gd::LineJoinRound);
pen.SetStartCap(gd::LineCapRound);
pen.SetEndCap(gd::LineCapRound);