mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-26 22:01:06 -04:00
feat(sets): browse the library inside the set editor
Adding drawings to a set meant opening the library dialog, then the set editor, then a second copy of the library in pick mode, then backing out again. The set editor now has the library as its left pane (unfiltered, searchable, sortable, paged): select drawings and Add to Set, double-click or press Enter. Members already in the set are greyed. The library dialog's pick mode had no other caller and is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
382abf702b
commit
19809c61d0
5 files changed
+547
-148
No files matched your search
@@ -1,3 +1,4 @@
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using OpenNest.Data;
|
||||
@@ -31,14 +32,17 @@ public class DrawingSetFormsTests
|
||||
{
|
||||
using var editor = new EditDrawingSetForm(edit, library, Server);
|
||||
editor.ShowMessage = (text, _, _) => throw new Xunit.Sdk.XunitException(text);
|
||||
editor.PickDrawings = () => (new[] { bracket, gusset }, 3);
|
||||
editor.Show();
|
||||
var save = Field<Button>(editor, "saveButton");
|
||||
var libraryGrid = Field<DataGridView>(editor, "libraryGrid");
|
||||
PumpUntil(() => libraryGrid.Rows.Count == 2, "the editor's library pane");
|
||||
Assert.False(save.Enabled);
|
||||
|
||||
Field<TextBox>(editor, "nameBox").Text = "Synthetic kit";
|
||||
Field<TextBox>(editor, "customerBox").Text = "Synthetic customer";
|
||||
editor.AddDrawings();
|
||||
libraryGrid.SelectAll();
|
||||
Field<NumericUpDown>(editor, "quantityBox").Value = 3;
|
||||
editor.AddSelectedDrawings();
|
||||
Assert.True(save.Enabled);
|
||||
Run(editor.SaveAsync());
|
||||
return editor.Saved;
|
||||
@@ -67,36 +71,58 @@ public class DrawingSetFormsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickMode_HasNoSetsTab_AndReturnsEverySelectedDrawingInListOrder()
|
||||
public void EditorLibraryPane_ListsEveryDrawing_AddsTheSelectionInListOrder_AndGreysMembers()
|
||||
{
|
||||
StaTestThread.Run(
|
||||
() =>
|
||||
{
|
||||
var library = new FakeLibrary();
|
||||
var a = library.Add("SYN-A", "Synthetic Steel", 0.25);
|
||||
library.Add("SYN-B", "Synthetic Steel", 0.25);
|
||||
var b = library.Add("SYN-B", "Synthetic Aluminum", 0.125);
|
||||
var c = library.Add("SYN-C", "Synthetic Steel", 0.25);
|
||||
var sets = new InMemoryDrawingSets();
|
||||
var created = Run(sets.CreateAsync(new DrawingSetRecord
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Synthetic kit",
|
||||
Members = new[] { new DrawingSetMember { DrawingId = b.Id, Quantity = 2, Drawing = b } },
|
||||
}));
|
||||
|
||||
using var form = new DrawingLibraryForm(library, Server);
|
||||
form.Show();
|
||||
var grid = Field<DataGridView>(form, "drawingGrid");
|
||||
PumpUntil(() => grid.Rows.Count == 3, "the unfiltered library page");
|
||||
using var editor = new EditDrawingSetForm(new DrawingSetEditSession(sets, created, "Synthetic operator"), library, Server);
|
||||
editor.ShowMessage = (text, _, _) => throw new Xunit.Sdk.XunitException(text);
|
||||
editor.Show();
|
||||
var libraryGrid = Field<DataGridView>(editor, "libraryGrid");
|
||||
var memberGrid = Field<DataGridView>(editor, "memberGrid");
|
||||
var add = Field<Button>(editor, "addButton");
|
||||
PumpUntil(() => libraryGrid.Rows.Count == 3, "the unfiltered library page");
|
||||
|
||||
Assert.True(form.IsPickMode);
|
||||
Assert.Single(Field<TabControl>(form, "tabControl").TabPages);
|
||||
Assert.Equal(("", "", (double?)null), (library.Queries[0].MaterialName, library.Queries[0].MaterialGrade, library.Queries[0].Thickness));
|
||||
grid.ClearSelection();
|
||||
grid.Rows[2].Selected = true;
|
||||
grid.Rows[0].Selected = true;
|
||||
Field<NumericUpDown>(form, "quantityBox").Value = 4;
|
||||
Run(form.AddSelectedAsync());
|
||||
Assert.Equal(SystemColors.GrayText, libraryGrid.Rows[1].DefaultCellStyle.ForeColor);
|
||||
Assert.Equal(Color.Empty, libraryGrid.Rows[0].DefaultCellStyle.ForeColor);
|
||||
|
||||
Assert.Equal(DialogResult.OK, form.DialogResult);
|
||||
Assert.Equal(new[] { a, c }, form.PickedDrawings);
|
||||
Assert.Equal(4, form.PickedQuantity);
|
||||
libraryGrid.ClearSelection();
|
||||
libraryGrid.Rows[2].Selected = true;
|
||||
libraryGrid.Rows[1].Selected = true;
|
||||
libraryGrid.Rows[0].Selected = true;
|
||||
Assert.True(add.Enabled);
|
||||
Field<NumericUpDown>(editor, "quantityBox").Value = 4;
|
||||
editor.AddSelectedDrawings();
|
||||
|
||||
Assert.Equal(new[] { ("SYN-B", 2), ("SYN-A", 4), ("SYN-C", 4) },
|
||||
memberGrid.Rows.Cast<DataGridViewRow>().Select(r => ((string)r.Cells["drawingColumn"].Value, (int)r.Cells["quantityColumn"].Value)));
|
||||
Assert.Contains("Already in the set: 'SYN-B'", Field<Label>(editor, "statusLabel").Text);
|
||||
Assert.All(libraryGrid.Rows.Cast<DataGridViewRow>(), r => Assert.Equal(SystemColors.GrayText, r.DefaultCellStyle.ForeColor));
|
||||
|
||||
memberGrid.CurrentCell = memberGrid.Rows[1].Cells["drawingColumn"];
|
||||
Field<Button>(editor, "removeButton").PerformClick();
|
||||
Assert.Equal(Color.Empty, libraryGrid.Rows[0].DefaultCellStyle.ForeColor);
|
||||
|
||||
Run(editor.SaveAsync());
|
||||
var stored = sets.Current.Single();
|
||||
Assert.Equal(new[] { (b.Id, 2), (c.Id, 4) }, stored.Members.Select(m => (m.DrawingId, m.Quantity)));
|
||||
},
|
||||
TestTimeout,
|
||||
"The pick mode test did not complete.");
|
||||
"The editor library pane test did not complete.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -22,11 +22,6 @@ namespace OpenNest.Forms
|
||||
/// rotation, color) on the server as a new revision with the same package. With a set
|
||||
/// store, the Sets tab browses and edits drawing sets (<see cref="Controls.DrawingSetBrowser"/>),
|
||||
/// and the drawing grid's menu lists the sets a drawing is in and adds it to a set.
|
||||
/// <para>
|
||||
/// Opened without a nest it picks drawings for a drawing set instead: every active
|
||||
/// drawing is listed, several may be selected, and Add to Set closes the dialog with
|
||||
/// <see cref="PickedDrawings"/>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public partial class DrawingLibraryForm : Form
|
||||
{
|
||||
@@ -54,15 +49,6 @@ namespace OpenNest.Forms
|
||||
/// <summary>Shows the set editor and returns the saved record, or null; replaced by tests.</summary>
|
||||
internal Func<DrawingSetEditSession, DrawingSetRecord> EditSet { get; set; }
|
||||
|
||||
/// <summary>In pick mode, the drawings chosen, in list order, once the dialog closes with OK.</summary>
|
||||
public IReadOnlyList<DrawingLibraryRecord> PickedDrawings { get; private set; } = Array.Empty<DrawingLibraryRecord>();
|
||||
|
||||
/// <summary>In pick mode, the quantity entered for the picked drawings.</summary>
|
||||
public int PickedQuantity { get; private set; }
|
||||
|
||||
/// <summary>True when the dialog picks drawings for a set rather than adding them to a nest.</summary>
|
||||
public bool IsPickMode => nest == null;
|
||||
|
||||
/// <summary>
|
||||
/// The library drawings this dialog added or raised the quantity of, in order. The
|
||||
/// dialog stays open after each add, so callers check this rather than the dialog result.
|
||||
@@ -71,25 +57,13 @@ namespace OpenNest.Forms
|
||||
|
||||
/// <param name="sets">Enables Used in Sets and Add to Set; null hides them.</param>
|
||||
public DrawingLibraryForm(IDrawingLibraryStore library, string serverUrl, Nest nest, IDrawingSetStore sets = null)
|
||||
: this(library, serverUrl, nest ?? throw new ArgumentNullException(nameof(nest)), sets, pick: false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Picks drawings for a drawing set (see <see cref="PickedDrawings"/>).</summary>
|
||||
public DrawingLibraryForm(IDrawingLibraryStore library, string serverUrl)
|
||||
: this(library, serverUrl, null, null, pick: true)
|
||||
{
|
||||
}
|
||||
|
||||
private DrawingLibraryForm(IDrawingLibraryStore library, string serverUrl, Nest nest, IDrawingSetStore sets, bool pick)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.library = library ?? throw new ArgumentNullException(nameof(library));
|
||||
this.serverUrl = serverUrl ?? "";
|
||||
this.nest = nest;
|
||||
this.nest = nest ?? throw new ArgumentNullException(nameof(nest));
|
||||
this.sets = sets;
|
||||
// Without a nest there is no material or thickness to filter by.
|
||||
session = new DrawingLibraryBrowseSession(library, nest ?? new Nest());
|
||||
session = new DrawingLibraryBrowseSession(library, nest);
|
||||
ShowMessage = (text, buttons, icon) => MessageBox.Show(this, text, Text, buttons, icon);
|
||||
EditDrawing = edit =>
|
||||
{
|
||||
@@ -117,18 +91,9 @@ namespace OpenNest.Forms
|
||||
revisionColumn.Tag = DrawingSortField.Revision;
|
||||
savedColumn.Tag = DrawingSortField.SavedAt;
|
||||
|
||||
if (pick)
|
||||
{
|
||||
Text = $"Add Drawings to Set — {this.serverUrl}";
|
||||
addButton.Text = "Add to Set";
|
||||
drawingGrid.MultiSelect = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = $"Add from Drawing Library — {this.serverUrl}";
|
||||
}
|
||||
Text = $"Add from Drawing Library — {this.serverUrl}";
|
||||
|
||||
if (sets != null && !pick)
|
||||
if (sets != null)
|
||||
{
|
||||
drawingGrid.ContextMenuStrip = drawingMenu;
|
||||
setBrowser.Initialize(sets, library, this.serverUrl);
|
||||
@@ -376,12 +341,6 @@ namespace OpenNest.Forms
|
||||
/// </summary>
|
||||
internal async Task AddSelectedAsync()
|
||||
{
|
||||
if (IsPickMode)
|
||||
{
|
||||
PickSelected();
|
||||
return;
|
||||
}
|
||||
|
||||
var record = SelectedRecord();
|
||||
if (record == null || adding)
|
||||
return;
|
||||
@@ -450,25 +409,6 @@ namespace OpenNest.Forms
|
||||
}
|
||||
}
|
||||
|
||||
// Pick mode: closes with every selected drawing, in list order.
|
||||
private void PickSelected()
|
||||
{
|
||||
var picked = drawingGrid.SelectedRows.Cast<DataGridViewRow>()
|
||||
.OrderBy(row => row.Index)
|
||||
.Select(row => row.Tag as DrawingLibraryRecord)
|
||||
.Where(record => record != null)
|
||||
.ToList();
|
||||
if (picked.Count == 0 && SelectedRecord() is { } current)
|
||||
picked.Add(current);
|
||||
if (picked.Count == 0)
|
||||
return;
|
||||
|
||||
PickedDrawings = picked;
|
||||
PickedQuantity = (int)quantityBox.Value;
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Fail(string message)
|
||||
{
|
||||
if (IsDisposed)
|
||||
@@ -555,12 +495,6 @@ namespace OpenNest.Forms
|
||||
|
||||
private void UpdateFilterLabel(bool showAll = false)
|
||||
{
|
||||
if (IsPickMode)
|
||||
{
|
||||
filterLabel.Text = "Showing every drawing. Select several with Ctrl or Shift.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!session.IsFilteredToNest && !showAll)
|
||||
{
|
||||
filterLabel.Text = "This nest has no material or thickness; showing every drawing.";
|
||||
|
||||
+314
-32
@@ -17,8 +17,10 @@ namespace OpenNest.Forms
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
System.Windows.Forms.DataGridViewCellStyle rightAligned = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle quantityStyle = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle libraryRightAligned = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
layoutTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
detailsTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
nameLabel = new System.Windows.Forms.Label();
|
||||
@@ -27,6 +29,25 @@ namespace OpenNest.Forms
|
||||
customerBox = new System.Windows.Forms.TextBox();
|
||||
notesLabel = new System.Windows.Forms.Label();
|
||||
notesBox = new System.Windows.Forms.TextBox();
|
||||
splitContainer = new System.Windows.Forms.SplitContainer();
|
||||
libraryGroup = new System.Windows.Forms.GroupBox();
|
||||
libraryTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
searchBox = new System.Windows.Forms.TextBox();
|
||||
libraryGrid = new System.Windows.Forms.DataGridView();
|
||||
libraryNameColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
libraryMaterialColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
libraryGradeColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
libraryThicknessColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
libraryCustomerColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
libraryNavTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
previousButton = new System.Windows.Forms.Button();
|
||||
nextButton = new System.Windows.Forms.Button();
|
||||
librarySummaryLabel = new System.Windows.Forms.Label();
|
||||
addTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
quantityLabel = new System.Windows.Forms.Label();
|
||||
quantityBox = new System.Windows.Forms.NumericUpDown();
|
||||
addButton = new System.Windows.Forms.Button();
|
||||
memberGroup = new System.Windows.Forms.GroupBox();
|
||||
memberTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
memberGrid = new System.Windows.Forms.DataGridView();
|
||||
drawingColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
@@ -38,7 +59,6 @@ namespace OpenNest.Forms
|
||||
quantityColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
warningColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
memberButtons = new System.Windows.Forms.FlowLayoutPanel();
|
||||
addButton = new System.Windows.Forms.Button();
|
||||
removeButton = new System.Windows.Forms.Button();
|
||||
upButton = new System.Windows.Forms.Button();
|
||||
downButton = new System.Windows.Forms.Button();
|
||||
@@ -47,8 +67,20 @@ namespace OpenNest.Forms
|
||||
saveButton = new System.Windows.Forms.Button();
|
||||
cancelButton = new System.Windows.Forms.Button();
|
||||
statusLabel = new System.Windows.Forms.Label();
|
||||
searchTimer = new System.Windows.Forms.Timer(components);
|
||||
layoutTable.SuspendLayout();
|
||||
detailsTable.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)splitContainer).BeginInit();
|
||||
splitContainer.Panel1.SuspendLayout();
|
||||
splitContainer.Panel2.SuspendLayout();
|
||||
splitContainer.SuspendLayout();
|
||||
libraryGroup.SuspendLayout();
|
||||
libraryTable.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)libraryGrid).BeginInit();
|
||||
libraryNavTable.SuspendLayout();
|
||||
addTable.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)quantityBox).BeginInit();
|
||||
memberGroup.SuspendLayout();
|
||||
memberTable.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)memberGrid).BeginInit();
|
||||
memberButtons.SuspendLayout();
|
||||
@@ -60,7 +92,7 @@ namespace OpenNest.Forms
|
||||
layoutTable.ColumnCount = 1;
|
||||
layoutTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
layoutTable.Controls.Add(detailsTable, 0, 0);
|
||||
layoutTable.Controls.Add(memberTable, 0, 1);
|
||||
layoutTable.Controls.Add(splitContainer, 0, 1);
|
||||
layoutTable.Controls.Add(bottomTable, 0, 2);
|
||||
layoutTable.Controls.Add(statusLabel, 0, 3);
|
||||
layoutTable.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
@@ -72,7 +104,7 @@ namespace OpenNest.Forms
|
||||
layoutTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
layoutTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
layoutTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
layoutTable.Size = new System.Drawing.Size(904, 561);
|
||||
layoutTable.Size = new System.Drawing.Size(1264, 641);
|
||||
layoutTable.TabIndex = 0;
|
||||
//
|
||||
// detailsTable
|
||||
@@ -95,7 +127,7 @@ namespace OpenNest.Forms
|
||||
detailsTable.Name = "detailsTable";
|
||||
detailsTable.RowCount = 2;
|
||||
detailsTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
detailsTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 60F));
|
||||
detailsTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 48F));
|
||||
detailsTable.TabIndex = 0;
|
||||
//
|
||||
// nameLabel
|
||||
@@ -149,6 +181,224 @@ namespace OpenNest.Forms
|
||||
notesBox.TabIndex = 5;
|
||||
notesBox.TextChanged += Details_TextChanged;
|
||||
//
|
||||
// splitContainer
|
||||
//
|
||||
splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
splitContainer.Margin = new System.Windows.Forms.Padding(0);
|
||||
splitContainer.Name = "splitContainer";
|
||||
splitContainer.Panel1.Controls.Add(libraryGroup);
|
||||
splitContainer.Panel2.Controls.Add(memberGroup);
|
||||
splitContainer.Size = new System.Drawing.Size(1248, 470);
|
||||
splitContainer.SplitterDistance = 450;
|
||||
splitContainer.SplitterWidth = 6;
|
||||
splitContainer.Panel1MinSize = 320;
|
||||
splitContainer.Panel2MinSize = 420;
|
||||
splitContainer.TabIndex = 1;
|
||||
//
|
||||
// libraryGroup
|
||||
//
|
||||
libraryGroup.Controls.Add(libraryTable);
|
||||
libraryGroup.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
libraryGroup.Name = "libraryGroup";
|
||||
libraryGroup.Padding = new System.Windows.Forms.Padding(6);
|
||||
libraryGroup.TabIndex = 0;
|
||||
libraryGroup.TabStop = false;
|
||||
libraryGroup.Text = "Drawing library";
|
||||
//
|
||||
// libraryTable
|
||||
//
|
||||
libraryTable.ColumnCount = 1;
|
||||
libraryTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
libraryTable.Controls.Add(searchBox, 0, 0);
|
||||
libraryTable.Controls.Add(libraryGrid, 0, 1);
|
||||
libraryTable.Controls.Add(libraryNavTable, 0, 2);
|
||||
libraryTable.Controls.Add(addTable, 0, 3);
|
||||
libraryTable.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
libraryTable.Margin = new System.Windows.Forms.Padding(0);
|
||||
libraryTable.Name = "libraryTable";
|
||||
libraryTable.RowCount = 4;
|
||||
libraryTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
libraryTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
libraryTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
libraryTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
libraryTable.TabIndex = 0;
|
||||
//
|
||||
// searchBox
|
||||
//
|
||||
searchBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
searchBox.Margin = new System.Windows.Forms.Padding(0, 0, 0, 6);
|
||||
searchBox.Name = "searchBox";
|
||||
searchBox.PlaceholderText = "Search by name, customer or notes";
|
||||
searchBox.TabIndex = 0;
|
||||
searchBox.TextChanged += SearchBox_TextChanged;
|
||||
//
|
||||
// libraryGrid
|
||||
//
|
||||
libraryGrid.AllowUserToAddRows = false;
|
||||
libraryGrid.AllowUserToDeleteRows = false;
|
||||
libraryGrid.AllowUserToOrderColumns = false;
|
||||
libraryGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { libraryNameColumn, libraryMaterialColumn, libraryGradeColumn, libraryThicknessColumn, libraryCustomerColumn });
|
||||
libraryGrid.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
libraryGrid.Margin = new System.Windows.Forms.Padding(0);
|
||||
libraryGrid.MultiSelect = true;
|
||||
libraryGrid.Name = "libraryGrid";
|
||||
libraryGrid.ReadOnly = true;
|
||||
libraryGrid.RowHeadersVisible = false;
|
||||
libraryGrid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
|
||||
libraryGrid.StandardTab = true;
|
||||
libraryGrid.TabIndex = 1;
|
||||
libraryGrid.CellDoubleClick += LibraryGrid_CellDoubleClick;
|
||||
libraryGrid.ColumnHeaderMouseClick += LibraryGrid_ColumnHeaderMouseClick;
|
||||
libraryGrid.SelectionChanged += LibraryGrid_SelectionChanged;
|
||||
//
|
||||
// libraryNameColumn
|
||||
//
|
||||
libraryNameColumn.HeaderText = "Drawing";
|
||||
libraryNameColumn.Name = "libraryNameColumn";
|
||||
libraryNameColumn.ReadOnly = true;
|
||||
libraryNameColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
|
||||
libraryNameColumn.Width = 140;
|
||||
//
|
||||
// libraryMaterialColumn
|
||||
//
|
||||
libraryMaterialColumn.HeaderText = "Material";
|
||||
libraryMaterialColumn.Name = "libraryMaterialColumn";
|
||||
libraryMaterialColumn.ReadOnly = true;
|
||||
libraryMaterialColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
|
||||
libraryMaterialColumn.Width = 100;
|
||||
//
|
||||
// libraryGradeColumn
|
||||
//
|
||||
libraryGradeColumn.HeaderText = "Grade";
|
||||
libraryGradeColumn.Name = "libraryGradeColumn";
|
||||
libraryGradeColumn.ReadOnly = true;
|
||||
libraryGradeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
|
||||
libraryGradeColumn.Width = 60;
|
||||
//
|
||||
// libraryThicknessColumn
|
||||
//
|
||||
libraryRightAligned.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight;
|
||||
libraryThicknessColumn.DefaultCellStyle = libraryRightAligned;
|
||||
libraryThicknessColumn.HeaderText = "Thickness";
|
||||
libraryThicknessColumn.Name = "libraryThicknessColumn";
|
||||
libraryThicknessColumn.ReadOnly = true;
|
||||
libraryThicknessColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
|
||||
libraryThicknessColumn.Width = 70;
|
||||
//
|
||||
// libraryCustomerColumn
|
||||
//
|
||||
libraryCustomerColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
libraryCustomerColumn.HeaderText = "Customer";
|
||||
libraryCustomerColumn.MinimumWidth = 60;
|
||||
libraryCustomerColumn.Name = "libraryCustomerColumn";
|
||||
libraryCustomerColumn.ReadOnly = true;
|
||||
libraryCustomerColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Programmatic;
|
||||
//
|
||||
// libraryNavTable
|
||||
//
|
||||
libraryNavTable.AutoSize = true;
|
||||
libraryNavTable.ColumnCount = 3;
|
||||
libraryNavTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
libraryNavTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
libraryNavTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
libraryNavTable.Controls.Add(previousButton, 0, 0);
|
||||
libraryNavTable.Controls.Add(nextButton, 1, 0);
|
||||
libraryNavTable.Controls.Add(librarySummaryLabel, 2, 0);
|
||||
libraryNavTable.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
libraryNavTable.Margin = new System.Windows.Forms.Padding(0, 4, 0, 0);
|
||||
libraryNavTable.Name = "libraryNavTable";
|
||||
libraryNavTable.RowCount = 1;
|
||||
libraryNavTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
libraryNavTable.TabIndex = 2;
|
||||
//
|
||||
// previousButton
|
||||
//
|
||||
previousButton.Enabled = false;
|
||||
previousButton.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||
previousButton.Name = "previousButton";
|
||||
previousButton.Size = new System.Drawing.Size(34, 26);
|
||||
previousButton.TabIndex = 0;
|
||||
previousButton.Text = "<";
|
||||
previousButton.UseVisualStyleBackColor = true;
|
||||
previousButton.Click += PreviousButton_Click;
|
||||
//
|
||||
// nextButton
|
||||
//
|
||||
nextButton.Enabled = false;
|
||||
nextButton.Margin = new System.Windows.Forms.Padding(0, 0, 6, 0);
|
||||
nextButton.Name = "nextButton";
|
||||
nextButton.Size = new System.Drawing.Size(34, 26);
|
||||
nextButton.TabIndex = 1;
|
||||
nextButton.Text = ">";
|
||||
nextButton.UseVisualStyleBackColor = true;
|
||||
nextButton.Click += NextButton_Click;
|
||||
//
|
||||
// librarySummaryLabel
|
||||
//
|
||||
librarySummaryLabel.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
librarySummaryLabel.AutoEllipsis = true;
|
||||
librarySummaryLabel.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
librarySummaryLabel.Name = "librarySummaryLabel";
|
||||
librarySummaryLabel.TabIndex = 2;
|
||||
//
|
||||
// addTable
|
||||
//
|
||||
addTable.AutoSize = true;
|
||||
addTable.ColumnCount = 4;
|
||||
addTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
addTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
addTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
addTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
addTable.Controls.Add(quantityLabel, 1, 0);
|
||||
addTable.Controls.Add(quantityBox, 2, 0);
|
||||
addTable.Controls.Add(addButton, 3, 0);
|
||||
addTable.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
addTable.Margin = new System.Windows.Forms.Padding(0, 6, 0, 0);
|
||||
addTable.Name = "addTable";
|
||||
addTable.RowCount = 1;
|
||||
addTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
addTable.TabIndex = 3;
|
||||
//
|
||||
// quantityLabel
|
||||
//
|
||||
quantityLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
quantityLabel.AutoSize = true;
|
||||
quantityLabel.Name = "quantityLabel";
|
||||
quantityLabel.TabIndex = 0;
|
||||
quantityLabel.Text = "Qty per kit:";
|
||||
//
|
||||
// quantityBox
|
||||
//
|
||||
quantityBox.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
quantityBox.Maximum = new decimal(new int[] { 100000, 0, 0, 0 });
|
||||
quantityBox.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
|
||||
quantityBox.Name = "quantityBox";
|
||||
quantityBox.Size = new System.Drawing.Size(70, 25);
|
||||
quantityBox.TabIndex = 1;
|
||||
quantityBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||
quantityBox.Value = new decimal(new int[] { 1, 0, 0, 0 });
|
||||
//
|
||||
// addButton
|
||||
//
|
||||
addButton.Enabled = false;
|
||||
addButton.Margin = new System.Windows.Forms.Padding(6, 0, 0, 0);
|
||||
addButton.Name = "addButton";
|
||||
addButton.Size = new System.Drawing.Size(120, 28);
|
||||
addButton.TabIndex = 2;
|
||||
addButton.Text = "Add to Set →";
|
||||
addButton.UseVisualStyleBackColor = true;
|
||||
addButton.Click += AddButton_Click;
|
||||
//
|
||||
// memberGroup
|
||||
//
|
||||
memberGroup.Controls.Add(memberTable);
|
||||
memberGroup.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
memberGroup.Name = "memberGroup";
|
||||
memberGroup.Padding = new System.Windows.Forms.Padding(6);
|
||||
memberGroup.TabIndex = 0;
|
||||
memberGroup.TabStop = false;
|
||||
memberGroup.Text = "In this set";
|
||||
//
|
||||
// memberTable
|
||||
//
|
||||
memberTable.ColumnCount = 2;
|
||||
@@ -161,7 +411,7 @@ namespace OpenNest.Forms
|
||||
memberTable.Name = "memberTable";
|
||||
memberTable.RowCount = 1;
|
||||
memberTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
memberTable.TabIndex = 1;
|
||||
memberTable.TabIndex = 0;
|
||||
//
|
||||
// memberGrid
|
||||
//
|
||||
@@ -171,6 +421,7 @@ namespace OpenNest.Forms
|
||||
memberGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { drawingColumn, materialColumn, gradeColumn, thicknessColumn, unitsColumn, cutTypeColumn, quantityColumn, warningColumn });
|
||||
memberGrid.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
memberGrid.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystrokeOrF2;
|
||||
memberGrid.Margin = new System.Windows.Forms.Padding(0);
|
||||
memberGrid.MultiSelect = false;
|
||||
memberGrid.Name = "memberGrid";
|
||||
memberGrid.RowHeadersVisible = false;
|
||||
@@ -188,7 +439,7 @@ namespace OpenNest.Forms
|
||||
drawingColumn.Name = "drawingColumn";
|
||||
drawingColumn.ReadOnly = true;
|
||||
drawingColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
drawingColumn.Width = 200;
|
||||
drawingColumn.Width = 150;
|
||||
//
|
||||
// materialColumn
|
||||
//
|
||||
@@ -196,7 +447,7 @@ namespace OpenNest.Forms
|
||||
materialColumn.Name = "materialColumn";
|
||||
materialColumn.ReadOnly = true;
|
||||
materialColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
materialColumn.Width = 140;
|
||||
materialColumn.Width = 100;
|
||||
//
|
||||
// gradeColumn
|
||||
//
|
||||
@@ -204,7 +455,7 @@ namespace OpenNest.Forms
|
||||
gradeColumn.Name = "gradeColumn";
|
||||
gradeColumn.ReadOnly = true;
|
||||
gradeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
gradeColumn.Width = 90;
|
||||
gradeColumn.Width = 60;
|
||||
//
|
||||
// thicknessColumn
|
||||
//
|
||||
@@ -214,7 +465,7 @@ namespace OpenNest.Forms
|
||||
thicknessColumn.Name = "thicknessColumn";
|
||||
thicknessColumn.ReadOnly = true;
|
||||
thicknessColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
thicknessColumn.Width = 80;
|
||||
thicknessColumn.Width = 70;
|
||||
//
|
||||
// unitsColumn
|
||||
//
|
||||
@@ -222,7 +473,7 @@ namespace OpenNest.Forms
|
||||
unitsColumn.Name = "unitsColumn";
|
||||
unitsColumn.ReadOnly = true;
|
||||
unitsColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
unitsColumn.Width = 60;
|
||||
unitsColumn.Width = 50;
|
||||
//
|
||||
// cutTypeColumn
|
||||
//
|
||||
@@ -230,7 +481,7 @@ namespace OpenNest.Forms
|
||||
cutTypeColumn.Name = "cutTypeColumn";
|
||||
cutTypeColumn.ReadOnly = true;
|
||||
cutTypeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
cutTypeColumn.Width = 75;
|
||||
cutTypeColumn.Width = 65;
|
||||
//
|
||||
// quantityColumn
|
||||
//
|
||||
@@ -242,12 +493,13 @@ namespace OpenNest.Forms
|
||||
quantityColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
quantityColumn.ToolTipText = "Quantity per kit; type to change it";
|
||||
quantityColumn.ValueType = typeof(int);
|
||||
quantityColumn.Width = 60;
|
||||
quantityColumn.Width = 50;
|
||||
//
|
||||
// warningColumn
|
||||
//
|
||||
warningColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
warningColumn.HeaderText = "Note";
|
||||
warningColumn.MinimumWidth = 60;
|
||||
warningColumn.Name = "warningColumn";
|
||||
warningColumn.ReadOnly = true;
|
||||
warningColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
@@ -255,7 +507,6 @@ namespace OpenNest.Forms
|
||||
// memberButtons
|
||||
//
|
||||
memberButtons.AutoSize = true;
|
||||
memberButtons.Controls.Add(addButton);
|
||||
memberButtons.Controls.Add(removeButton);
|
||||
memberButtons.Controls.Add(upButton);
|
||||
memberButtons.Controls.Add(downButton);
|
||||
@@ -266,21 +517,13 @@ namespace OpenNest.Forms
|
||||
memberButtons.TabIndex = 1;
|
||||
memberButtons.WrapContents = false;
|
||||
//
|
||||
// addButton
|
||||
//
|
||||
addButton.Name = "addButton";
|
||||
addButton.Size = new System.Drawing.Size(130, 28);
|
||||
addButton.TabIndex = 0;
|
||||
addButton.Text = "Add Drawings...";
|
||||
addButton.UseVisualStyleBackColor = true;
|
||||
addButton.Click += AddButton_Click;
|
||||
//
|
||||
// removeButton
|
||||
//
|
||||
removeButton.Enabled = false;
|
||||
removeButton.Margin = new System.Windows.Forms.Padding(0, 0, 0, 3);
|
||||
removeButton.Name = "removeButton";
|
||||
removeButton.Size = new System.Drawing.Size(130, 28);
|
||||
removeButton.TabIndex = 1;
|
||||
removeButton.Size = new System.Drawing.Size(100, 28);
|
||||
removeButton.TabIndex = 0;
|
||||
removeButton.Text = "Remove";
|
||||
removeButton.UseVisualStyleBackColor = true;
|
||||
removeButton.Click += RemoveButton_Click;
|
||||
@@ -288,10 +531,10 @@ namespace OpenNest.Forms
|
||||
// upButton
|
||||
//
|
||||
upButton.Enabled = false;
|
||||
upButton.Margin = new System.Windows.Forms.Padding(3, 12, 3, 3);
|
||||
upButton.Margin = new System.Windows.Forms.Padding(0, 12, 0, 3);
|
||||
upButton.Name = "upButton";
|
||||
upButton.Size = new System.Drawing.Size(130, 28);
|
||||
upButton.TabIndex = 2;
|
||||
upButton.Size = new System.Drawing.Size(100, 28);
|
||||
upButton.TabIndex = 1;
|
||||
upButton.Text = "Move Up";
|
||||
upButton.UseVisualStyleBackColor = true;
|
||||
upButton.Click += UpButton_Click;
|
||||
@@ -299,9 +542,10 @@ namespace OpenNest.Forms
|
||||
// downButton
|
||||
//
|
||||
downButton.Enabled = false;
|
||||
downButton.Margin = new System.Windows.Forms.Padding(0, 0, 0, 3);
|
||||
downButton.Name = "downButton";
|
||||
downButton.Size = new System.Drawing.Size(130, 28);
|
||||
downButton.TabIndex = 3;
|
||||
downButton.Size = new System.Drawing.Size(100, 28);
|
||||
downButton.TabIndex = 2;
|
||||
downButton.Text = "Move Down";
|
||||
downButton.UseVisualStyleBackColor = true;
|
||||
downButton.Click += DownButton_Click;
|
||||
@@ -358,25 +602,44 @@ namespace OpenNest.Forms
|
||||
statusLabel.Size = new System.Drawing.Size(100, 20);
|
||||
statusLabel.TabIndex = 3;
|
||||
//
|
||||
// searchTimer
|
||||
//
|
||||
searchTimer.Interval = 300;
|
||||
searchTimer.Tick += SearchTimer_Tick;
|
||||
//
|
||||
// EditDrawingSetForm
|
||||
//
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
CancelButton = cancelButton;
|
||||
ClientSize = new System.Drawing.Size(904, 561);
|
||||
ClientSize = new System.Drawing.Size(1264, 641);
|
||||
Controls.Add(layoutTable);
|
||||
Font = new System.Drawing.Font("Segoe UI", 9.75F);
|
||||
MinimizeBox = false;
|
||||
MinimumSize = new System.Drawing.Size(720, 420);
|
||||
MinimumSize = new System.Drawing.Size(1000, 480);
|
||||
Name = "EditDrawingSetForm";
|
||||
ShowIcon = false;
|
||||
ShowInTaskbar = false;
|
||||
StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
Text = "Drawing Set";
|
||||
FormClosing += EditDrawingSetForm_FormClosing;
|
||||
Shown += EditDrawingSetForm_Shown;
|
||||
layoutTable.ResumeLayout(false);
|
||||
layoutTable.PerformLayout();
|
||||
detailsTable.ResumeLayout(false);
|
||||
detailsTable.PerformLayout();
|
||||
splitContainer.Panel1.ResumeLayout(false);
|
||||
splitContainer.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)splitContainer).EndInit();
|
||||
splitContainer.ResumeLayout(false);
|
||||
libraryGroup.ResumeLayout(false);
|
||||
libraryTable.ResumeLayout(false);
|
||||
libraryTable.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)libraryGrid).EndInit();
|
||||
libraryNavTable.ResumeLayout(false);
|
||||
addTable.ResumeLayout(false);
|
||||
addTable.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)quantityBox).EndInit();
|
||||
memberGroup.ResumeLayout(false);
|
||||
memberTable.ResumeLayout(false);
|
||||
memberTable.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)memberGrid).EndInit();
|
||||
@@ -396,6 +659,25 @@ namespace OpenNest.Forms
|
||||
private System.Windows.Forms.TextBox customerBox;
|
||||
private System.Windows.Forms.Label notesLabel;
|
||||
private System.Windows.Forms.TextBox notesBox;
|
||||
private System.Windows.Forms.SplitContainer splitContainer;
|
||||
private System.Windows.Forms.GroupBox libraryGroup;
|
||||
private System.Windows.Forms.TableLayoutPanel libraryTable;
|
||||
private System.Windows.Forms.TextBox searchBox;
|
||||
private System.Windows.Forms.DataGridView libraryGrid;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn libraryNameColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn libraryMaterialColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn libraryGradeColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn libraryThicknessColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn libraryCustomerColumn;
|
||||
private System.Windows.Forms.TableLayoutPanel libraryNavTable;
|
||||
private System.Windows.Forms.Button previousButton;
|
||||
private System.Windows.Forms.Button nextButton;
|
||||
private System.Windows.Forms.Label librarySummaryLabel;
|
||||
private System.Windows.Forms.TableLayoutPanel addTable;
|
||||
private System.Windows.Forms.Label quantityLabel;
|
||||
private System.Windows.Forms.NumericUpDown quantityBox;
|
||||
private System.Windows.Forms.Button addButton;
|
||||
private System.Windows.Forms.GroupBox memberGroup;
|
||||
private System.Windows.Forms.TableLayoutPanel memberTable;
|
||||
private System.Windows.Forms.DataGridView memberGrid;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn drawingColumn;
|
||||
@@ -407,7 +689,6 @@ namespace OpenNest.Forms
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn quantityColumn;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn warningColumn;
|
||||
private System.Windows.Forms.FlowLayoutPanel memberButtons;
|
||||
private System.Windows.Forms.Button addButton;
|
||||
private System.Windows.Forms.Button removeButton;
|
||||
private System.Windows.Forms.Button upButton;
|
||||
private System.Windows.Forms.Button downButton;
|
||||
@@ -416,5 +697,6 @@ namespace OpenNest.Forms
|
||||
private System.Windows.Forms.Button saveButton;
|
||||
private System.Windows.Forms.Button cancelButton;
|
||||
private System.Windows.Forms.Label statusLabel;
|
||||
private System.Windows.Forms.Timer searchTimer;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -13,22 +14,25 @@ namespace OpenNest.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates or edits one drawing set through <see cref="DrawingSetEditSession"/>: name,
|
||||
/// customer, notes and the ordered members with a quantity each. Add Drawings picks from
|
||||
/// the drawing library; a drawing already in the set is not added twice. Saving adds a
|
||||
/// revision on the server, guarded by the revision the set was read at.
|
||||
/// customer, notes and the ordered members with a quantity each. The drawing library is
|
||||
/// browsed in the left pane (every active drawing, a page at a time through
|
||||
/// <see cref="DrawingLibraryBrowseSession"/>); Add to Set, a double-click or Enter adds the
|
||||
/// selected drawings at the entered quantity, and a drawing already in the set is greyed
|
||||
/// and not added twice. Saving adds a revision on the server, guarded by the revision the
|
||||
/// set was read at.
|
||||
/// </summary>
|
||||
public partial class EditDrawingSetForm : Form
|
||||
{
|
||||
private const string LoadingText = "Loading...";
|
||||
|
||||
private readonly DrawingSetEditSession session;
|
||||
private readonly DrawingLibraryBrowseSession librarySession;
|
||||
private bool loading;
|
||||
private bool saving;
|
||||
|
||||
/// <summary>Shows a message and returns the operator's answer; replaced by tests.</summary>
|
||||
internal Func<string, MessageBoxButtons, MessageBoxIcon, DialogResult> ShowMessage { get; set; }
|
||||
|
||||
/// <summary>Picks library drawings and the quantity to add them with (none when cancelled); replaced by tests.</summary>
|
||||
internal Func<(IReadOnlyList<DrawingLibraryRecord> Drawings, int Quantity)> PickDrawings { get; set; }
|
||||
|
||||
/// <summary>The saved revision once the dialog closes with OK; otherwise null.</summary>
|
||||
public DrawingSetRecord Saved { get; private set; }
|
||||
|
||||
@@ -37,16 +41,20 @@ namespace OpenNest.Forms
|
||||
InitializeComponent();
|
||||
this.session = session ?? throw new ArgumentNullException(nameof(session));
|
||||
ArgumentNullException.ThrowIfNull(library);
|
||||
// A set mixes materials and thicknesses, so the library is never filtered to a nest.
|
||||
librarySession = new DrawingLibraryBrowseSession(library, new Nest());
|
||||
Disposed += (_, _) => librarySession.Dispose();
|
||||
ShowMessage = (text, buttons, icon) => MessageBox.Show(this, text, Text, buttons, icon);
|
||||
PickDrawings = () =>
|
||||
{
|
||||
using var form = new DrawingLibraryForm(library, serverUrl);
|
||||
return form.ShowDialog(this) == DialogResult.OK
|
||||
? (form.PickedDrawings, form.PickedQuantity)
|
||||
: (Array.Empty<DrawingLibraryRecord>(), 0);
|
||||
};
|
||||
|
||||
GridStyle.Apply(memberGrid);
|
||||
GridStyle.Apply(libraryGrid);
|
||||
libraryNameColumn.Tag = DrawingSortField.Name;
|
||||
libraryMaterialColumn.Tag = DrawingSortField.MaterialName;
|
||||
libraryGradeColumn.Tag = DrawingSortField.MaterialGrade;
|
||||
libraryThicknessColumn.Tag = DrawingSortField.Thickness;
|
||||
libraryCustomerColumn.Tag = DrawingSortField.Customer;
|
||||
quantityBox.Maximum = DrawingSetRules.MaxQuantity;
|
||||
libraryGroup.Text = string.IsNullOrEmpty(serverUrl) ? "Drawing library" : $"Drawing library — {serverUrl}";
|
||||
loading = true;
|
||||
nameBox.Text = session.Name;
|
||||
customerBox.Text = session.Customer;
|
||||
@@ -113,7 +121,54 @@ namespace OpenNest.Forms
|
||||
// Validation refuses bad text before it is parsed; never show the grid's own error dialog.
|
||||
private void MemberGrid_DataError(object sender, DataGridViewDataErrorEventArgs e) => e.ThrowException = false;
|
||||
|
||||
private void AddButton_Click(object sender, EventArgs e) => AddDrawings();
|
||||
private async void EditDrawingSetForm_Shown(object sender, EventArgs e) =>
|
||||
await RunLibraryAsync(librarySession.RefreshAsync);
|
||||
|
||||
private void SearchBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
searchTimer.Stop();
|
||||
searchTimer.Start();
|
||||
}
|
||||
|
||||
private async void SearchTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
searchTimer.Stop();
|
||||
await RunLibraryAsync(() => librarySession.SetSearchAsync(searchBox.Text));
|
||||
}
|
||||
|
||||
private async void LibraryGrid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
|
||||
{
|
||||
// Sorting a page locally would misrepresent the library; the server sorts all matches.
|
||||
if (e.Button == MouseButtons.Left && libraryGrid.Columns[e.ColumnIndex].Tag is DrawingSortField field)
|
||||
await RunLibraryAsync(() => librarySession.SortByAsync(field));
|
||||
}
|
||||
|
||||
private async void PreviousButton_Click(object sender, EventArgs e) =>
|
||||
await RunLibraryAsync(librarySession.PreviousPageAsync);
|
||||
|
||||
private async void NextButton_Click(object sender, EventArgs e) =>
|
||||
await RunLibraryAsync(librarySession.NextPageAsync);
|
||||
|
||||
private void LibraryGrid_SelectionChanged(object sender, EventArgs e) => UpdateAddCommand();
|
||||
|
||||
private void LibraryGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
if (e.RowIndex >= 0)
|
||||
AddSelectedDrawings();
|
||||
}
|
||||
|
||||
private void AddButton_Click(object sender, EventArgs e) => AddSelectedDrawings();
|
||||
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||
{
|
||||
if (keyData == Keys.Enter && libraryGrid.ContainsFocus && SelectedLibraryDrawings().Count > 0)
|
||||
{
|
||||
AddSelectedDrawings();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.ProcessCmdKey(ref msg, keyData);
|
||||
}
|
||||
|
||||
private void RemoveButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
@@ -138,24 +193,122 @@ namespace OpenNest.Forms
|
||||
UpdateCommands();
|
||||
}
|
||||
|
||||
/// <summary>Adds the drawings picked from the library, skipping those already in the set.</summary>
|
||||
internal void AddDrawings()
|
||||
/// <summary>
|
||||
/// Adds the drawings selected in the library pane, in list order, at the entered
|
||||
/// quantity, skipping those already in the set.
|
||||
/// </summary>
|
||||
internal void AddSelectedDrawings()
|
||||
{
|
||||
if (saving || !memberGrid.EndEdit())
|
||||
return;
|
||||
var (drawings, quantity) = PickDrawings();
|
||||
if (drawings == null || drawings.Count == 0 || IsDisposed)
|
||||
var drawings = SelectedLibraryDrawings();
|
||||
if (saving || drawings.Count == 0 || !memberGrid.EndEdit())
|
||||
return;
|
||||
|
||||
var result = session.AddDrawings(drawings, quantity);
|
||||
var result = session.AddDrawings(drawings, (int)quantityBox.Value);
|
||||
Populate(result.Added.Count > 0 ? session.Members.Count - 1 : SelectedIndex());
|
||||
UpdateCommands();
|
||||
var added = result.Added.Count == 1 ? $"Added '{result.Added[0].Name}'." : $"Added {result.Added.Count} drawings.";
|
||||
var added = result.Added.Count switch
|
||||
{
|
||||
0 => "Nothing added.",
|
||||
1 => $"Added '{result.Added[0].Name}'.",
|
||||
_ => $"Added {result.Added.Count} drawings.",
|
||||
};
|
||||
statusLabel.Text = result.AlreadyMembers.Count == 0
|
||||
? added
|
||||
: $"{added} Already in the set: {string.Join(", ", result.AlreadyMembers.Select(d => $"'{d.Name}'"))}.";
|
||||
}
|
||||
|
||||
// Every selected row in list order; the current row alone when nothing is selected.
|
||||
private IReadOnlyList<DrawingLibraryRecord> SelectedLibraryDrawings()
|
||||
{
|
||||
var picked = libraryGrid.SelectedRows.Cast<DataGridViewRow>()
|
||||
.OrderBy(row => row.Index)
|
||||
.Select(row => row.Tag as DrawingLibraryRecord)
|
||||
.Where(record => record != null)
|
||||
.ToList();
|
||||
if (picked.Count == 0 && libraryGrid.CurrentRow?.Tag is DrawingLibraryRecord current)
|
||||
picked.Add(current);
|
||||
return picked;
|
||||
}
|
||||
|
||||
private async Task RunLibraryAsync(Func<Task<bool>> request)
|
||||
{
|
||||
librarySummaryLabel.Text = LoadingText;
|
||||
try
|
||||
{
|
||||
var started = request();
|
||||
UpdateLibraryNavigation();
|
||||
if (await started && !IsDisposed)
|
||||
PopulateLibrary(librarySession.Page);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!IsDisposed)
|
||||
{
|
||||
libraryGrid.Rows.Clear();
|
||||
librarySummaryLabel.Text = ex is ServerTooOldException
|
||||
? ex.Message
|
||||
: $"Could not load the drawing library: {ex.Message}";
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!IsDisposed)
|
||||
{
|
||||
UpdateLibraryNavigation();
|
||||
// A request that was declined or superseded renders nothing of its own.
|
||||
if (!librarySession.IsLoading && librarySummaryLabel.Text == LoadingText)
|
||||
librarySummaryLabel.Text = librarySession.Summary;
|
||||
UpdateAddCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateLibrary(DrawingLibraryPage page)
|
||||
{
|
||||
libraryGrid.Rows.Clear();
|
||||
foreach (var record in page?.Items ?? Array.Empty<DrawingLibraryRecord>())
|
||||
{
|
||||
var index = libraryGrid.Rows.Add(
|
||||
record.Name,
|
||||
record.MaterialName,
|
||||
record.MaterialGrade,
|
||||
record.Thickness.ToString("0.####", CultureInfo.CurrentCulture),
|
||||
record.Customer);
|
||||
libraryGrid.Rows[index].Tag = record;
|
||||
}
|
||||
|
||||
foreach (DataGridViewColumn column in libraryGrid.Columns)
|
||||
{
|
||||
column.HeaderCell.SortGlyphDirection = column.Tag is DrawingSortField field && field == librarySession.Sort
|
||||
? librarySession.Descending ? SortOrder.Descending : SortOrder.Ascending
|
||||
: SortOrder.None;
|
||||
}
|
||||
|
||||
MarkMembersInLibrary();
|
||||
UpdateAddCommand();
|
||||
}
|
||||
|
||||
// Greys the library rows already in the set, so what is left to add stands out.
|
||||
private void MarkMembersInLibrary()
|
||||
{
|
||||
var members = session.Members.Select(m => m.DrawingId).ToHashSet();
|
||||
foreach (DataGridViewRow row in libraryGrid.Rows)
|
||||
{
|
||||
var inSet = row.Tag is DrawingLibraryRecord record && members.Contains(record.Id);
|
||||
row.DefaultCellStyle.ForeColor = inSet ? SystemColors.GrayText : Color.Empty;
|
||||
row.Cells[libraryNameColumn.Index].ToolTipText = inSet ? "Already in this set" : "";
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLibraryNavigation()
|
||||
{
|
||||
previousButton.Enabled = !librarySession.IsLoading && librarySession.CanGoPrevious;
|
||||
nextButton.Enabled = !librarySession.IsLoading && librarySession.CanGoNext;
|
||||
}
|
||||
|
||||
private void UpdateAddCommand() =>
|
||||
addButton.Enabled = !saving && SelectedLibraryDrawings().Count > 0;
|
||||
|
||||
private async void SaveButton_Click(object sender, EventArgs e) => await SaveAsync();
|
||||
|
||||
/// <summary>Saves the set as a new revision; closes with OK on success.</summary>
|
||||
@@ -237,9 +390,10 @@ namespace OpenNest.Forms
|
||||
else
|
||||
memberGrid.ClearSelection();
|
||||
|
||||
MarkMembersInLibrary();
|
||||
var parts = session.Members.Sum(m => (long)m.Quantity);
|
||||
summaryLabel.Text = session.Members.Count == 0
|
||||
? "No drawings yet. Choose Add Drawings to pick them from the library."
|
||||
? "No drawings yet. Select drawings in the library on the left and choose Add to Set."
|
||||
: $"{session.Members.Count:N0} drawing{(session.Members.Count == 1 ? "" : "s")}, {parts:N0} part{(parts == 1 ? "" : "s")} per kit";
|
||||
}
|
||||
|
||||
@@ -260,7 +414,7 @@ namespace OpenNest.Forms
|
||||
{
|
||||
var index = SelectedIndex();
|
||||
var error = session.GetError();
|
||||
addButton.Enabled = !saving;
|
||||
UpdateAddCommand();
|
||||
removeButton.Enabled = !saving && index >= 0;
|
||||
upButton.Enabled = !saving && index > 0;
|
||||
downButton.Enabled = !saving && index >= 0 && index < session.Members.Count - 1;
|
||||
|
||||
@@ -342,9 +342,12 @@ a set shows its notes.
|
||||
- **New Set...** and **Edit...** open the set editor
|
||||
(`OpenNest.Data.DrawingSetEditSession`): name, customer, notes and the member
|
||||
grid (drawing, material, grade, thickness, units, cut type, quantity, note).
|
||||
**Add Drawings...** opens the library in pick mode: every active drawing,
|
||||
several selectable, added with the quantity entered there. A drawing already
|
||||
in the set is skipped and named; one member per drawing. Quantities are edited
|
||||
The editor's left pane browses the library in place, with no second dialog:
|
||||
every active drawing (never filtered to a nest), searched, sorted and paged
|
||||
like the Drawings tab. Select one or several and choose **Add to Set**,
|
||||
double-click or press Enter to add them at the entered quantity per kit.
|
||||
Drawings already in the set are greyed; one picked again is skipped and
|
||||
named, so there is one member per drawing. Quantities are edited
|
||||
in the grid (1 to 100,000); **Remove**, **Move Up** and **Move Down** change
|
||||
the list. The note column flags drawings archived in the library (skipped on
|
||||
release unless included) and drawings with no material or thickness (cannot be
|
||||
|
||||
Reference in new issue
Block a user