perf: defer Path.IsVisible hit-test to hover timer callback

Move the expensive per-part hit-test out of OnMouseMove and into
the hoverTimer callback. The hit-test now only runs once after
1000ms of stillness, not on every mouse move event.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 16:19:48 -04:00
parent 30f1008fa9
commit 98c574c2ad
+25 -25
View File
@@ -102,7 +102,7 @@ namespace OpenNest.Controls
redrawTimer.Elapsed += redrawTimer_Elapsed; redrawTimer.Elapsed += redrawTimer_Elapsed;
hoverTimer = new Timer() { AutoReset = false, Interval = 1000 }; hoverTimer = new Timer() { AutoReset = false, Interval = 1000 };
hoverTimer.Elapsed += (s, _) => { showTooltip = true; Invalidate(); }; hoverTimer.Elapsed += hoverTimer_Elapsed;
SetStyle( SetStyle(
ControlStyles.AllPaintingInWmPaint | ControlStyles.AllPaintingInWmPaint |
@@ -355,37 +355,16 @@ namespace OpenNest.Controls
} }
if (e.Button == MouseButtons.None && actionManager.CurrentAction is ActionSelect) if (e.Button == MouseButtons.None && actionManager.CurrentAction is ActionSelect)
{
var graphPt = PointControlToGraph(e.Location);
LayoutPart hitPart = null;
for (var i = parts.Count - 1; i >= 0; --i)
{
if (parts[i].Path.GetBounds().Contains(graphPt) &&
parts[i].Path.IsVisible(graphPt))
{
hitPart = parts[i];
break;
}
}
if (hitPart != hoveredPart)
hoveredPart = hitPart;
if (hoveredPart != null)
{ {
hoverPoint = e.Location; hoverPoint = e.Location;
showTooltip = false; showTooltip = false;
hoverTimer.Stop(); hoverTimer.Stop();
hoverTimer.Start(); hoverTimer.Start();
if (hoveredPart != null)
Invalidate(); Invalidate();
} }
else else if (hoveredPart != null || showTooltip)
{
hoverTimer.Stop();
showTooltip = false;
}
}
else if (hoveredPart != null)
{ {
hoveredPart = null; hoveredPart = null;
hoverTimer.Stop(); hoverTimer.Stop();
@@ -644,6 +623,27 @@ namespace OpenNest.Controls
Invalidate(); Invalidate();
} }
private void hoverTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var graphPt = PointControlToGraph(hoverPoint);
LayoutPart hitPart = null;
for (var i = parts.Count - 1; i >= 0; --i)
{
if (parts[i].Path.GetBounds().Contains(graphPt) &&
parts[i].Path.IsVisible(graphPt))
{
hitPart = parts[i];
break;
}
}
hoveredPart = hitPart;
showTooltip = hitPart != null;
if (showTooltip)
Invalidate();
}
private void plate_PartAdded(object sender, ItemAddedEventArgs<Part> e) private void plate_PartAdded(object sender, ItemAddedEventArgs<Part> e)
{ {
if (PartAdded != null) if (PartAdded != null)