mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-26 22:01:06 -04:00
feat(desktop): size grid columns to their first content, then leave them to the user
Grid columns no longer stretch to fill the control. GridStyle sizes each column once to its header and the first rows shown (capped at 400 px), then the widths are the user's to resize. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3f5d402489
commit
ebecd42433
12 files changed
+106
-33
No files matched your search
@@ -0,0 +1,48 @@
|
||||
using System.Windows.Forms;
|
||||
using OpenNest.Controls;
|
||||
|
||||
namespace OpenNest.WinForms.Tests.Controls;
|
||||
|
||||
public class GridStyleTests
|
||||
{
|
||||
[Fact]
|
||||
public void ColumnsSizeToFirstContentThenKeepTheUsersWidths() => ArchUnitsTests.RunSta(() =>
|
||||
{
|
||||
using var form = new Form { Width = 1200, Height = 400, ShowInTaskbar = false };
|
||||
var grid = GridStyle.Apply(new DataGridView { Dock = DockStyle.Fill, AllowUserToAddRows = false });
|
||||
var shortColumn = new DataGridViewTextBoxColumn { HeaderText = "Qty", Width = 300 };
|
||||
var longColumn = new DataGridViewTextBoxColumn { HeaderText = "Name", Width = 40 };
|
||||
var hugeColumn = new DataGridViewTextBoxColumn { HeaderText = "Notes", Width = 40 };
|
||||
grid.Columns.AddRange(shortColumn, longColumn, hugeColumn);
|
||||
form.Controls.Add(grid);
|
||||
form.Show();
|
||||
Pump(grid);
|
||||
Assert.Equal(300, shortColumn.Width); // no rows yet: nothing is measured
|
||||
|
||||
grid.Rows.Add("1", "A fairly long drawing name", new string('W', 200));
|
||||
Pump(grid);
|
||||
|
||||
Assert.True(shortColumn.Width < 300);
|
||||
Assert.True(longColumn.Width > 40);
|
||||
Assert.Equal(400, hugeColumn.Width);
|
||||
Assert.All(grid.Columns.Cast<DataGridViewColumn>(), column =>
|
||||
{
|
||||
Assert.Equal(DataGridViewAutoSizeColumnMode.None, column.InheritedAutoSizeMode);
|
||||
Assert.True(column.Resizable == DataGridViewTriState.True || column.Resizable == DataGridViewTriState.NotSet);
|
||||
});
|
||||
|
||||
longColumn.Width = 77;
|
||||
grid.Rows.Add("2", new string('X', 80), "");
|
||||
Pump(grid);
|
||||
Assert.Equal(77, longColumn.Width);
|
||||
});
|
||||
|
||||
private static void Pump(Control control)
|
||||
{
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
control.Refresh();
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -199,7 +199,7 @@ namespace OpenNest.Controls
|
||||
//
|
||||
// nestNameColumn
|
||||
//
|
||||
nestNameColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
nestNameColumn.Width = 240;
|
||||
nestNameColumn.HeaderText = "Name";
|
||||
nestNameColumn.MinimumWidth = 160;
|
||||
nestNameColumn.Name = "nestNameColumn";
|
||||
@@ -366,7 +366,7 @@ namespace OpenNest.Controls
|
||||
//
|
||||
// nameColumn
|
||||
//
|
||||
nameColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
nameColumn.Width = 240;
|
||||
nameColumn.HeaderText = "Name";
|
||||
nameColumn.MinimumWidth = 160;
|
||||
nameColumn.Name = "nameColumn";
|
||||
|
||||
@@ -6,11 +6,13 @@ namespace OpenNest.Controls;
|
||||
/// <summary>
|
||||
/// The shared look of every <see cref="DataGridView"/> in the desktop app, taken from the
|
||||
/// database nest browser: flat light headers, faint grid lines, a soft blue selection and
|
||||
/// fixed row heights. Behaviour (editing, selection mode, column sizing) stays with each grid.
|
||||
/// fixed row heights. Columns size once to their first content and are then the user's to
|
||||
/// resize. Other behaviour (editing, selection mode) stays with each grid.
|
||||
/// </summary>
|
||||
public static class GridStyle
|
||||
{
|
||||
public const int RowHeight = 22;
|
||||
private const int MaxInitialColumnWidth = 400;
|
||||
|
||||
private static readonly Color HeaderBackColor = Color.FromArgb(245, 245, 245);
|
||||
private static readonly Color HeaderForeColor = Color.FromArgb(90, 90, 90);
|
||||
@@ -42,6 +44,35 @@ public static class GridStyle
|
||||
grid.RowHeadersDefaultCellStyle.SelectionBackColor = SelectionBackColor;
|
||||
grid.RowHeadersDefaultCellStyle.SelectionForeColor = Color.Black;
|
||||
grid.RowHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||
SizeColumnsOnceToContent(grid);
|
||||
return grid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Widens each column to fit its header and the rows first shown, once, then leaves the
|
||||
/// widths to the user. Columns never stretch to fill the grid.
|
||||
/// </summary>
|
||||
private static void SizeColumnsOnceToContent(DataGridView grid)
|
||||
{
|
||||
// The first paint with rows is the first time they are on screen to be measured. The
|
||||
// empty new-row placeholder does not count: a grid that starts empty keeps its widths
|
||||
// until it has content.
|
||||
void OnPaint(object sender, PaintEventArgs e)
|
||||
{
|
||||
var newRowShown = grid.NewRowIndex >= 0 && grid.Rows[grid.NewRowIndex].Displayed;
|
||||
if (grid.DisplayedRowCount(false) - (newRowShown ? 1 : 0) <= 0)
|
||||
return;
|
||||
grid.Paint -= OnPaint;
|
||||
grid.BeginInvoke(() =>
|
||||
{
|
||||
if (grid.IsDisposed)
|
||||
return;
|
||||
grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
|
||||
foreach (DataGridViewColumn column in grid.Columns)
|
||||
column.Width = System.Math.Min(column.Width, MaxInitialColumnWidth);
|
||||
});
|
||||
}
|
||||
|
||||
grid.Paint += OnPaint;
|
||||
}
|
||||
}
|
||||
@@ -258,14 +258,13 @@ namespace OpenNest.Controls
|
||||
Height = 200,
|
||||
AllowUserToAddRows = true,
|
||||
AllowUserToDeleteRows = true,
|
||||
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
|
||||
RowHeadersWidth = 28,
|
||||
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
|
||||
MultiSelect = true,
|
||||
Margin = new Padding(0, 4, 0, 0),
|
||||
});
|
||||
table.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = field.KeyHeader, FillWeight = 65 });
|
||||
table.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = field.ValueHeader, FillWeight = 35 });
|
||||
table.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = field.KeyHeader, Width = 260 });
|
||||
table.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = field.ValueHeader, Width = 140 });
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ namespace OpenNest.Controls
|
||||
releaseNotesColumn.HeaderText = "Notes";
|
||||
releaseNotesColumn.Name = "releaseNotesColumn";
|
||||
releaseNotesColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
releaseNotesColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
releaseNotesColumn.Width = 300;
|
||||
//
|
||||
// nestsGroup
|
||||
//
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// libraryCustomerColumn
|
||||
//
|
||||
libraryCustomerColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
libraryCustomerColumn.Width = 150;
|
||||
libraryCustomerColumn.HeaderText = "Customer";
|
||||
libraryCustomerColumn.MinimumWidth = 60;
|
||||
libraryCustomerColumn.Name = "libraryCustomerColumn";
|
||||
|
||||
Generated
+7
-9
@@ -270,7 +270,6 @@ namespace OpenNest.Forms
|
||||
//
|
||||
dgvParts.AllowUserToAddRows = false;
|
||||
dgvParts.AllowUserToDeleteRows = false;
|
||||
dgvParts.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
|
||||
dgvParts.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { colItemNum, colFileName, colDescription, colMaterial, colThickness, colQty, colStatus });
|
||||
dgvParts.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
dgvParts.Name = "dgvParts";
|
||||
@@ -288,7 +287,7 @@ namespace OpenNest.Forms
|
||||
// colItemNum
|
||||
//
|
||||
colItemNum.DataPropertyName = "ItemNum";
|
||||
colItemNum.FillWeight = 40F;
|
||||
colItemNum.Width = 60;
|
||||
colItemNum.HeaderText = "Item #";
|
||||
colItemNum.Name = "colItemNum";
|
||||
colItemNum.ReadOnly = true;
|
||||
@@ -297,7 +296,7 @@ namespace OpenNest.Forms
|
||||
// colFileName
|
||||
//
|
||||
colFileName.DataPropertyName = "FileName";
|
||||
colFileName.FillWeight = 120F;
|
||||
colFileName.Width = 180;
|
||||
colFileName.HeaderText = "File Name";
|
||||
colFileName.Name = "colFileName";
|
||||
colFileName.ReadOnly = true;
|
||||
@@ -306,7 +305,7 @@ namespace OpenNest.Forms
|
||||
// colDescription
|
||||
//
|
||||
colDescription.DataPropertyName = "Description";
|
||||
colDescription.FillWeight = 150F;
|
||||
colDescription.Width = 220;
|
||||
colDescription.HeaderText = "Description";
|
||||
colDescription.Name = "colDescription";
|
||||
colDescription.ReadOnly = true;
|
||||
@@ -315,7 +314,7 @@ namespace OpenNest.Forms
|
||||
// colMaterial
|
||||
//
|
||||
colMaterial.DataPropertyName = "Material";
|
||||
colMaterial.FillWeight = 110F;
|
||||
colMaterial.Width = 140;
|
||||
colMaterial.HeaderText = "Material";
|
||||
colMaterial.Name = "colMaterial";
|
||||
colMaterial.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
@@ -327,7 +326,7 @@ namespace OpenNest.Forms
|
||||
thicknessCellStyle.Format = "0.####";
|
||||
colThickness.DataPropertyName = "Thickness";
|
||||
colThickness.DefaultCellStyle = thicknessCellStyle;
|
||||
colThickness.FillWeight = 70F;
|
||||
colThickness.Width = 80;
|
||||
colThickness.HeaderText = "Thickness";
|
||||
colThickness.Name = "colThickness";
|
||||
colThickness.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
@@ -338,7 +337,7 @@ namespace OpenNest.Forms
|
||||
qtyCellStyle.DataSourceNullValue = null;
|
||||
colQty.DataPropertyName = "Qty";
|
||||
colQty.DefaultCellStyle = qtyCellStyle;
|
||||
colQty.FillWeight = 50F;
|
||||
colQty.Width = 60;
|
||||
colQty.HeaderText = "Qty";
|
||||
colQty.Name = "colQty";
|
||||
colQty.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
@@ -346,7 +345,7 @@ namespace OpenNest.Forms
|
||||
// colStatus
|
||||
//
|
||||
colStatus.DataPropertyName = "StatusText";
|
||||
colStatus.FillWeight = 100F;
|
||||
colStatus.Width = 140;
|
||||
colStatus.HeaderText = "Status";
|
||||
colStatus.Name = "colStatus";
|
||||
colStatus.ReadOnly = true;
|
||||
@@ -363,7 +362,6 @@ namespace OpenNest.Forms
|
||||
//
|
||||
dgvGroups.AllowUserToAddRows = false;
|
||||
dgvGroups.AllowUserToDeleteRows = false;
|
||||
dgvGroups.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
|
||||
dgvGroups.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
dgvGroups.Name = "dgvGroups";
|
||||
dgvGroups.RowHeadersVisible = false;
|
||||
|
||||
@@ -212,17 +212,15 @@ internal sealed class CuttingInspectionPanel : UserControl
|
||||
warningGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
HeaderText = name,
|
||||
Width = 48,
|
||||
Width = name is "Issue" or "Status" ? 260 : 48,
|
||||
SortMode = DataGridViewColumnSortMode.NotSortable,
|
||||
AutoSizeMode = name == "Issue" ? DataGridViewAutoSizeColumnMode.Fill : DataGridViewAutoSizeColumnMode.None
|
||||
});
|
||||
foreach (var name in new[] { "Plate", "Part", "Status" })
|
||||
partsGrid.Columns.Add(new DataGridViewTextBoxColumn
|
||||
{
|
||||
HeaderText = name,
|
||||
Width = 48,
|
||||
Width = name is "Issue" or "Status" ? 260 : 48,
|
||||
SortMode = DataGridViewColumnSortMode.NotSortable,
|
||||
AutoSizeMode = name == "Status" ? DataGridViewAutoSizeColumnMode.Fill : DataGridViewAutoSizeColumnMode.None
|
||||
});
|
||||
Padding = new Padding(10);
|
||||
planButton.Click += (_, _) => StartCurrentMode();
|
||||
|
||||
+2
-2
@@ -286,7 +286,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// libraryCustomerColumn
|
||||
//
|
||||
libraryCustomerColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
libraryCustomerColumn.Width = 120;
|
||||
libraryCustomerColumn.HeaderText = "Customer";
|
||||
libraryCustomerColumn.MinimumWidth = 60;
|
||||
libraryCustomerColumn.Name = "libraryCustomerColumn";
|
||||
@@ -476,7 +476,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// warningColumn
|
||||
//
|
||||
warningColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
warningColumn.Width = 200;
|
||||
warningColumn.HeaderText = "Note";
|
||||
warningColumn.MinimumWidth = 60;
|
||||
warningColumn.Name = "warningColumn";
|
||||
|
||||
+6
-7
@@ -190,7 +190,6 @@ namespace OpenNest.Forms
|
||||
drawingGrid.AllowUserToAddRows = false;
|
||||
drawingGrid.AllowUserToDeleteRows = false;
|
||||
drawingGrid.AllowUserToResizeRows = false;
|
||||
drawingGrid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
|
||||
drawingGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
drawingGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { drawingColumn, materialColumn, thicknessColumn, quantityColumn, libraryColumn, noteColumn });
|
||||
drawingGrid.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
@@ -203,21 +202,21 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// drawingColumn
|
||||
//
|
||||
drawingColumn.FillWeight = 130F;
|
||||
drawingColumn.Width = 180;
|
||||
drawingColumn.HeaderText = "Drawing";
|
||||
drawingColumn.Name = "drawingColumn";
|
||||
drawingColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// materialColumn
|
||||
//
|
||||
materialColumn.FillWeight = 80F;
|
||||
materialColumn.Width = 120;
|
||||
materialColumn.HeaderText = "Material";
|
||||
materialColumn.Name = "materialColumn";
|
||||
materialColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// thicknessColumn
|
||||
//
|
||||
thicknessColumn.FillWeight = 50F;
|
||||
thicknessColumn.Width = 80;
|
||||
thicknessColumn.HeaderText = "Thickness";
|
||||
thicknessColumn.Name = "thicknessColumn";
|
||||
thicknessColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
@@ -225,7 +224,7 @@ namespace OpenNest.Forms
|
||||
// quantityColumn
|
||||
//
|
||||
quantityColumn.DefaultCellStyle = new System.Windows.Forms.DataGridViewCellStyle { Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleRight };
|
||||
quantityColumn.FillWeight = 40F;
|
||||
quantityColumn.Width = 60;
|
||||
quantityColumn.HeaderText = "Qty";
|
||||
quantityColumn.Name = "quantityColumn";
|
||||
quantityColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
@@ -233,14 +232,14 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// libraryColumn
|
||||
//
|
||||
libraryColumn.FillWeight = 120F;
|
||||
libraryColumn.Width = 180;
|
||||
libraryColumn.HeaderText = "Drawing library";
|
||||
libraryColumn.Name = "libraryColumn";
|
||||
libraryColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// noteColumn
|
||||
//
|
||||
noteColumn.FillWeight = 120F;
|
||||
noteColumn.Width = 200;
|
||||
noteColumn.HeaderText = "Note";
|
||||
noteColumn.Name = "noteColumn";
|
||||
noteColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenNest.Forms
|
||||
Name = "Name",
|
||||
HeaderText = "Strategy",
|
||||
ReadOnly = true,
|
||||
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||
Width = 220,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -209,7 +209,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// setNameColumn
|
||||
//
|
||||
setNameColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
setNameColumn.Width = 260;
|
||||
setNameColumn.HeaderText = "Set or drawing";
|
||||
setNameColumn.Name = "setNameColumn";
|
||||
setNameColumn.ReadOnly = true;
|
||||
@@ -434,7 +434,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// statusColumn
|
||||
//
|
||||
statusColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
statusColumn.Width = 200;
|
||||
statusColumn.HeaderText = "Status";
|
||||
statusColumn.Name = "statusColumn";
|
||||
statusColumn.ReadOnly = true;
|
||||
|
||||
Reference in new issue
Block a user