From f208569e721cace2f4151f02c4de4bcebfd3211e Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 24 Mar 2026 23:51:21 -0400 Subject: [PATCH] fix: improve CadConverter sidebar layout and bend line visibility Replace sidebar Panel+Splitter with SplitContainer for resizable file list / filter panel. Sort file list alphabetically on insert. Widen bend line dash spacing and draw ETCH layer entities on top of bend lines so etch marks are visible. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest/Controls/EntityView.cs | 15 +- OpenNest/Controls/FileListControl.cs | 10 +- OpenNest/Forms/CadConverterForm.Designer.cs | 299 +++++++++++--------- 3 files changed, 193 insertions(+), 131 deletions(-) diff --git a/OpenNest/Controls/EntityView.cs b/OpenNest/Controls/EntityView.cs index a2476d8..7cd721b 100644 --- a/OpenNest/Controls/EntityView.cs +++ b/OpenNest/Controls/EntityView.cs @@ -48,12 +48,20 @@ namespace OpenNest.Controls foreach (var entity in Entities) { + if (IsEtchLayer(entity.Layer)) continue; var pen = GetEntityPen(entity.Color); DrawEntity(e.Graphics, entity, pen); } DrawBendLines(e.Graphics); + foreach (var entity in Entities) + { + if (!IsEtchLayer(entity.Layer)) continue; + var pen = GetEntityPen(entity.Color); + DrawEntity(e.Graphics, entity, pen); + } + #if DRAW_OFFSET var offsetShape = new Shape(); @@ -138,6 +146,9 @@ namespace OpenNest.Controls penCache.Clear(); } + private static bool IsEtchLayer(Layer layer) => + string.Equals(layer?.Name, "ETCH", System.StringComparison.OrdinalIgnoreCase); + private void DrawBendLines(Graphics g) { if (Bends == null || Bends.Count == 0) @@ -145,11 +156,11 @@ namespace OpenNest.Controls using var bendPen = new Pen(Color.Yellow, 1.5f) { - DashStyle = DashStyle.Dash + DashPattern = new float[] { 8, 6 } }; using var selectedPen = new Pen(Color.Cyan, 2.5f) { - DashStyle = DashStyle.Dash + DashPattern = new float[] { 8, 6 } }; for (var i = 0; i < Bends.Count; i++) diff --git a/OpenNest/Controls/FileListControl.cs b/OpenNest/Controls/FileListControl.cs index 6a0cf2e..6a35270 100644 --- a/OpenNest/Controls/FileListControl.cs +++ b/OpenNest/Controls/FileListControl.cs @@ -62,12 +62,20 @@ namespace OpenNest.Controls public void AddItem(FileListItem item) { - items.Add(item); + var index = items.BinarySearch(item, Comparer.Create( + (a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase))); + if (index < 0) index = ~index; + items.Insert(index, item); + if (items.Count == 1) { selectedIndex = 0; SelectedIndexChanged?.Invoke(this, selectedIndex); } + else if (selectedIndex >= 0 && index <= selectedIndex) + { + selectedIndex++; + } Invalidate(); } diff --git a/OpenNest/Forms/CadConverterForm.Designer.cs b/OpenNest/Forms/CadConverterForm.Designer.cs index 1898619..aa5fc96 100644 --- a/OpenNest/Forms/CadConverterForm.Designer.cs +++ b/OpenNest/Forms/CadConverterForm.Designer.cs @@ -15,10 +15,9 @@ namespace OpenNest.Forms private void InitializeComponent() { - sidebarPanel = new System.Windows.Forms.Panel(); + sidebarSplit = new System.Windows.Forms.SplitContainer(); fileList = new OpenNest.Controls.FileListControl(); filterPanel = new OpenNest.Controls.FilterPanel(); - splitterSidebar = new System.Windows.Forms.Splitter(); entityView1 = new OpenNest.Controls.EntityView(); detailBar = new System.Windows.Forms.FlowLayoutPanel(); lblQty = new System.Windows.Forms.Label(); @@ -33,204 +32,248 @@ namespace OpenNest.Forms bottomPanel1 = new OpenNest.Controls.BottomPanel(); cancelButton = new System.Windows.Forms.Button(); acceptButton = new System.Windows.Forms.Button(); - + ((System.ComponentModel.ISupportInitialize)sidebarSplit).BeginInit(); + sidebarSplit.Panel1.SuspendLayout(); + sidebarSplit.Panel2.SuspendLayout(); + sidebarSplit.SuspendLayout(); + detailBar.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)numQuantity).BeginInit(); - sidebarPanel.SuspendLayout(); bottomPanel1.SuspendLayout(); SuspendLayout(); - - // - // sidebarPanel (Left dock — contains file list + filter panel) - // - sidebarPanel.Dock = System.Windows.Forms.DockStyle.Left; - sidebarPanel.Name = "sidebarPanel"; - sidebarPanel.Size = new System.Drawing.Size(260, 670); - sidebarPanel.Controls.Add(filterPanel); - sidebarPanel.Controls.Add(fileList); - - // - // fileList (Top of sidebar) - // - fileList.Dock = System.Windows.Forms.DockStyle.Top; + // + // sidebarSplit + // + sidebarSplit.Dock = System.Windows.Forms.DockStyle.Left; + sidebarSplit.Location = new System.Drawing.Point(0, 0); + sidebarSplit.Name = "sidebarSplit"; + sidebarSplit.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // sidebarSplit.Panel1 + // + sidebarSplit.Panel1.Controls.Add(fileList); + // + // sidebarSplit.Panel2 + // + sidebarSplit.Panel2.Controls.Add(filterPanel); + sidebarSplit.Size = new System.Drawing.Size(260, 670); + sidebarSplit.SplitterDistance = 300; + sidebarSplit.SplitterWidth = 5; + sidebarSplit.TabIndex = 2; + // + // fileList + // fileList.AllowDrop = true; + fileList.BackColor = System.Drawing.Color.White; + fileList.Dock = System.Windows.Forms.DockStyle.Fill; + fileList.Font = new System.Drawing.Font("Segoe UI", 9F); + fileList.Location = new System.Drawing.Point(0, 0); fileList.Name = "fileList"; fileList.Size = new System.Drawing.Size(260, 300); - - // - // filterPanel (Fill remainder of sidebar) - // + fileList.TabIndex = 0; + // + // filterPanel + // + filterPanel.AutoScroll = true; + filterPanel.BackColor = System.Drawing.Color.White; filterPanel.Dock = System.Windows.Forms.DockStyle.Fill; + filterPanel.Location = new System.Drawing.Point(0, 0); filterPanel.Name = "filterPanel"; - filterPanel.Size = new System.Drawing.Size(260, 370); - - // - // splitterSidebar (between sidebar and preview) - // - splitterSidebar.Location = new System.Drawing.Point(260, 0); - splitterSidebar.Name = "splitterSidebar"; - splitterSidebar.Size = new System.Drawing.Size(3, 670); - splitterSidebar.TabStop = false; - - // - // entityView1 (Fill — main preview area) - // + filterPanel.Size = new System.Drawing.Size(260, 365); + filterPanel.TabIndex = 0; + // + // entityView1 + // entityView1.BackColor = System.Drawing.Color.FromArgb(33, 40, 48); entityView1.Cursor = System.Windows.Forms.Cursors.Cross; entityView1.Dock = System.Windows.Forms.DockStyle.Fill; + entityView1.Location = new System.Drawing.Point(260, 0); entityView1.Name = "entityView1"; - entityView1.Size = new System.Drawing.Size(761, 634); - - // - // detailBar (Bottom of preview area) - // - detailBar.Dock = System.Windows.Forms.DockStyle.Bottom; - detailBar.Name = "detailBar"; - detailBar.Size = new System.Drawing.Size(761, 36); + entityView1.Size = new System.Drawing.Size(764, 634); + entityView1.TabIndex = 0; + // + // detailBar + // detailBar.BackColor = System.Drawing.Color.FromArgb(245, 245, 245); + detailBar.Controls.Add(lblQty); + detailBar.Controls.Add(numQuantity); + detailBar.Controls.Add(lblCust); + detailBar.Controls.Add(txtCustomer); + detailBar.Controls.Add(lblDimensions); + detailBar.Controls.Add(lblEntityCount); + detailBar.Controls.Add(btnSplit); + detailBar.Controls.Add(lblDetect); + detailBar.Controls.Add(cboBendDetector); + detailBar.Dock = System.Windows.Forms.DockStyle.Bottom; + detailBar.Location = new System.Drawing.Point(260, 634); + detailBar.Name = "detailBar"; detailBar.Padding = new System.Windows.Forms.Padding(4, 6, 4, 4); + detailBar.Size = new System.Drawing.Size(764, 36); + detailBar.TabIndex = 1; detailBar.WrapContents = false; - - // + // // lblQty - // - lblQty.Text = "Qty:"; + // lblQty.AutoSize = true; - lblQty.Font = new System.Drawing.Font("Segoe UI", 9f); + lblQty.Font = new System.Drawing.Font("Segoe UI", 9F); + lblQty.Location = new System.Drawing.Point(6, 9); lblQty.Margin = new System.Windows.Forms.Padding(2, 3, 0, 0); - - // + lblQty.Name = "lblQty"; + lblQty.Size = new System.Drawing.Size(29, 15); + lblQty.TabIndex = 0; + lblQty.Text = "Qty:"; + // // numQuantity - // - numQuantity.Size = new System.Drawing.Size(50, 24); - numQuantity.Minimum = 1; - numQuantity.Maximum = 9999; - numQuantity.Value = 1; - numQuantity.Font = new System.Drawing.Font("Segoe UI", 9f); + // + numQuantity.Font = new System.Drawing.Font("Segoe UI", 9F); + numQuantity.Location = new System.Drawing.Point(37, 6); numQuantity.Margin = new System.Windows.Forms.Padding(2, 0, 8, 0); - - // + numQuantity.Maximum = new decimal(new int[] { 9999, 0, 0, 0 }); + numQuantity.Minimum = new decimal(new int[] { 1, 0, 0, 0 }); + numQuantity.Name = "numQuantity"; + numQuantity.Size = new System.Drawing.Size(50, 23); + numQuantity.TabIndex = 1; + numQuantity.Value = new decimal(new int[] { 1, 0, 0, 0 }); + // // lblCust - // - lblCust.Text = "Customer:"; + // lblCust.AutoSize = true; - lblCust.Font = new System.Drawing.Font("Segoe UI", 9f); + lblCust.Font = new System.Drawing.Font("Segoe UI", 9F); + lblCust.Location = new System.Drawing.Point(97, 9); lblCust.Margin = new System.Windows.Forms.Padding(2, 3, 0, 0); - - // + lblCust.Name = "lblCust"; + lblCust.Size = new System.Drawing.Size(62, 15); + lblCust.TabIndex = 2; + lblCust.Text = "Customer:"; + // // txtCustomer - // - txtCustomer.Size = new System.Drawing.Size(100, 24); - txtCustomer.Font = new System.Drawing.Font("Segoe UI", 9f); + // txtCustomer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + txtCustomer.Font = new System.Drawing.Font("Segoe UI", 9F); + txtCustomer.Location = new System.Drawing.Point(161, 6); txtCustomer.Margin = new System.Windows.Forms.Padding(2, 0, 8, 0); - - // + txtCustomer.Name = "txtCustomer"; + txtCustomer.Size = new System.Drawing.Size(100, 23); + txtCustomer.TabIndex = 3; + // // lblDimensions - // + // lblDimensions.AutoSize = true; - lblDimensions.Font = new System.Drawing.Font("Segoe UI", 9f); + lblDimensions.Font = new System.Drawing.Font("Segoe UI", 9F); lblDimensions.ForeColor = System.Drawing.Color.Gray; + lblDimensions.Location = new System.Drawing.Point(271, 9); lblDimensions.Margin = new System.Windows.Forms.Padding(2, 3, 8, 0); - - // + lblDimensions.Name = "lblDimensions"; + lblDimensions.Size = new System.Drawing.Size(0, 15); + lblDimensions.TabIndex = 4; + // // lblEntityCount - // + // lblEntityCount.AutoSize = true; - lblEntityCount.Font = new System.Drawing.Font("Segoe UI", 9f); + lblEntityCount.Font = new System.Drawing.Font("Segoe UI", 9F); lblEntityCount.ForeColor = System.Drawing.Color.Gray; + lblEntityCount.Location = new System.Drawing.Point(281, 9); lblEntityCount.Margin = new System.Windows.Forms.Padding(2, 3, 8, 0); - - // + lblEntityCount.Name = "lblEntityCount"; + lblEntityCount.Size = new System.Drawing.Size(0, 15); + lblEntityCount.TabIndex = 5; + // // btnSplit - // - btnSplit.Text = "Split..."; - btnSplit.Size = new System.Drawing.Size(60, 24); + // btnSplit.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - btnSplit.Font = new System.Drawing.Font("Segoe UI", 9f); + btnSplit.Font = new System.Drawing.Font("Segoe UI", 9F); + btnSplit.Location = new System.Drawing.Point(291, 6); btnSplit.Margin = new System.Windows.Forms.Padding(2, 0, 8, 0); - - // + btnSplit.Name = "btnSplit"; + btnSplit.Size = new System.Drawing.Size(60, 24); + btnSplit.TabIndex = 6; + btnSplit.Text = "Split..."; + // // lblDetect - // - lblDetect.Text = "Bends:"; + // lblDetect.AutoSize = true; - lblDetect.Font = new System.Drawing.Font("Segoe UI", 9f); + lblDetect.Font = new System.Drawing.Font("Segoe UI", 9F); + lblDetect.Location = new System.Drawing.Point(361, 9); lblDetect.Margin = new System.Windows.Forms.Padding(2, 3, 0, 0); - - // + lblDetect.Name = "lblDetect"; + lblDetect.Size = new System.Drawing.Size(42, 15); + lblDetect.TabIndex = 7; + lblDetect.Text = "Bends:"; + // // cboBendDetector - // - cboBendDetector.Size = new System.Drawing.Size(90, 24); + // cboBendDetector.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - cboBendDetector.Font = new System.Drawing.Font("Segoe UI", 9f); + cboBendDetector.Font = new System.Drawing.Font("Segoe UI", 9F); + cboBendDetector.Location = new System.Drawing.Point(405, 6); cboBendDetector.Margin = new System.Windows.Forms.Padding(2, 0, 0, 0); - - detailBar.Controls.AddRange(new System.Windows.Forms.Control[] { - lblQty, numQuantity, lblCust, txtCustomer, - lblDimensions, lblEntityCount, btnSplit, - lblDetect, cboBendDetector - }); - - // + cboBendDetector.Name = "cboBendDetector"; + cboBendDetector.Size = new System.Drawing.Size(90, 23); + cboBendDetector.TabIndex = 8; + // // bottomPanel1 - // - bottomPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; - bottomPanel1.Name = "bottomPanel1"; - bottomPanel1.Size = new System.Drawing.Size(1024, 50); + // bottomPanel1.Controls.Add(cancelButton); bottomPanel1.Controls.Add(acceptButton); - - // + bottomPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; + bottomPanel1.Location = new System.Drawing.Point(0, 670); + bottomPanel1.Name = "bottomPanel1"; + bottomPanel1.Size = new System.Drawing.Size(1024, 50); + bottomPanel1.TabIndex = 3; + // // cancelButton - // + // cancelButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - cancelButton.Location = new System.Drawing.Point(922, 10); - cancelButton.Size = new System.Drawing.Size(90, 28); - cancelButton.Text = "Cancel"; cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - cancelButton.Font = new System.Drawing.Font("Segoe UI", 9f); - - // + cancelButton.Font = new System.Drawing.Font("Segoe UI", 9F); + cancelButton.Location = new System.Drawing.Point(922, 10); + cancelButton.Name = "cancelButton"; + cancelButton.Size = new System.Drawing.Size(90, 28); + cancelButton.TabIndex = 0; + cancelButton.Text = "Cancel"; + // // acceptButton - // + // acceptButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; acceptButton.DialogResult = System.Windows.Forms.DialogResult.OK; - acceptButton.Location = new System.Drawing.Point(826, 10); - acceptButton.Size = new System.Drawing.Size(90, 28); - acceptButton.Text = "Accept"; acceptButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; - acceptButton.Font = new System.Drawing.Font("Segoe UI", 9f); - - // + acceptButton.Font = new System.Drawing.Font("Segoe UI", 9F); + acceptButton.Location = new System.Drawing.Point(826, 10); + acceptButton.Name = "acceptButton"; + acceptButton.Size = new System.Drawing.Size(90, 28); + acceptButton.TabIndex = 1; + acceptButton.Text = "Accept"; + // // CadConverterForm - // Add order: Fill last so it gets remaining space - // + // + AllowDrop = true; AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; ClientSize = new System.Drawing.Size(1024, 720); Controls.Add(entityView1); Controls.Add(detailBar); - Controls.Add(splitterSidebar); - Controls.Add(sidebarPanel); + Controls.Add(sidebarSplit); Controls.Add(bottomPanel1); - Font = new System.Drawing.Font("Segoe UI", 9f); + Font = new System.Drawing.Font("Segoe UI", 9F); MinimizeBox = false; + Name = "CadConverterForm"; ShowIcon = false; ShowInTaskbar = false; StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; Text = "CAD Converter"; - AllowDrop = true; - + WindowState = System.Windows.Forms.FormWindowState.Maximized; + sidebarSplit.Panel1.ResumeLayout(false); + sidebarSplit.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)sidebarSplit).EndInit(); + sidebarSplit.ResumeLayout(false); + detailBar.ResumeLayout(false); + detailBar.PerformLayout(); ((System.ComponentModel.ISupportInitialize)numQuantity).EndInit(); - sidebarPanel.ResumeLayout(false); bottomPanel1.ResumeLayout(false); ResumeLayout(false); } #endregion - private System.Windows.Forms.Panel sidebarPanel; - private System.Windows.Forms.Splitter splitterSidebar; + private System.Windows.Forms.SplitContainer sidebarSplit; private Controls.FileListControl fileList; private Controls.FilterPanel filterPanel; private Controls.EntityView entityView1;