mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-11 23:51:30 -05:00
AutoScroll runs a layout inside the constructor before dimensionsPanel exists, so every CAD Converter form threw NullReferenceException.
656 lines
25 KiB
C#
656 lines
25 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using OpenNest.Bending;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Controls
|
|
{
|
|
public class FilterPanel : Panel
|
|
{
|
|
private readonly CollapsiblePanel layersPanel;
|
|
private readonly CollapsiblePanel colorsPanel;
|
|
private readonly CollapsiblePanel lineTypesPanel;
|
|
private readonly CollapsiblePanel bendLinesPanel;
|
|
|
|
private readonly CheckedListBox layersList;
|
|
private readonly ListBox colorsList;
|
|
private readonly CheckedListBox lineTypesList;
|
|
private readonly ListBox bendLinesList;
|
|
private readonly LinkLabel bendAddLink;
|
|
private readonly CollapsiblePanel breakoffsPanel;
|
|
private readonly ListBox breakoffsList;
|
|
private readonly LinkLabel breakoffAddLink;
|
|
private bool loadingBreakoffs;
|
|
private readonly CollapsiblePanel cutoutsPanel;
|
|
private readonly ListBox cutoutsList;
|
|
private readonly LinkLabel cutoutAddLink;
|
|
private bool loadingCutouts;
|
|
private readonly CollapsiblePanel dimensionsPanel;
|
|
private readonly ListBox dimensionsList;
|
|
private bool loadingDimensions;
|
|
|
|
private List<Entity> currentEntities;
|
|
private List<Bend> currentBends;
|
|
|
|
public event EventHandler FilterChanged;
|
|
public event EventHandler<int> BendLineSelected;
|
|
public event EventHandler<int> BendLineRemoved;
|
|
public event EventHandler<int> BendLineEdited;
|
|
public event EventHandler AddBendLineClicked;
|
|
public event EventHandler<int> BreakoffSelected;
|
|
public event EventHandler<int> BreakoffEdited;
|
|
public event EventHandler<int> BreakoffRemoved;
|
|
public event EventHandler<int> BreakoffFlipped;
|
|
public event EventHandler AddBreakoffClicked;
|
|
public event EventHandler<int> TabbedCutoutSelected;
|
|
public event EventHandler<int> TabbedCutoutEdited;
|
|
public event EventHandler<int> TabbedCutoutRemoved;
|
|
public event EventHandler AddTabbedCutoutClicked;
|
|
public event EventHandler<int> DimensionSelected;
|
|
public event EventHandler<int> DimensionRemoved;
|
|
public event EventHandler AddDimensionsClicked;
|
|
|
|
public FilterPanel()
|
|
{
|
|
AutoScroll = true;
|
|
BackColor = Color.White;
|
|
|
|
// Breakoffs
|
|
breakoffsPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Breakoffs (0)",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = 110,
|
|
IsExpanded = false,
|
|
};
|
|
breakoffsList = new ListBox
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
BorderStyle = BorderStyle.None,
|
|
Font = new Font("Segoe UI", 9f),
|
|
};
|
|
breakoffsList.SelectedIndexChanged += (s, e) =>
|
|
{
|
|
if (!loadingBreakoffs)
|
|
BreakoffSelected?.Invoke(this, breakoffsList.SelectedIndex);
|
|
};
|
|
breakoffsList.DoubleClick += (s, e) =>
|
|
{
|
|
if (breakoffsList.SelectedIndex >= 0)
|
|
BreakoffEdited?.Invoke(this, breakoffsList.SelectedIndex);
|
|
};
|
|
|
|
breakoffAddLink = new LinkLabel { Text = "Add Breakoff", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
breakoffAddLink.LinkClicked += (s, e) => AddBreakoffClicked?.Invoke(this, EventArgs.Empty);
|
|
var breakoffEditLink = new LinkLabel { Text = "Edit", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
breakoffEditLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (breakoffsList.SelectedIndex >= 0)
|
|
BreakoffEdited?.Invoke(this, breakoffsList.SelectedIndex);
|
|
};
|
|
var breakoffFlipLink = new LinkLabel { Text = "Flip", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
breakoffFlipLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (breakoffsList.SelectedIndex >= 0)
|
|
BreakoffFlipped?.Invoke(this, breakoffsList.SelectedIndex);
|
|
};
|
|
var breakoffRemoveLink = new LinkLabel { Text = "Remove", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
breakoffRemoveLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (breakoffsList.SelectedIndex >= 0)
|
|
BreakoffRemoved?.Invoke(this, breakoffsList.SelectedIndex);
|
|
};
|
|
|
|
var breakoffLinksPanel = new FlowLayoutPanel
|
|
{
|
|
Dock = DockStyle.Top,
|
|
Height = 20,
|
|
FlowDirection = FlowDirection.LeftToRight,
|
|
WrapContents = false,
|
|
};
|
|
breakoffLinksPanel.Controls.Add(breakoffAddLink);
|
|
breakoffLinksPanel.Controls.Add(breakoffEditLink);
|
|
breakoffLinksPanel.Controls.Add(breakoffFlipLink);
|
|
breakoffLinksPanel.Controls.Add(breakoffRemoveLink);
|
|
|
|
breakoffsPanel.ContentPanel.Controls.Add(breakoffsList);
|
|
breakoffsPanel.ContentPanel.Controls.Add(breakoffLinksPanel);
|
|
|
|
// Tabbed cutouts
|
|
cutoutsPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Tabbed Cutouts (0)",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = 110,
|
|
IsExpanded = false,
|
|
};
|
|
cutoutsList = new ListBox
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
BorderStyle = BorderStyle.None,
|
|
Font = new Font("Segoe UI", 9f),
|
|
};
|
|
cutoutsList.SelectedIndexChanged += (s, e) =>
|
|
{
|
|
if (!loadingCutouts)
|
|
TabbedCutoutSelected?.Invoke(this, cutoutsList.SelectedIndex);
|
|
};
|
|
cutoutsList.DoubleClick += (s, e) =>
|
|
{
|
|
if (cutoutsList.SelectedIndex >= 0)
|
|
TabbedCutoutEdited?.Invoke(this, cutoutsList.SelectedIndex);
|
|
};
|
|
|
|
cutoutAddLink = new LinkLabel { Text = "Add Tabbed Cutout", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
cutoutAddLink.LinkClicked += (s, e) => AddTabbedCutoutClicked?.Invoke(this, EventArgs.Empty);
|
|
var cutoutEditLink = new LinkLabel { Text = "Edit", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
cutoutEditLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (cutoutsList.SelectedIndex >= 0)
|
|
TabbedCutoutEdited?.Invoke(this, cutoutsList.SelectedIndex);
|
|
};
|
|
var cutoutRemoveLink = new LinkLabel { Text = "Remove", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
cutoutRemoveLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (cutoutsList.SelectedIndex >= 0)
|
|
TabbedCutoutRemoved?.Invoke(this, cutoutsList.SelectedIndex);
|
|
};
|
|
|
|
var cutoutLinksPanel = new FlowLayoutPanel
|
|
{
|
|
Dock = DockStyle.Top,
|
|
Height = 20,
|
|
FlowDirection = FlowDirection.LeftToRight,
|
|
WrapContents = false,
|
|
};
|
|
cutoutLinksPanel.Controls.Add(cutoutAddLink);
|
|
cutoutLinksPanel.Controls.Add(cutoutEditLink);
|
|
cutoutLinksPanel.Controls.Add(cutoutRemoveLink);
|
|
|
|
cutoutsPanel.ContentPanel.Controls.Add(cutoutsList);
|
|
cutoutsPanel.ContentPanel.Controls.Add(cutoutLinksPanel);
|
|
|
|
// Dimensions
|
|
dimensionsPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Dimensions (0)",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = DimensionsMinimumHeight,
|
|
IsExpanded = false,
|
|
};
|
|
dimensionsList = new ListBox
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
BorderStyle = BorderStyle.None,
|
|
Font = new Font("Segoe UI", 9f),
|
|
};
|
|
dimensionsList.SelectedIndexChanged += (s, e) =>
|
|
{
|
|
if (!loadingDimensions)
|
|
DimensionSelected?.Invoke(this, dimensionsList.SelectedIndex);
|
|
};
|
|
|
|
var dimensionAddLink = new LinkLabel { Text = "Add Overall Dimensions", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
dimensionAddLink.LinkClicked += (s, e) => AddDimensionsClicked?.Invoke(this, EventArgs.Empty);
|
|
var dimensionRemoveLink = new LinkLabel { Text = "Remove", AutoSize = true, Font = new Font("Segoe UI", 8f) };
|
|
dimensionRemoveLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (dimensionsList.SelectedIndex >= 0)
|
|
DimensionRemoved?.Invoke(this, dimensionsList.SelectedIndex);
|
|
};
|
|
|
|
var dimensionLinksPanel = new FlowLayoutPanel
|
|
{
|
|
Dock = DockStyle.Top,
|
|
Height = 20,
|
|
FlowDirection = FlowDirection.LeftToRight,
|
|
WrapContents = false,
|
|
};
|
|
dimensionLinksPanel.Controls.Add(dimensionAddLink);
|
|
dimensionLinksPanel.Controls.Add(dimensionRemoveLink);
|
|
|
|
dimensionsPanel.ContentPanel.Controls.Add(dimensionsList);
|
|
dimensionsPanel.ContentPanel.Controls.Add(dimensionLinksPanel);
|
|
|
|
// Bend Lines
|
|
bendLinesPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Bend Lines (0)",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = 120,
|
|
IsExpanded = false,
|
|
};
|
|
bendLinesList = new ListBox
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
BorderStyle = BorderStyle.None,
|
|
Font = new Font("Segoe UI", 9f),
|
|
};
|
|
bendLinesList.SelectedIndexChanged += (s, e) =>
|
|
BendLineSelected?.Invoke(this, bendLinesList.SelectedIndex);
|
|
|
|
var bendEditLink = new LinkLabel
|
|
{
|
|
Text = "Edit",
|
|
AutoSize = true,
|
|
Font = new Font("Segoe UI", 8f),
|
|
};
|
|
bendEditLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (bendLinesList.SelectedIndex >= 0)
|
|
BendLineEdited?.Invoke(this, bendLinesList.SelectedIndex);
|
|
};
|
|
|
|
var bendDeleteLink = new LinkLabel
|
|
{
|
|
Text = "Remove",
|
|
AutoSize = true,
|
|
Font = new Font("Segoe UI", 8f),
|
|
};
|
|
bendDeleteLink.LinkClicked += (s, e) =>
|
|
{
|
|
if (bendLinesList.SelectedIndex >= 0)
|
|
BendLineRemoved?.Invoke(this, bendLinesList.SelectedIndex);
|
|
};
|
|
|
|
bendLinesList.DoubleClick += (s, e) =>
|
|
{
|
|
if (bendLinesList.SelectedIndex >= 0)
|
|
BendLineEdited?.Invoke(this, bendLinesList.SelectedIndex);
|
|
};
|
|
|
|
bendAddLink = new LinkLabel
|
|
{
|
|
Text = "Add Bend Line",
|
|
AutoSize = true,
|
|
Font = new Font("Segoe UI", 8f),
|
|
};
|
|
bendAddLink.LinkClicked += (s, e) => AddBendLineClicked?.Invoke(this, EventArgs.Empty);
|
|
|
|
var bendLinksPanel = new FlowLayoutPanel
|
|
{
|
|
Dock = DockStyle.Top,
|
|
Height = 20,
|
|
FlowDirection = FlowDirection.LeftToRight,
|
|
WrapContents = false,
|
|
};
|
|
bendLinksPanel.Controls.Add(bendAddLink);
|
|
bendLinksPanel.Controls.Add(bendEditLink);
|
|
bendLinksPanel.Controls.Add(bendDeleteLink);
|
|
|
|
bendLinesPanel.ContentPanel.Controls.Add(bendLinesList);
|
|
bendLinesPanel.ContentPanel.Controls.Add(bendLinksPanel);
|
|
|
|
// Line Types
|
|
lineTypesPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Line Types (0)",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = 100,
|
|
IsExpanded = true,
|
|
};
|
|
lineTypesList = CreateCheckedList();
|
|
lineTypesPanel.ContentPanel.Controls.Add(lineTypesList);
|
|
|
|
// Colors
|
|
colorsPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Colors (0)",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = 100,
|
|
IsExpanded = true,
|
|
};
|
|
colorsList = new ListBox
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
BorderStyle = BorderStyle.None,
|
|
Font = new Font("Segoe UI", 9f),
|
|
DrawMode = DrawMode.OwnerDrawFixed,
|
|
ItemHeight = 20,
|
|
SelectionMode = SelectionMode.None,
|
|
};
|
|
colorsList.DrawItem += ColorsList_DrawItem;
|
|
colorsList.MouseClick += ColorsList_MouseClick;
|
|
colorsPanel.ContentPanel.Controls.Add(colorsList);
|
|
|
|
// Layers (always expanded)
|
|
layersPanel = new CollapsiblePanel
|
|
{
|
|
HeaderText = "Layers",
|
|
Dock = DockStyle.Top,
|
|
ExpandedHeight = 160,
|
|
IsExpanded = true,
|
|
};
|
|
|
|
var checkAllPanel = new Panel { Dock = DockStyle.Top, Height = 22 };
|
|
var checkAll = new LinkLabel
|
|
{
|
|
Text = "All",
|
|
AutoSize = true,
|
|
Location = new Point(4, 2),
|
|
Font = new Font("Segoe UI", 8f),
|
|
};
|
|
var uncheckAll = new LinkLabel
|
|
{
|
|
Text = "None",
|
|
AutoSize = true,
|
|
Location = new Point(30, 2),
|
|
Font = new Font("Segoe UI", 8f),
|
|
};
|
|
checkAll.LinkClicked += (s, e) => SetAllChecked(layersList, true);
|
|
uncheckAll.LinkClicked += (s, e) => SetAllChecked(layersList, false);
|
|
checkAllPanel.Controls.AddRange(new Control[] { checkAll, uncheckAll });
|
|
|
|
layersList = CreateCheckedList();
|
|
layersPanel.ContentPanel.Controls.Add(layersList);
|
|
layersPanel.ContentPanel.Controls.Add(checkAllPanel);
|
|
|
|
// Add panels in reverse order (Dock.Top stacks top-down)
|
|
Controls.Add(dimensionsPanel);
|
|
Controls.Add(cutoutsPanel);
|
|
Controls.Add(breakoffsPanel);
|
|
Controls.Add(bendLinesPanel);
|
|
Controls.Add(lineTypesPanel);
|
|
Controls.Add(colorsPanel);
|
|
Controls.Add(layersPanel);
|
|
}
|
|
|
|
/// <summary>The expanded Dimensions section never shrinks below this; when there is room it fills the panel to the bottom.</summary>
|
|
internal const int DimensionsMinimumHeight = 140;
|
|
|
|
protected override void OnLayout(LayoutEventArgs levent)
|
|
{
|
|
base.OnLayout(levent);
|
|
FillDimensionsToBottom();
|
|
}
|
|
|
|
// Dimensions is the bottom section: stretch it over the empty space below it so its list
|
|
// shows every dimension instead of scrolling inside a short box.
|
|
private void FillDimensionsToBottom()
|
|
{
|
|
// Layout already runs inside the constructor (AutoScroll), before the sections exist.
|
|
if (dimensionsPanel is not { IsExpanded: true })
|
|
return;
|
|
|
|
var above = 0;
|
|
foreach (Control control in Controls)
|
|
{
|
|
if (control != dimensionsPanel && control.Visible)
|
|
above += control.Height;
|
|
}
|
|
|
|
var height = System.Math.Max(DimensionsMinimumHeight, ClientSize.Height - above);
|
|
if (dimensionsPanel.Height != height)
|
|
dimensionsPanel.Height = height;
|
|
}
|
|
|
|
private CheckedListBox CreateCheckedList()
|
|
{
|
|
var list = new CheckedListBox
|
|
{
|
|
Dock = DockStyle.Fill,
|
|
BorderStyle = BorderStyle.None,
|
|
CheckOnClick = true,
|
|
Font = new Font("Segoe UI", 9f),
|
|
};
|
|
list.ItemCheck += (s, e) =>
|
|
{
|
|
if (IsHandleCreated)
|
|
BeginInvoke((Action)(() => FilterChanged?.Invoke(this, EventArgs.Empty)));
|
|
};
|
|
return list;
|
|
}
|
|
|
|
public void LoadItem(List<Entity> entities, List<Bend> bends)
|
|
{
|
|
currentEntities = entities;
|
|
currentBends = bends;
|
|
|
|
// Layers
|
|
layersList.Items.Clear();
|
|
var layers = entities
|
|
.Where(e => e.Layer != null)
|
|
.Select(e => e.Layer)
|
|
.GroupBy(l => l.Name)
|
|
.Select(g => g.First());
|
|
foreach (var layer in layers)
|
|
layersList.Items.Add(layer.Name, layer.IsVisible);
|
|
|
|
layersPanel.HeaderText = $"Layers ({layersList.Items.Count})";
|
|
|
|
// Colors
|
|
colorsList.Items.Clear();
|
|
var colors = entities
|
|
.Select(e => e.Color.ToArgb())
|
|
.Distinct()
|
|
.Select(argb => new ColorItem(Color.FromArgb(argb)));
|
|
foreach (var color in colors)
|
|
colorsList.Items.Add(color);
|
|
|
|
colorsPanel.HeaderText = $"Colors ({colorsList.Items.Count})";
|
|
|
|
// Line Types
|
|
lineTypesList.Items.Clear();
|
|
var lineTypes = entities
|
|
.GroupBy(e => e.LineTypeName ?? "Continuous")
|
|
.Select(g => new { Name = g.Key, Visible = g.Any(e => e.IsVisible) });
|
|
foreach (var lt in lineTypes)
|
|
lineTypesList.Items.Add(lt.Name, lt.Visible);
|
|
|
|
lineTypesPanel.HeaderText = $"Line Types ({lineTypesList.Items.Count})";
|
|
|
|
// Bend Lines
|
|
bendLinesList.Items.Clear();
|
|
if (bends != null)
|
|
{
|
|
foreach (var bend in bends)
|
|
bendLinesList.Items.Add(bend.ToString());
|
|
}
|
|
|
|
var bendCount = bends?.Count ?? 0;
|
|
bendLinesPanel.HeaderText = $"Bend Lines ({bendCount})";
|
|
bendLinesPanel.IsExpanded = bendCount > 0;
|
|
}
|
|
|
|
public void ApplyFilters(List<Entity> entities)
|
|
{
|
|
var hiddenLayers = new HashSet<string>();
|
|
for (var i = 0; i < layersList.Items.Count; i++)
|
|
{
|
|
if (!layersList.GetItemChecked(i))
|
|
hiddenLayers.Add(layersList.Items[i].ToString());
|
|
}
|
|
|
|
var hiddenColors = new HashSet<int>();
|
|
for (var i = 0; i < colorsList.Items.Count; i++)
|
|
{
|
|
var item = (ColorItem)colorsList.Items[i];
|
|
if (!item.IsChecked)
|
|
hiddenColors.Add(item.Argb);
|
|
}
|
|
|
|
var hiddenLineTypes = new HashSet<string>();
|
|
for (var i = 0; i < lineTypesList.Items.Count; i++)
|
|
{
|
|
if (!lineTypesList.GetItemChecked(i))
|
|
hiddenLineTypes.Add(lineTypesList.Items[i].ToString());
|
|
}
|
|
|
|
foreach (var entity in entities)
|
|
{
|
|
var layerVisible =
|
|
entity.Layer?.Name == null || !hiddenLayers.Contains(entity.Layer.Name);
|
|
var colorVisible = !hiddenColors.Contains(entity.Color.ToArgb());
|
|
var ltVisible = !hiddenLineTypes.Contains(entity.LineTypeName ?? "Continuous");
|
|
|
|
entity.IsVisible = layerVisible && colorVisible && ltVisible;
|
|
if (entity.Layer != null)
|
|
entity.Layer.IsVisible = !hiddenLayers.Contains(entity.Layer.Name);
|
|
}
|
|
}
|
|
|
|
private void SetAllChecked(CheckedListBox list, bool isChecked)
|
|
{
|
|
for (var i = 0; i < list.Items.Count; i++)
|
|
list.SetItemChecked(i, isChecked);
|
|
}
|
|
|
|
private void ColorsList_MouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
var index = colorsList.IndexFromPoint(e.Location);
|
|
if (index < 0)
|
|
return;
|
|
var item = (ColorItem)colorsList.Items[index];
|
|
item.IsChecked = !item.IsChecked;
|
|
colorsList.Invalidate(colorsList.GetItemRectangle(index));
|
|
FilterChanged?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void ColorsList_DrawItem(object sender, DrawItemEventArgs e)
|
|
{
|
|
if (e.Index < 0)
|
|
return;
|
|
|
|
e.Graphics.FillRectangle(Brushes.White, e.Bounds);
|
|
|
|
var colorItem = (ColorItem)colorsList.Items[e.Index];
|
|
var checkSize = CheckBoxRenderer.GetGlyphSize(
|
|
e.Graphics,
|
|
System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
|
|
);
|
|
var checkY = e.Bounds.Top + (e.Bounds.Height - checkSize.Height) / 2;
|
|
var checkState = colorItem.IsChecked
|
|
? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
|
|
: System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
|
|
CheckBoxRenderer.DrawCheckBox(
|
|
e.Graphics,
|
|
new Point(e.Bounds.Left + 2, checkY),
|
|
checkState
|
|
);
|
|
|
|
var swatchX = e.Bounds.Left + checkSize.Width + 6;
|
|
var swatchRect = new Rectangle(swatchX, e.Bounds.Top + 2, 16, e.Bounds.Height - 4);
|
|
using (var brush = new SolidBrush(colorItem.Color))
|
|
e.Graphics.FillRectangle(brush, swatchRect);
|
|
e.Graphics.DrawRectangle(Pens.Gray, swatchRect);
|
|
|
|
TextRenderer.DrawText(
|
|
e.Graphics,
|
|
colorItem.ToString(),
|
|
e.Font,
|
|
new Point(swatchRect.Right + 4, e.Bounds.Top + 1),
|
|
SystemColors.WindowText
|
|
);
|
|
}
|
|
|
|
public void SetPickMode(bool active)
|
|
{
|
|
bendAddLink.Text = active ? "Cancel (Esc)" : "Add Bend Line";
|
|
bendAddLink.LinkColor = active ? Color.OrangeRed : Color.Empty;
|
|
}
|
|
|
|
public void SetBreakoffPickMode(bool active)
|
|
{
|
|
breakoffAddLink.Text = active ? "Cancel (Esc)" : "Add Breakoff";
|
|
breakoffAddLink.LinkColor = active ? Color.OrangeRed : Color.Empty;
|
|
}
|
|
|
|
/// <summary>Shows one line per breakoff with <paramref name="selected"/> selected, without raising selection events.</summary>
|
|
public void LoadBreakoffs(IReadOnlyList<string> labels, int selected)
|
|
{
|
|
var added = labels.Count > breakoffsList.Items.Count;
|
|
loadingBreakoffs = true;
|
|
try
|
|
{
|
|
breakoffsList.BeginUpdate();
|
|
breakoffsList.Items.Clear();
|
|
foreach (var label in labels)
|
|
breakoffsList.Items.Add(label);
|
|
breakoffsList.SelectedIndex = selected >= 0 && selected < labels.Count ? selected : -1;
|
|
breakoffsList.EndUpdate();
|
|
}
|
|
finally
|
|
{
|
|
loadingBreakoffs = false;
|
|
}
|
|
breakoffsPanel.HeaderText = $"Breakoffs ({labels.Count})";
|
|
if (added)
|
|
breakoffsPanel.IsExpanded = true;
|
|
}
|
|
|
|
public void SetTabbedCutoutPickMode(bool active)
|
|
{
|
|
cutoutAddLink.Text = active ? "Cancel (Esc)" : "Add Tabbed Cutout";
|
|
cutoutAddLink.LinkColor = active ? Color.OrangeRed : Color.Empty;
|
|
}
|
|
|
|
/// <summary>Shows one line per tabbed cutout with <paramref name="selected"/> selected, without raising selection events.</summary>
|
|
public void LoadTabbedCutouts(IReadOnlyList<string> labels, int selected)
|
|
{
|
|
var added = labels.Count > cutoutsList.Items.Count;
|
|
loadingCutouts = true;
|
|
try
|
|
{
|
|
cutoutsList.BeginUpdate();
|
|
cutoutsList.Items.Clear();
|
|
foreach (var label in labels)
|
|
cutoutsList.Items.Add(label);
|
|
cutoutsList.SelectedIndex = selected >= 0 && selected < labels.Count ? selected : -1;
|
|
cutoutsList.EndUpdate();
|
|
}
|
|
finally
|
|
{
|
|
loadingCutouts = false;
|
|
}
|
|
cutoutsPanel.HeaderText = $"Tabbed Cutouts ({labels.Count})";
|
|
if (added)
|
|
cutoutsPanel.IsExpanded = true;
|
|
}
|
|
|
|
/// <summary>Shows one line per dimension with <paramref name="selected"/> selected, without raising selection events.</summary>
|
|
public void LoadDimensions(IReadOnlyList<string> labels, int selected)
|
|
{
|
|
var added = labels.Count > dimensionsList.Items.Count;
|
|
loadingDimensions = true;
|
|
try
|
|
{
|
|
dimensionsList.BeginUpdate();
|
|
dimensionsList.Items.Clear();
|
|
foreach (var label in labels)
|
|
dimensionsList.Items.Add(label);
|
|
dimensionsList.SelectedIndex = selected >= 0 && selected < labels.Count ? selected : -1;
|
|
dimensionsList.EndUpdate();
|
|
}
|
|
finally
|
|
{
|
|
loadingDimensions = false;
|
|
}
|
|
dimensionsPanel.HeaderText = $"Dimensions ({labels.Count})";
|
|
if (added)
|
|
dimensionsPanel.IsExpanded = true;
|
|
}
|
|
}
|
|
|
|
public class ColorItem
|
|
{
|
|
public int Argb { get; }
|
|
public Color Color { get; }
|
|
public bool IsChecked { get; set; } = true;
|
|
|
|
public ColorItem(Color color)
|
|
{
|
|
Color = color;
|
|
Argb = color.ToArgb();
|
|
}
|
|
|
|
public override string ToString() => $"#{Color.R:X2}{Color.G:X2}{Color.B:X2}";
|
|
|
|
public override bool Equals(object obj) => obj is ColorItem other && Argb == other.Argb;
|
|
|
|
public override int GetHashCode() => Argb;
|
|
}
|
|
}
|