mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-10 07:34:14 -04:00
Keep cut outlines dark and etch strokes bright green. Assign drawing fills by a golden-angle hue walk with varied saturation/lightness tiers, preserving legacy schemes and rendering-only behavior. Include palette, visibility, persistence, and contrast regressions.
215 lines
6.5 KiB
C#
215 lines
6.5 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using Size = System.Drawing.Size;
|
|
|
|
namespace OpenNest.Controls
|
|
{
|
|
public class DrawingListBox : ListBox
|
|
{
|
|
private const int WM_ERASEBKGND = 0x0014;
|
|
|
|
private readonly Size imageSize;
|
|
private readonly Font nameFont;
|
|
private Point lastClickLocation;
|
|
|
|
public DrawingListBox()
|
|
{
|
|
DrawMode = DrawMode.OwnerDrawFixed;
|
|
ItemHeight = 85;
|
|
|
|
imageSize = new Size(ItemHeight, ItemHeight - 10);
|
|
nameFont = new Font(Font.FontFamily, 10, FontStyle.Bold);
|
|
|
|
var menu = new ContextMenuStrip();
|
|
var deleteItem = new ToolStripMenuItem("Delete");
|
|
deleteItem.Click += (s, e) =>
|
|
{
|
|
if (SelectedItem is Drawing drawing)
|
|
DeleteRequested?.Invoke(this, drawing);
|
|
};
|
|
menu.Opening += (s, e) =>
|
|
{
|
|
if (SelectedItem == null)
|
|
e.Cancel = true;
|
|
};
|
|
menu.Items.Add(deleteItem);
|
|
ContextMenuStrip = menu;
|
|
}
|
|
|
|
public event EventHandler<Drawing> DeleteRequested;
|
|
|
|
public Units Units { get; set; }
|
|
|
|
public bool HideDepletedParts { get; set; }
|
|
|
|
public bool HideQuantity { get; set; }
|
|
|
|
protected override void OnDrawItem(DrawItemEventArgs e)
|
|
{
|
|
if (e.Index >= Items.Count || e.Index <= -1)
|
|
return;
|
|
|
|
var dwg = Items[e.Index] as Drawing;
|
|
|
|
if (dwg == null)
|
|
return;
|
|
|
|
var isSelected = (e.State & DrawItemState.Selected) != 0;
|
|
Brush bgBrush;
|
|
|
|
if (!HideQuantity && dwg.Quantity.Nested > 0 && dwg.Quantity.Remaining == 0)
|
|
bgBrush = SystemBrushes.Info;
|
|
else
|
|
bgBrush = Brushes.White;
|
|
|
|
e.Graphics.FillRectangle(bgBrush, e.Bounds);
|
|
|
|
if (isSelected)
|
|
{
|
|
var borderRect = new Rectangle(
|
|
e.Bounds.X,
|
|
e.Bounds.Y,
|
|
e.Bounds.Width - 1,
|
|
e.Bounds.Height - 1
|
|
);
|
|
using var borderPen = new Pen(SystemColors.Highlight, 2);
|
|
e.Graphics.DrawRectangle(borderPen, borderRect);
|
|
}
|
|
|
|
if (!HideQuantity && dwg.Quantity.Required > 0)
|
|
{
|
|
var barWidth = 4;
|
|
var barColor =
|
|
dwg.Quantity.Nested >= dwg.Quantity.Required
|
|
? Color.FromArgb(76, 175, 80)
|
|
: Color.FromArgb(255, 152, 0);
|
|
using var barBrush = new SolidBrush(barColor);
|
|
e.Graphics.FillRectangle(
|
|
barBrush,
|
|
e.Bounds.X,
|
|
e.Bounds.Y,
|
|
barWidth,
|
|
e.Bounds.Height
|
|
);
|
|
}
|
|
|
|
var pt = new PointF(5, e.Bounds.Y + 5);
|
|
|
|
var brush = new SolidBrush(dwg.Color);
|
|
var pen = new Pen(ColorScheme.Default.GetPartOutlineColor(dwg.Color));
|
|
|
|
using var img = dwg.Program.GetImage(imageSize, pen, brush);
|
|
|
|
pen.Dispose();
|
|
brush.Dispose();
|
|
|
|
e.Graphics.DrawImage(img, pt);
|
|
|
|
pt.X += imageSize.Width + 10;
|
|
|
|
var textBrush = Brushes.Black;
|
|
var detailBrush = Brushes.Gray;
|
|
|
|
e.Graphics.DrawString(dwg.Name, nameFont, textBrush, pt);
|
|
|
|
var bounds = dwg.Program.BoundingBox();
|
|
var text2 = bounds.Size.ToString(4);
|
|
var text3 = string.Format(
|
|
"{0} sq/{1}",
|
|
System.Math.Round(dwg.Area, 4),
|
|
UnitsHelper.GetShortString(Units)
|
|
);
|
|
|
|
if (HideQuantity)
|
|
{
|
|
pt.Y += 22;
|
|
e.Graphics.DrawString(text2, Font, detailBrush, pt);
|
|
pt.Y += 18;
|
|
e.Graphics.DrawString(text3, Font, detailBrush, pt);
|
|
}
|
|
else
|
|
{
|
|
var text1 = string.Format(
|
|
"{0} of {1} nested",
|
|
dwg.Quantity.Nested,
|
|
dwg.Quantity.Required
|
|
);
|
|
pt.Y += 22;
|
|
e.Graphics.DrawString(text1, Font, detailBrush, pt);
|
|
pt.Y += 18;
|
|
e.Graphics.DrawString(text2, Font, detailBrush, pt);
|
|
pt.Y += 18;
|
|
e.Graphics.DrawString(text3, Font, detailBrush, pt);
|
|
}
|
|
|
|
using var separatorPen = new Pen(Color.LightGray);
|
|
var separatorY = e.Bounds.Bottom - 1;
|
|
e.Graphics.DrawLine(separatorPen, e.Bounds.X, separatorY, e.Bounds.Right, separatorY);
|
|
}
|
|
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
base.OnMouseMove(e);
|
|
|
|
var item = SelectedItem as Drawing;
|
|
|
|
if (item == null)
|
|
return;
|
|
|
|
if (e.Button == MouseButtons.Left && e.Location.DistanceTo(lastClickLocation) > 3)
|
|
DoDragDrop(item, DragDropEffects.Copy);
|
|
}
|
|
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
|
{
|
|
base.OnMouseDown(e);
|
|
lastClickLocation = e.Location;
|
|
}
|
|
|
|
protected override void WndProc(ref Message m)
|
|
{
|
|
if (m.Msg == WM_ERASEBKGND)
|
|
{
|
|
var itemBottom = 0;
|
|
|
|
if (Items.Count > 0)
|
|
{
|
|
var lastVisible = System.Math.Min(
|
|
TopIndex + (ClientSize.Height / ItemHeight),
|
|
Items.Count - 1
|
|
);
|
|
itemBottom = GetItemRectangle(lastVisible).Bottom;
|
|
}
|
|
|
|
if (itemBottom < ClientSize.Height)
|
|
{
|
|
using var g = Graphics.FromHdc(m.WParam);
|
|
g.FillRectangle(
|
|
Brushes.White,
|
|
0,
|
|
itemBottom,
|
|
ClientSize.Width,
|
|
ClientSize.Height - itemBottom
|
|
);
|
|
}
|
|
|
|
m.Result = (IntPtr)1;
|
|
return;
|
|
}
|
|
base.WndProc(ref m);
|
|
}
|
|
}
|
|
|
|
public static class PointExtensions
|
|
{
|
|
public static double DistanceTo(this Point pt1, Point pt2)
|
|
{
|
|
var x = pt2.X - pt1.X;
|
|
var y = pt2.Y - pt1.Y;
|
|
|
|
return System.Math.Sqrt(x * x + y * y);
|
|
}
|
|
}
|
|
}
|