feat(ui): ghost rendering for title block entities and text in EntityView

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-30 12:08:38 -04:00
parent cc38934d10
commit 9d1a39aa8f
2 changed files with 47 additions and 1 deletions
+46 -1
View File
@@ -30,13 +30,16 @@ namespace OpenNest.Controls
public List<Entity> OriginalEntities { get; set; }
public bool ShowEntityLabels { get; set; }
public List<CadText> Texts { get; set; } = new List<CadText>();
public HashSet<Guid> TitleBlockEntityIds { get; set; }
private readonly Pen gridPen = new Pen(Color.FromArgb(70, 70, 70));
private readonly Dictionary<int, Pen> penCache = new Dictionary<int, Pen>();
private readonly Dictionary<int, Pen> ghostPenCache = new Dictionary<int, Pen>();
private readonly Font labelFont = new Font("Segoe UI", 7f);
private readonly SolidBrush labelBrush = new SolidBrush(Color.FromArgb(220, 255, 255, 200));
private readonly SolidBrush labelBackBrush = new SolidBrush(Color.FromArgb(33, 40, 48));
private readonly SolidBrush textBrush = new SolidBrush(Color.FromArgb(180, 200, 200, 200));
private readonly SolidBrush ghostTextBrush = new SolidBrush(Color.FromArgb(50, 200, 200, 200));
public event EventHandler<Line> LinePicked;
public event EventHandler PickCancelled;
@@ -102,6 +105,13 @@ namespace OpenNest.Controls
foreach (var entity in Entities)
{
if (IsEtchLayer(entity.Layer)) continue;
if (TitleBlockEntityIds != null && TitleBlockEntityIds.Contains(entity.Id))
{
DrawGhostEntity(e.Graphics, entity);
continue;
}
var isHighlighted = simplifierHighlightSet != null && simplifierHighlightSet.Contains(entity);
var pen = isHighlighted
? GetEntityPen(Color.FromArgb(60, entity.Color))
@@ -243,11 +253,26 @@ namespace OpenNest.Controls
return pen;
}
private Pen GetGhostPen(Color color)
{
var ghostColor = Color.FromArgb(60, color.R, color.G, color.B);
var argb = ghostColor.ToArgb();
if (!ghostPenCache.TryGetValue(argb, out var pen))
{
pen = new Pen(ghostColor);
ghostPenCache[argb] = pen;
}
return pen;
}
public void ClearPenCache()
{
foreach (var pen in penCache.Values)
pen.Dispose();
penCache.Clear();
foreach (var pen in ghostPenCache.Values)
pen.Dispose();
ghostPenCache.Clear();
}
private static bool IsEtchLayer(Layer layer) =>
@@ -413,10 +438,28 @@ namespace OpenNest.Controls
labelBrush.Dispose();
labelBackBrush.Dispose();
textBrush.Dispose();
ghostTextBrush.Dispose();
}
base.Dispose(disposing);
}
private void DrawGhostEntity(Graphics g, Entity e)
{
var pen = GetGhostPen(e.Color);
switch (e.Type)
{
case EntityType.Arc:
DrawArc(g, (Arc)e, pen);
break;
case EntityType.Circle:
DrawCircle(g, (Circle)e, pen);
break;
case EntityType.Line:
DrawLine(g, (Line)e, pen);
break;
}
}
private void DrawEntity(Graphics g, Entity e, Pen pen)
{
if (!e.Layer.IsVisible || !e.IsVisible)
@@ -501,8 +544,10 @@ namespace OpenNest.Controls
sf.Alignment = text.HAlign;
sf.LineAlignment = text.VAlign;
var brush = TitleBlockEntityIds != null && TitleBlockEntityIds.Count > 0
? ghostTextBrush : textBrush;
using var font = new Font("Segoe UI", fontSize, GraphicsUnit.Pixel);
g.DrawString(text.Value, font, textBrush, 0, 0, sf);
g.DrawString(text.Value, font, brush, 0, 0, sf);
g.Restore(state);
}
}
+1
View File
@@ -162,6 +162,7 @@ namespace OpenNest.Forms
entityView1.Entities.AddRange(item.Entities);
entityView1.Bends = item.Bends ?? new List<Bend>();
entityView1.Texts = item.Texts ?? new List<CadText>();
entityView1.TitleBlockEntityIds = item.TitleBlockEntityIds;
item.Entities.ForEach(e => e.IsVisible = true);
if (item.Entities.Any(e => e.Layer != null))