fix: 修正滑块填充残留、数值内联输入与信号/分组重命名,拖拽虚影跟随鼠标
- 滑块最小值时不再有超出圆钮的填充残留,三处滑块统一为共享实现 - 透明度/RGB/色号支持点击或双击直接输入,整段高亮、首次键入替换、回车提交、Ctrl+C 复制 - 双击信号行或分组名进入重命名编辑;分组竖线改为绘制而非字符 - 拖拽信号时曲线虚影跟随鼠标纵向位移 - 数据层新增展示名覆盖,面板改为持有可写数据集合
This commit is contained in:
1 parent
542aa51e40
commit
261b8ac07d
13 files changed
+1074
-274
No files matched your search
@@ -1185,6 +1185,7 @@ namespace jdi
|
||||
{
|
||||
const int target = LaneAtY(y);
|
||||
m_dragMoved = true;
|
||||
m_dragMouseY = y;
|
||||
if (target != m_dragTargetLane)
|
||||
{
|
||||
m_dragTargetLane = target;
|
||||
@@ -1883,7 +1884,7 @@ namespace jdi
|
||||
std::wstring label = BuildLegendText(*resolved.data);
|
||||
if (multiFile && resolved.file != nullptr)
|
||||
{
|
||||
label += L" · " + resolved.file->fileName;
|
||||
label += L" · " + resolved.file->Title();
|
||||
}
|
||||
const float itemWidth = 13.0f * m_scale + UiTextWidth(g, label, m_fonts->uiSmall) +
|
||||
14.0f * m_scale;
|
||||
@@ -1915,7 +1916,7 @@ namespace jdi
|
||||
std::wstring label = BuildLegendText(*resolved.data);
|
||||
if (multiFile && resolved.file != nullptr)
|
||||
{
|
||||
label += L" · " + resolved.file->fileName;
|
||||
label += L" · " + resolved.file->Title();
|
||||
}
|
||||
const float textWidth = UiTextWidth(g, label, m_fonts->uiSmall);
|
||||
const float itemWidth = 13.0f * m_scale + textWidth + 14.0f * m_scale;
|
||||
@@ -1992,10 +1993,10 @@ namespace jdi
|
||||
}
|
||||
|
||||
ReadoutLine line;
|
||||
line.text = resolved.data->name;
|
||||
line.text = resolved.data->Title();
|
||||
if (multiFile)
|
||||
{
|
||||
line.text += L" · " + resolved.file->fileName;
|
||||
line.text += L" · " + resolved.file->Title();
|
||||
}
|
||||
line.text += L" = " + FormatValue(value);
|
||||
lines.push_back(std::move(line));
|
||||
@@ -2226,55 +2227,75 @@ namespace jdi
|
||||
return;
|
||||
}
|
||||
|
||||
// 拖拽中:在目标网格内以虚线绘制该信号的“虚影”,并高亮目标网格。
|
||||
// 拖拽中:虚影跟随鼠标纵向位移,同时在目标网格内高亮落点。
|
||||
if (m_dragMode == PlotDragMode::MOVE_SIGNAL && m_dragSignal.IsValid())
|
||||
{
|
||||
const int target = (m_dragTargetLane >= 0) ? m_dragTargetLane : m_tab->LaneOfSignal(m_dragSignal);
|
||||
const ResolvedSignal resolved = ResolveSignal(m_dragSignal);
|
||||
const int sourceLane = m_tab->LaneOfSignal(m_dragSignal);
|
||||
if (resolved.data == nullptr || resolved.style == nullptr || sourceLane < 0 ||
|
||||
sourceLane >= static_cast<int>(m_lanes.size()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 虚影:以源网格的幅值映射构建波形,并整体平移跟随鼠标,形成“拖着曲线走”的观感。
|
||||
LaneVisual ghostLane = m_lanes[static_cast<std::size_t>(sourceLane)];
|
||||
const float follow = static_cast<float>(m_dragMouseY - m_dragStartY);
|
||||
ghostLane.rect.Y += follow;
|
||||
|
||||
{
|
||||
const float clipTop = std::max(m_plotRect.Y, m_plotRect.Y);
|
||||
const float clipHeight = m_plotRect.Height;
|
||||
const int saveState = g.Save();
|
||||
g.SetClip(gd::RectF(m_plotRect.X, clipTop, m_plotRect.Width, clipHeight),
|
||||
gd::CombineModeIntersect);
|
||||
|
||||
std::vector<gd::PointF> points;
|
||||
std::vector<std::size_t> breaks;
|
||||
BuildPolyline(resolved, ghostLane, points, breaks);
|
||||
|
||||
gd::Pen ghost(ToGdiColor(WithAlpha(m_theme->accent, 0xC0)),
|
||||
std::max(1.8f, resolved.style->lineWidth) * m_scale);
|
||||
ghost.SetDashStyle(gd::DashStyleDash);
|
||||
ghost.SetStartCap(gd::LineCapRound);
|
||||
ghost.SetEndCap(gd::LineCapRound);
|
||||
for (std::size_t k = 0; k < breaks.size(); ++k)
|
||||
{
|
||||
const std::size_t start = breaks[k];
|
||||
const std::size_t stop = (k + 1 < breaks.size()) ? breaks[k + 1] : points.size();
|
||||
if (stop <= start + 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
g.DrawLines(&ghost, points.data() + start, static_cast<INT>(stop - start));
|
||||
}
|
||||
|
||||
g.Restore(saveState);
|
||||
}
|
||||
|
||||
// 落点提示:高亮鼠标所在网格并给出文字说明。
|
||||
const int target = (m_dragTargetLane >= 0) ? m_dragTargetLane : sourceLane;
|
||||
if (target >= 0 && target < static_cast<int>(m_lanes.size()))
|
||||
{
|
||||
const LaneVisual& lane = m_lanes[static_cast<std::size_t>(target)];
|
||||
const ResolvedSignal resolved = ResolveSignal(m_dragSignal);
|
||||
if (resolved.data != nullptr && resolved.style != nullptr)
|
||||
const gd::RectF& targetRect = m_lanes[static_cast<std::size_t>(target)].rect;
|
||||
const float visibleTop = std::max(targetRect.Y, m_plotRect.Y);
|
||||
const float visibleBottom = std::min(targetRect.Y + targetRect.Height,
|
||||
m_plotRect.Y + m_plotRect.Height);
|
||||
if (visibleBottom > visibleTop)
|
||||
{
|
||||
const int saveState = g.Save();
|
||||
g.SetClip(gd::RectF(m_plotRect.X, std::max(lane.rect.Y, m_plotRect.Y), m_plotRect.Width,
|
||||
std::min(lane.rect.Y + lane.rect.Height,
|
||||
m_plotRect.Y + m_plotRect.Height) -
|
||||
std::max(lane.rect.Y, m_plotRect.Y)),
|
||||
gd::CombineModeIntersect);
|
||||
|
||||
// 目标网格边框高亮。
|
||||
gd::Pen frame(ToGdiColor(m_theme->accent), 2.0f);
|
||||
g.DrawRectangle(&frame, lane.rect.X, lane.rect.Y, lane.rect.Width, lane.rect.Height);
|
||||
g.DrawRectangle(&frame, targetRect.X, visibleTop, targetRect.Width,
|
||||
visibleBottom - visibleTop);
|
||||
|
||||
std::vector<gd::PointF> points;
|
||||
std::vector<std::size_t> breaks;
|
||||
BuildPolyline(resolved, lane, points, breaks);
|
||||
|
||||
gd::Pen ghost(ToGdiColor(WithAlpha(m_theme->accent, 0xB0)),
|
||||
std::max(1.6f, resolved.style->lineWidth) * m_scale);
|
||||
ghost.SetDashStyle(gd::DashStyleDash);
|
||||
for (std::size_t k = 0; k < breaks.size(); ++k)
|
||||
{
|
||||
const std::size_t start = breaks[k];
|
||||
const std::size_t stop = (k + 1 < breaks.size()) ? breaks[k + 1] : points.size();
|
||||
if (stop <= start + 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
g.DrawLines(&ghost, points.data() + start, static_cast<INT>(stop - start));
|
||||
}
|
||||
|
||||
g.Restore(saveState);
|
||||
|
||||
// 目标网格名称提示。
|
||||
const std::wstring hint =
|
||||
L"移动到网格 " + std::to_wstring(target + 1) + L":松开左键确认";
|
||||
const std::wstring hint = (target == sourceLane)
|
||||
? std::wstring(L"松开左键放回本网格")
|
||||
: (L"移动到网格 " + std::to_wstring(target + 1) +
|
||||
L":松开左键确认");
|
||||
const float textWidth = UiTextWidth(g, hint, m_fonts->uiSmall) + 16.0f * m_scale;
|
||||
const float height = 20.0f * m_scale;
|
||||
float left = lane.rect.X + (lane.rect.Width - textWidth) * 0.5f;
|
||||
float left = targetRect.X + (targetRect.Width - textWidth) * 0.5f;
|
||||
left = std::max(m_plotRect.X, std::min(left, m_plotRect.X + m_plotRect.Width - textWidth));
|
||||
const gd::RectF pill(left, lane.rect.Y + 4.0f * m_scale, textWidth, height);
|
||||
const gd::RectF pill(left, visibleTop + 4.0f * m_scale, textWidth, height);
|
||||
UiFillRoundRect(g, pill, 3.0f * m_scale, m_theme->accent);
|
||||
UiText(g, hint, m_fonts->uiSmall, pill, m_theme->textOnAccent, TextAlign::CENTER);
|
||||
}
|
||||
@@ -2299,7 +2320,7 @@ namespace jdi
|
||||
}
|
||||
|
||||
const LaneVisual& lane = m_lanes[static_cast<std::size_t>(laneIndex)];
|
||||
const std::wstring text = resolved.data->name + L" · 按住拖拽可移入其它网格";
|
||||
const std::wstring text = resolved.data->Title() + L" · 按住拖拽可移入其它网格";
|
||||
|
||||
const float textWidth = UiTextWidth(g, text, m_fonts->uiSmall) + 16.0f * m_scale;
|
||||
const float height = 20.0f * m_scale;
|
||||
|
||||
Reference in new issue
Block a user