diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c1fdadf43d..e71f6ef1c7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,9 +31,6 @@ jobs: - name: Setup msbuild uses: microsoft/setup-msbuild@v1 - - name: Clear package cache # workaround for actions/setup-dotnet#155 - run: dotnet nuget locals all --clear - - name: Build run: dotnet build ${{ env.BuildParameters }} /p:Platform=Windows /t:Package /bl:artifacts/log/Build.Windows.binlog diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000000..6ce97590ac --- /dev/null +++ b/nuget.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/Eto.Gtk/Forms/Controls/GridColumnHandler.cs b/src/Eto.Gtk/Forms/Controls/GridColumnHandler.cs index e7b6426ea3..663ce81a19 100644 --- a/src/Eto.Gtk/Forms/Controls/GridColumnHandler.cs +++ b/src/Eto.Gtk/Forms/Controls/GridColumnHandler.cs @@ -96,8 +96,8 @@ public bool Editable public int Width { get { return Control.Width; } - set - { + set + { autoSize = value == -1; Control.FixedWidth = value; Control.Sizing = autoSize ? Gtk.TreeViewColumnSizing.GrowOnly : Gtk.TreeViewColumnSizing.Fixed; @@ -182,6 +182,19 @@ Gtk.TreeViewColumn IGridColumnHandler.Control { get { return Control; } } + + public bool Expand + { + get => Control.Expand; + set => Control.Expand = value; + } + public TextAlignment HeaderTextAlignment + { + get => GtkConversions.ToEtoAlignment(Control.Alignment); + set => Control.Alignment = value.ToAlignment(); + } + public int MinWidth { get => Control.MinWidth; set => Control.MinWidth = value; } + public int MaxWidth { get => Control.MaxWidth; set => Control.MaxWidth = value; } } } diff --git a/src/Eto.Gtk/Forms/Controls/GridHandler.cs b/src/Eto.Gtk/Forms/Controls/GridHandler.cs index 4b4a59bd67..708612e082 100644 --- a/src/Eto.Gtk/Forms/Controls/GridHandler.cs +++ b/src/Eto.Gtk/Forms/Controls/GridHandler.cs @@ -34,11 +34,56 @@ public abstract class GridHandler : GtkControl Tree; + class EtoScrolledWindow : Gtk.ScrolledWindow + { + WeakReference handler; + public IGtkControl Handler { get => handler?.Target as IGtkControl; set => handler = new WeakReference(value); } + +#if GTKCORE + + protected override void OnGetPreferredWidth(out int minimum_width, out int natural_width) + { + base.OnGetPreferredWidth(out minimum_width, out natural_width); + + var h = Handler; + if (h != null) + { + var size = h.UserPreferredSize; + if (size.Width >= 0) + { + natural_width = Math.Min(size.Width, natural_width); + minimum_width = Math.Min(size.Width, minimum_width); + } + } + } + + protected override void OnGetPreferredHeight(out int minimum_height, out int natural_height) + { + base.OnGetPreferredHeight(out minimum_height, out natural_height); + var h = Handler; + if (h != null) + { + var size = h.UserPreferredSize; + if (size.Height >= 0) + { + natural_height = Math.Min(size.Height, natural_height); + minimum_height = Math.Min(size.Height, minimum_height); + } + } + } +#endif + } + protected GridHandler() { - Control = new Gtk.ScrolledWindow + Control = new EtoScrolledWindow { - ShadowType = Gtk.ShadowType.In + Handler = this, + ShadowType = Gtk.ShadowType.In, +#if GTKCORE + PropagateNaturalHeight = true, + PropagateNaturalWidth = true +#endif }; } diff --git a/src/Eto.Gtk/GtkConversions.cs b/src/Eto.Gtk/GtkConversions.cs index d804f940d9..c518bef702 100644 --- a/src/Eto.Gtk/GtkConversions.cs +++ b/src/Eto.Gtk/GtkConversions.cs @@ -691,6 +691,17 @@ public static Pango.Alignment ToPango(this TextAlignment alignment) } } + public static TextAlignment ToEtoAlignment(float align) + { + if (align == 0f) + return TextAlignment.Left; + else if (align == 0.5f) + return TextAlignment.Center; + else if (align == 1f) + return TextAlignment.Right; + return TextAlignment.Left; + } + public static float ToAlignment(this TextAlignment alignment) { switch (alignment) diff --git a/src/Eto.Mac/Forms/Controls/GridColumnHandler.cs b/src/Eto.Mac/Forms/Controls/GridColumnHandler.cs index 6e86301e1e..26b26773f6 100644 --- a/src/Eto.Mac/Forms/Controls/GridColumnHandler.cs +++ b/src/Eto.Mac/Forms/Controls/GridColumnHandler.cs @@ -64,7 +64,7 @@ public interface IDataViewHandler bool IsCancellingEdit { get; } } - public interface IDataColumnHandler + public interface IDataColumnHandler : GridColumn.IHandler { void Setup(IDataViewHandler handler, int column); @@ -72,7 +72,7 @@ public interface IDataColumnHandler void SetObjectValue(object dataItem, NSObject val); - GridColumn Widget { get; } + new GridColumn Widget { get; } IDataViewHandler DataViewHandler { get; } @@ -81,6 +81,7 @@ public interface IDataColumnHandler void EnabledChanged(bool value); nfloat GetPreferredWidth(NSRange? range = null); + void SizeToFit(); } public class GridColumnHandler : MacObject, GridColumn.IHandler, IDataColumnHandler @@ -112,6 +113,7 @@ protected override void Initialize() HeaderText = string.Empty; Editable = false; AutoSize = true; + Control.Width = Control.MinWidth; DataCell = new TextBoxCell(); base.Initialize(); } @@ -119,7 +121,10 @@ protected override void Initialize() public void AutoSizeColumn(NSRange rowRange, bool force = false) { var handler = DataViewHandler; - if (AutoSize && handler != null) + if (handler == null) + return; + + if (AutoSize) { var width = GetPreferredWidth(rowRange); if (force || width > Control.Width) @@ -131,9 +136,17 @@ public nfloat GetPreferredWidth(NSRange? range = null) { var handler = DataViewHandler; nfloat width = 0; + + if (!AutoSize) + return Width; + var outlineView = handler.Table as NSOutlineView; if (handler.ShowHeader) + { width = (nfloat)Math.Max(Control.HeaderCell.CellSizeForBounds(new CGRect(0, 0, int.MaxValue, int.MaxValue)).Width, width); + if (outlineView != null && Column == 0) + width += (float)outlineView.IndentationPerLevel; + } if (dataCell != null) { @@ -217,9 +230,15 @@ public int Width { get => (int)Math.Ceiling(Control.Width) + 3; set - { + { AutoSize = value == -1; Control.Width = Math.Max(0, value - 3); + + var table = Control.TableView; + if (DataViewHandler != null && DataViewHandler.Loaded && table != null) + { + table.SizeToFit(); + } } } @@ -290,6 +309,25 @@ public Font Font } } + public bool Expand + { + get => Control.ResizingMask.HasFlag(NSTableColumnResizing.Autoresizing); + set + { + if (value) + Control.ResizingMask |= NSTableColumnResizing.Autoresizing; + else + Control.ResizingMask &= ~NSTableColumnResizing.Autoresizing; + } + } + public TextAlignment HeaderTextAlignment + { + get => Control.HeaderCell.Alignment.ToEto(); + set => Control.HeaderCell.Alignment = value.ToNS(); + } + public int MinWidth { get => (int)Control.MinWidth; set => Control.MinWidth = value; } + public int MaxWidth { get => (int)Control.MaxWidth; set => Control.MaxWidth = value; } + public void EnabledChanged(bool value) { if (dataCell != null) @@ -298,6 +336,8 @@ public void EnabledChanged(bool value) cellHandler.EnabledChanged(value); } } + + public void SizeToFit() => Control.SizeToFit(); } } diff --git a/src/Eto.Mac/Forms/Controls/GridHandler.cs b/src/Eto.Mac/Forms/Controls/GridHandler.cs index f8a66d4347..8383538344 100644 --- a/src/Eto.Mac/Forms/Controls/GridHandler.cs +++ b/src/Eto.Mac/Forms/Controls/GridHandler.cs @@ -51,7 +51,7 @@ public interface IGridHandler : IMacViewHandler NSTableView Table { get; } - bool AutoSizeColumns(bool force); + bool AutoSizeColumns(bool force, bool forceNewSize = false); void PerformLayout(); } @@ -72,7 +72,7 @@ public override void SetFrameSize(CGSize newSize) if (!autoSized) { - autoSized = h.AutoSizeColumns(false); + autoSized = h.AutoSizeColumns(false, true); } h.OnSizeChanged(EventArgs.Empty); h.Callback.OnSizeChanged(h.Widget, EventArgs.Empty); @@ -345,18 +345,14 @@ public override void OnLoadComplete(EventArgs e) base.OnLoadComplete(e); UpdateColumns(); - if (!Widget.Properties.Get(GridHandler.ScrolledToRow_Key)) - // Yosemite bug: hides first row when DataStore is set before control is visible - Control.ScrollRowToVisible(0); - else - Widget.Properties.Remove(GridHandler.ScrolledToRow_Key); + var row = Widget.Properties.Get(GridHandler.ScrolledToRow_Key, 0); + // Yosemite bug: hides first row when DataStore is set before control is visible, so we always call this + Control.ScrollRowToVisible(row); } NSRange autoSizeRange; - public bool AutoSizeColumns(bool force) => AutoSizeColumns(force, false); - - public bool AutoSizeColumns(bool force, bool forceNewSize) + public bool AutoSizeColumns(bool force, bool forceNewSize = false) { if (Widget.Loaded) { @@ -434,8 +430,13 @@ public virtual IEnumerable SelectedRows UnselectAll(); if (value != null) { - var indexes = NSIndexSet.FromArray(value.ToArray()); - Control.SelectRows(indexes, AllowMultipleSelection); + var rows = value.ToArray(); + if (rows.Length > 0) + { + var indexes = NSIndexSet.FromArray(rows); + Control.SelectRows(indexes, AllowMultipleSelection); + ScrollToRow(rows[0]); + } } SuppressSelectionChanged--; if (SuppressSelectionChanged == 0) @@ -547,12 +548,19 @@ public CGRect GetVisibleRect() protected override SizeF GetNaturalSize(SizeF availableSize) { - var width = Widget.Columns.Sum(r => r.Width); + EnsureAutoSizedColumns(); + var width = (int)ColumnHandlers.Sum(r => r.Width); if (width == 0) width = 100; - var height = RowHeight * 4; + if (Border != BorderType.None) width += 4; + + width -= 2; // it's okay for the last divider to be hidden + + var height = (RowHeight + 2) * RowCount; + if (ShowHeader) + height += 2 + (int)Control.HeaderView.Frame.Height; return new Size(width, height); } @@ -563,9 +571,10 @@ public void OnCellFormatting(GridCellFormatEventArgs args) public void ScrollToRow(int row) { - Control.ScrollRowToVisible(row); if (!Widget.Loaded) - Widget.Properties[GridHandler.ScrolledToRow_Key] = true; + Widget.Properties[GridHandler.ScrolledToRow_Key] = row; + else + Control.ScrollRowToVisible(row); } public bool Loaded => Widget.Loaded; @@ -629,14 +638,23 @@ void IDataViewHandler.OnCellEdited(GridViewCellEventArgs e) bool hasAutoSizedColumns; protected void ResetAutoSizedColumns() => hasAutoSizedColumns = false; - public void PerformLayout() + void EnsureAutoSizedColumns() { - if (!hasAutoSizedColumns && Widget.Loaded && !Table.VisibleRect().IsNull()) + if (!hasAutoSizedColumns && !Table.VisibleRect().IsEmpty) { AutoSizeColumns(true, true); + var width = ColumnHandlers.Sum(r => r.Width); + if (width < Table.Frame.Width && Widget.Columns.Any(r => r.Expand)) + { + Control.SizeToFit(); + } hasAutoSizedColumns = true; } + } + public void PerformLayout() + { + EnsureAutoSizedColumns(); } public bool IsEditing => Widget.Properties.Get(GridHandler.IsEditing_Key, Control.EditedRow != -1 && Control.EditedColumn != -1); @@ -676,6 +694,21 @@ public override void DoDragDrop(DataObject data, DragEffects allowedAction, Imag base.DoDragDrop(data, allowedAction, image, origin); } } + + protected void ColumnDidResize(NSNotification notification) + { + if (!IsAutoSizingColumns && Widget.Loaded && hasAutoSizedColumns) + { + // when the user resizes the column, don't autosize anymore when data/scroll changes + var column = notification.UserInfo["NSTableColumn"] as NSTableColumn; + if (column != null) + { + var colHandler = GetColumn(column); + colHandler.AutoSize = false; + InvalidateMeasure(); + } + } + } } } diff --git a/src/Eto.Mac/Forms/Controls/GridViewHandler.cs b/src/Eto.Mac/Forms/Controls/GridViewHandler.cs index ab540ec6c1..ffc3d8f843 100644 --- a/src/Eto.Mac/Forms/Controls/GridViewHandler.cs +++ b/src/Eto.Mac/Forms/Controls/GridViewHandler.cs @@ -135,7 +135,7 @@ public EtoTableView(GridViewHandler handler) FocusRingType = NSFocusRingType.None; DataSource = new EtoTableViewDataSource { Handler = handler }; Delegate = new EtoTableDelegate { Handler = handler }; - ColumnAutoresizingStyle = NSTableViewColumnAutoresizingStyle.None; + ColumnAutoresizingStyle = NSTableViewColumnAutoresizingStyle.Uniform; SetDraggingSourceOperationMask(NSDragOperation.All, true); SetDraggingSourceOperationMask(NSDragOperation.All, false); } @@ -416,16 +416,7 @@ public override void DidClickTableColumn(NSTableView tableView, NSTableColumn ta public override void ColumnDidResize(NSNotification notification) { - if (!Handler.IsAutoSizingColumns) - { - // when the user resizes the column, don't autosize anymore when data/scroll changes - var column = notification.UserInfo["NSTableColumn"] as NSTableColumn; - if (column != null) - { - var colHandler = Handler.GetColumn(column); - colHandler.AutoSize = false; - } - } + Handler?.ColumnDidResize(notification); } public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row) diff --git a/src/Eto.Mac/Forms/Controls/TreeGridViewHandler.cs b/src/Eto.Mac/Forms/Controls/TreeGridViewHandler.cs index 34c0d580da..89bff6dedb 100644 --- a/src/Eto.Mac/Forms/Controls/TreeGridViewHandler.cs +++ b/src/Eto.Mac/Forms/Controls/TreeGridViewHandler.cs @@ -275,16 +275,7 @@ public override void DidClickTableColumn(NSOutlineView outlineView, NSTableColum public override void ColumnDidResize(NSNotification notification) { - if (!Handler.IsAutoSizingColumns) - { - // when the user resizes the column, don't autosize anymore when data/scroll changes - var column = notification.UserInfo["NSTableColumn"] as NSTableColumn; - if (column != null) - { - var colHandler = Handler.GetColumn(column); - colHandler.AutoSize = false; - } - } + Handler?.ColumnDidResize(notification); } public override NSView GetView(NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) @@ -340,6 +331,9 @@ public override void SetObjectValue(NSOutlineView outlineView, NSObject theObjec public override bool ItemExpandable(NSOutlineView outlineView, NSObject item) { + if (item == null) + return true; + var myitem = Handler.GetEtoItem(item); return myitem != null && myitem.Expandable; } @@ -633,12 +627,13 @@ public override void MouseDown(NSEvent theEvent) public EtoOutlineView(TreeGridViewHandler handler) { Delegate = new EtoOutlineDelegate { Handler = handler }; + DataSource = new EtoDataSource { Handler = handler }; //HeaderView = null, AutoresizesOutlineColumn = false; //AllowsColumnResizing = false, AllowsColumnReordering = false; FocusRingType = NSFocusRingType.None; - ColumnAutoresizingStyle = NSTableViewColumnAutoresizingStyle.None; + ColumnAutoresizingStyle = NSTableViewColumnAutoresizingStyle.Uniform; SetDraggingSourceOperationMask(NSDragOperation.All, true); SetDraggingSourceOperationMask(NSDragOperation.All, false); } @@ -662,6 +657,10 @@ public override void AttachEvent(string id) { switch (id) { + case Grid.CellEditingEvent: + case Grid.CellEditedEvent: + // handled by delegate + break; case TreeGridView.ActivatedEvent: Widget.KeyDown += (sender, e) => { @@ -714,18 +713,18 @@ public ITreeGridStore DataStore get { return store; } set { + Control.BeginUpdates(); store = value; topitems.Clear(); cachedItems.Clear(); - if (Control.DataSource == null) - Control.DataSource = new EtoDataSource { Handler = this }; - else - Control.ReloadData(); + Control.ReloadData(); suppressExpandCollapseEvents++; ExpandItems(null); suppressExpandCollapseEvents--; - if (Widget.Loaded) - AutoSizeColumns(true); + Control.EndUpdates(); + + ResetAutoSizedColumns(); + InvalidateMeasure(); } } @@ -830,24 +829,25 @@ public ITreeGridItem SelectedItem Control.DeselectAll(Control); else { - EtoTreeItem myitem; if (cachedItems.TryGetValue(value, out myitem)) { var cachedRow = Control.RowForItem(myitem); if (cachedRow >= 0) { - Control.ScrollRowToVisible(cachedRow); Control.SelectRow((nnint)cachedRow, false); + ScrollToRow((int)cachedRow); return; } } + Control.BeginUpdates(); var row = ExpandToItem(value); + Control.EndUpdates(); if (row != null) { - Control.ScrollRowToVisible(row.Value); Control.SelectRow((nnint)row.Value, false); + ScrollToRow((int)row.Value); } } } @@ -855,11 +855,15 @@ public ITreeGridItem SelectedItem void ExpandItems(NSObject parent) { - var ds = (EtoDataSource)Control.DataSource; - var count = ds.GetChildrenCount(Control, parent); + int count; + if (parent == null) + count = store?.Count ?? 0; + else + count = ((parent as EtoTreeItem)?.Item as ITreeGridStore)?.Count ?? 0; + for (int i = 0; i < count; i++) { - var item = ds.GetChild(Control, i, parent) as EtoTreeItem; + var item = Control.GetChild(i, parent) as EtoTreeItem; if (item != null && item.Item.Expanded && !Control.IsItemExpanded(item)) { Control.ExpandItem(item); @@ -894,6 +898,7 @@ public void ReloadData() if (!Control.IsFlipped) loc.Y = Control.Frame.Height - contentView.Frame.Height - loc.Y; + Control.BeginUpdates(); topitems.Clear(); cachedItems.Clear(); Control.ReloadData(); @@ -916,6 +921,7 @@ public void ReloadData() else isSelectionChanged = true; } + Control.EndUpdates(); ScrollView.ReflectScrolledClipView(contentView); suppressExpandCollapseEvents--; diff --git a/src/Eto.WinForms/Forms/Controls/GridColumnHandler.cs b/src/Eto.WinForms/Forms/Controls/GridColumnHandler.cs index 83fc642d47..81ad4ea024 100644 --- a/src/Eto.WinForms/Forms/Controls/GridColumnHandler.cs +++ b/src/Eto.WinForms/Forms/Controls/GridColumnHandler.cs @@ -3,6 +3,7 @@ using Eto.Forms; using Eto.WinForms.Forms.Cells; using System; +using System.Diagnostics; namespace Eto.WinForms.Forms.Controls { @@ -10,7 +11,6 @@ namespace Eto.WinForms.Forms.Controls public class GridColumnHandler : WidgetHandler, GridColumn.IHandler, ICellConfigHandler { Cell dataCell; - bool autosize; public IGridHandler GridHandler { get; private set; } @@ -19,10 +19,15 @@ public GridColumnHandler() Control = new swf.DataGridViewColumn(); DataCell = new TextBoxCell(); Editable = false; - AutoSize = true; Resizable = true; } + protected override void Initialize() + { + base.Initialize(); + SetAutoSizeMode(); + } + public string HeaderText { get { return Control.HeaderText; } @@ -41,13 +46,15 @@ public bool Sortable set { Control.SortMode = (value) ? swf.DataGridViewColumnSortMode.Programmatic : swf.DataGridViewColumnSortMode.NotSortable; } } + static readonly object AutoSize_Key = new object(); + public bool AutoSize { - get { return autosize; } + get => Widget.Properties.Get(AutoSize_Key, true); set { - autosize = value; - Control.AutoSizeMode = (value) ? swf.DataGridViewAutoSizeColumnMode.NotSet : swf.DataGridViewAutoSizeColumnMode.None; + if (Widget.Properties.TrySet(AutoSize_Key, value, true)) + SetAutoSizeMode(); } } @@ -92,6 +99,45 @@ public bool Visible public swf.DataGridViewColumn Column => Control; + static readonly object Expand_Key = new object(); + + public bool Expand + { + get => Widget.Properties.Get(Expand_Key); + set + { + if (Widget.Properties.TrySet(Expand_Key, value)) + { + SetAutoSizeMode(); + } + } + } + + void SetAutoSizeMode() + { + if (Expand) + Control.AutoSizeMode = swf.DataGridViewAutoSizeColumnMode.Fill; + else if (AutoSize) + Control.AutoSizeMode = swf.DataGridViewAutoSizeColumnMode.DisplayedCells; + else + Control.AutoSizeMode = swf.DataGridViewAutoSizeColumnMode.None; + } + + public TextAlignment HeaderTextAlignment + { + get => Control.HeaderCell.Style.Alignment.ToEtoTextAlignment(); + set => Control.HeaderCell.Style.Alignment = value.ToSWFGridViewContentAlignment(); + } + public int MinWidth { get => Control.MinimumWidth; set => Control.MinimumWidth = value; } + public int MaxWidth + { + get => int.MaxValue; + set + { + Debug.WriteLine("GridColumn.MaxWidth is not supported in WinForms"); + } + } + public void SetCellValue(object dataItem, object value) { if (dataCell != null) diff --git a/src/Eto.WinForms/Forms/Controls/GridHandler.cs b/src/Eto.WinForms/Forms/Controls/GridHandler.cs index c2abfc4272..5cf880e703 100644 --- a/src/Eto.WinForms/Forms/Controls/GridHandler.cs +++ b/src/Eto.WinForms/Forms/Controls/GridHandler.cs @@ -20,8 +20,8 @@ public interface IGridHandler } public abstract class GridHandler : WindowsControl, Grid.IHandler, IGridHandler - where TWidget: Grid - where TCallback: Grid.ICallback + where TWidget : Grid + where TCallback : Grid.ICallback { ColumnCollection columns; bool isFirstSelection = true; @@ -42,16 +42,51 @@ class EtoDataGridView : swf.DataGridView public EtoDataGridView() { DoubleBuffered = true; } + sd.Size GetSizeWithData(sd.Size proposedSize) + { + int width = RowHeadersWidth; + int height = 0; + if (ColumnHeadersVisible) + height += ColumnHeadersHeight; + + if (BorderStyle == swf.BorderStyle.Fixed3D) + { + width += 4; + height += 4; + } + else if (BorderStyle == swf.BorderStyle.FixedSingle) + { + width += 2; + height += 2; + } + + height += RowCount * (RowTemplate.Height + RowTemplate.DividerHeight); + + for (int i = 0; i < ColumnCount; i++) + { + var col = Columns[i]; + if (col.Visible) + { + width += col.GetPreferredWidth(swf.DataGridViewAutoSizeColumnMode.DisplayedCells, true); + } + } + + if (proposedSize.Height > 0 && proposedSize.Height < height) + width += swf.SystemInformation.VerticalScrollBarWidth; + + return new sd.Size(width, height); + } + public override sd.Size GetPreferredSize(sd.Size proposedSize) { - var size = base.GetPreferredSize(proposedSize); + var size = GetSizeWithData(proposedSize); + var def = Handler.UserPreferredSize; if (def.Width >= 0) size.Width = def.Width; if (def.Height >= 0) size.Height = def.Height; - else - size.Height = Math.Min(size.Height, 100); + return size; } @@ -134,8 +169,8 @@ private void Widget_MouseDown(object sender, MouseEventArgs e) } } else if (e.Modifiers == Keys.Control - && hitTest.RowIndex >= 0 - && Control.SelectedRows.Count == 1 + && hitTest.RowIndex >= 0 + && Control.SelectedRows.Count == 1 && Control.SelectedRows[0].Index == hitTest.RowIndex) { // don't allow user to deselect all items @@ -390,7 +425,7 @@ public int RowHeight { get { return Control.RowTemplate.Height; } set - { + { Control.RowTemplate.Height = value; foreach (swf.DataGridViewRow row in Control.Rows) { diff --git a/src/Eto.WinForms/Forms/Controls/LabelHandler.cs b/src/Eto.WinForms/Forms/Controls/LabelHandler.cs index 50931d0d73..70573fbab0 100644 --- a/src/Eto.WinForms/Forms/Controls/LabelHandler.cs +++ b/src/Eto.WinForms/Forms/Controls/LabelHandler.cs @@ -111,7 +111,7 @@ public override sd.Size GetPreferredSize(sd.Size proposedSize) var bordersAndPadding = Padding.Size; if (proposedSize.Width <= 1) proposedSize.Width = int.MaxValue; - else if (Width > 1) + else if (IsHandleCreated && Width > 1) proposedSize.Width = Width; sd.SizeF size; diff --git a/src/Eto.WinForms/Forms/Controls/TextStepperHandler.cs b/src/Eto.WinForms/Forms/Controls/TextStepperHandler.cs index d9737ff8ad..03b67367de 100644 --- a/src/Eto.WinForms/Forms/Controls/TextStepperHandler.cs +++ b/src/Eto.WinForms/Forms/Controls/TextStepperHandler.cs @@ -17,9 +17,16 @@ public class EtoUpDown : swf.UpDownBase public event EventHandler DownButtonClicked; public event EventHandler UpButtonClicked; +#if NETCOREAPP + static FieldInfo DefaultButtonsWidthField = typeof(swf.UpDownBase).GetField("_defaultButtonsWidth", BindingFlags.Static | BindingFlags.NonPublic); + static FieldInfo TextBoxField = typeof(swf.UpDownBase).GetField("_upDownEdit", BindingFlags.Instance | BindingFlags.NonPublic); + static FieldInfo UpDownButtonsField = typeof(swf.UpDownBase).GetField("_upDownButtons", BindingFlags.Instance | BindingFlags.NonPublic); +#else static FieldInfo DefaultButtonsWidthField = typeof(swf.UpDownBase).GetField("defaultButtonsWidth", BindingFlags.Static | BindingFlags.NonPublic); static FieldInfo TextBoxField = typeof(swf.UpDownBase).GetField("upDownEdit", BindingFlags.Instance | BindingFlags.NonPublic); static FieldInfo UpDownButtonsField = typeof(swf.UpDownBase).GetField("upDownButtons", BindingFlags.Instance | BindingFlags.NonPublic); +#endif + public swf.TextBox TextBox => TextBoxField?.GetValue(this) as swf.TextBox; @@ -59,7 +66,7 @@ public override sd.Size GetPreferredSize(sd.Size proposedSize) protected override void OnLayout(swf.LayoutEventArgs e) { - if (!UpDownButtons.Visible) + if (UpDownButtons != null && !UpDownButtons.Visible) { var oldVal = DefaultButtonsWidth; DefaultButtonsWidth = 0; diff --git a/src/Eto.WinForms/WinConversions.cs b/src/Eto.WinForms/WinConversions.cs index 96fd6e57d1..411afb43d9 100644 --- a/src/Eto.WinForms/WinConversions.cs +++ b/src/Eto.WinForms/WinConversions.cs @@ -603,6 +603,47 @@ public static TextAlignment ToEtoTextAlignment(this swf.DataGridViewContentAlign } } + public static swf.DataGridViewContentAlignment ToSWFGridViewContentAlignment(this TextAlignment alignment, VerticalAlignment vertical = VerticalAlignment.Center) + { + switch (alignment) + { + default: + case TextAlignment.Left: + switch (vertical) + { + case VerticalAlignment.Top: + return swf.DataGridViewContentAlignment.TopLeft; + default: + case VerticalAlignment.Center: + return swf.DataGridViewContentAlignment.MiddleLeft; + case VerticalAlignment.Bottom: + return swf.DataGridViewContentAlignment.BottomLeft; + } + case TextAlignment.Center: + switch (vertical) + { + case VerticalAlignment.Top: + return swf.DataGridViewContentAlignment.TopCenter; + default: + case VerticalAlignment.Center: + return swf.DataGridViewContentAlignment.MiddleCenter; + case VerticalAlignment.Bottom: + return swf.DataGridViewContentAlignment.BottomCenter; + } + case TextAlignment.Right: + switch (vertical) + { + case VerticalAlignment.Top: + return swf.DataGridViewContentAlignment.TopRight; + default: + case VerticalAlignment.Center: + return swf.DataGridViewContentAlignment.MiddleRight; + case VerticalAlignment.Bottom: + return swf.DataGridViewContentAlignment.BottomRight; + } + } + } + public static VerticalAlignment ToEtoVerticalAlignment(this swf.DataGridViewContentAlignment existing) { switch (existing) diff --git a/src/Eto.Wpf/Forms/Controls/GridColumnHandler.cs b/src/Eto.Wpf/Forms/Controls/GridColumnHandler.cs index 0c7550f61b..7a74a6324f 100755 --- a/src/Eto.Wpf/Forms/Controls/GridColumnHandler.cs +++ b/src/Eto.Wpf/Forms/Controls/GridColumnHandler.cs @@ -10,14 +10,16 @@ public interface IGridHandler Grid Widget { get; } bool Loaded { get; } bool DisableAutoScrollToSelection { get; } - sw.FrameworkElement SetupCell (IGridColumnHandler column, sw.FrameworkElement defaultContent, swc.DataGridCell cell); - void FormatCell (IGridColumnHandler column, ICellHandler cell, sw.FrameworkElement element, swc.DataGridCell gridcell, object dataItem); + sw.FrameworkElement SetupCell(IGridColumnHandler column, sw.FrameworkElement defaultContent, swc.DataGridCell cell); + void FormatCell(IGridColumnHandler column, ICellHandler cell, sw.FrameworkElement element, swc.DataGridCell gridcell, object dataItem); void CellEdited(int row, swc.DataGridColumn dataGridColumn, object dataItem); } public interface IGridColumnHandler : GridColumn.IHandler { swc.DataGridColumn Control { get; } + + void OnLoad(); } @@ -38,7 +40,7 @@ protected override void Initialize() public string HeaderText { get { return Control.Header as string; } - set { Control.Header = value; } + set { Control.Header = value; } } public bool Resizable @@ -53,27 +55,90 @@ public bool Sortable set { Control.CanUserSort = value; } } + static readonly object AutoSize_Key = new object(); + static readonly object Expand_Key = new object(); + static readonly object Width_Key = new object(); + + bool IsGridLoaded => GridHandler?.Loaded == true; + public bool AutoSize { - get { return Control.Width.IsAuto; } - set { Control.Width = value ? new swc.DataGridLength(1, swc.DataGridLengthUnitType.Auto) : new swc.DataGridLength(100); } + get + { + if (IsGridLoaded) + return Expand ? Widget.Properties.Get(AutoSize_Key, true) : Control.Width.IsAuto; + return Widget.Properties.Get(AutoSize_Key, true); + } + set + { + if (value && IsGridLoaded && !Expand) + { + Control.Width = new swc.DataGridLength(1, swc.DataGridLengthUnitType.Auto); + Widget.Properties.Set(AutoSize_Key, value, true); + } + else if (Widget.Properties.TrySet(AutoSize_Key, value, true)) + SetWidth(); + } + } + + public bool Expand + { + get => Widget.Properties.Get(Expand_Key); + set + { + if (Widget.Properties.TrySet(Expand_Key, value)) + SetWidth(); + } } public int Width { get { - if (GridHandler?.Loaded == true) + if (IsGridLoaded) return (int)Control.ActualWidth; - return (int)Control.Width.Value; + return Widget.Properties.Get(Width_Key, -1); } set { - Control.Width = new swc.DataGridLength (value); + if (value == -1) + { + Widget.Properties.Set(Width_Key, value, -1); + AutoSize = true; + return; + } + + Widget.Properties.Set(AutoSize_Key, false, true); + if (IsGridLoaded) + { + Control.Width = new swc.DataGridLength(value); + Widget.Properties.Set(Width_Key, value, -1); + } + else if (Widget.Properties.TrySet(Width_Key, value, -1)) + SetWidth(); + } + } + + void SetWidth() + { + if (Expand) + { + if (AutoSize && !IsGridLoaded) + Control.Width = new swc.DataGridLength(1.0, swc.DataGridLengthUnitType.Auto); + else + Control.Width = new swc.DataGridLength(1.0, swc.DataGridLengthUnitType.Star); + } + else if (AutoSize) + { + Control.Width = new swc.DataGridLength(1.0, swc.DataGridLengthUnitType.Auto); + } + else + { + Control.Width = Width; } } - void CopyValues (Cell oldCell) + void CopyValues(Cell oldCell) { if (oldCell == null) return; var handler = (ICellHandler)oldCell.Handler; @@ -98,7 +163,7 @@ public Cell DataCell var cellHandler = (ICellHandler)dataCell.Handler; cellHandler.ContainerHandler = this; Control = cellHandler.Control; - CopyValues (oldCell); + CopyValues(oldCell); } } @@ -114,20 +179,20 @@ public bool Visible set { Control.Visibility = (value) ? sw.Visibility.Visible : sw.Visibility.Hidden; } } - public void Setup (IGridHandler gridHandler) + public void Setup(IGridHandler gridHandler) { GridHandler = gridHandler; } - public sw.FrameworkElement SetupCell (ICellHandler handler, sw.FrameworkElement defaultContent, swc.DataGridCell cell) + public sw.FrameworkElement SetupCell(ICellHandler handler, sw.FrameworkElement defaultContent, swc.DataGridCell cell) { return GridHandler != null ? GridHandler.SetupCell(this, defaultContent, cell) : defaultContent; } - public void FormatCell (ICellHandler cell, sw.FrameworkElement element, swc.DataGridCell gridcell, object dataItem) + public void FormatCell(ICellHandler cell, sw.FrameworkElement element, swc.DataGridCell gridcell, object dataItem) { if (GridHandler != null) - GridHandler.FormatCell (this, cell, element, gridcell, dataItem); + GridHandler.FormatCell(this, cell, element, gridcell, dataItem); } internal ICellHandler DataCellHandler => DataCell?.Handler as ICellHandler; @@ -146,6 +211,41 @@ internal void OnMouseUp(GridCellMouseEventArgs args, sw.DependencyObject hitTest public Grid Grid => GridHandler?.Widget; + void IGridColumnHandler.OnLoad() + { + if (Expand && AutoSize) + SetWidth(); + } + + static readonly object HeaderTextAlignment_Key = new object(); + + public TextAlignment HeaderTextAlignment + { + get => Widget.Properties.Get(HeaderTextAlignment_Key); + set + { + if (Widget.Properties.TrySet(HeaderTextAlignment_Key, value)) + { + if (value == TextAlignment.Left) + Control.HeaderStyle = null; + else + { + var style = new sw.Style(); + style.TargetType = typeof(swc.Primitives.DataGridColumnHeader); + style.Setters.Add(new sw.Setter(swc.Primitives.DataGridColumnHeader.HorizontalContentAlignmentProperty, value.ToWpf())); + Control.HeaderStyle = style; + } + } + } + } + + public int MinWidth { get => (int)Control.MinWidth; set => Control.MinWidth = value; } + public int MaxWidth + { + get => double.IsInfinity(Control.MaxWidth) ? int.MaxValue : (int)Control.MaxWidth; + set => Control.MaxWidth = value == int.MaxValue ? double.PositiveInfinity : value; + } + public void CellEdited(ICellHandler cell, sw.FrameworkElement element) { var dataCell = element.GetVisualParent(); diff --git a/src/Eto.Wpf/Forms/Controls/GridHandler.cs b/src/Eto.Wpf/Forms/Controls/GridHandler.cs index f3e6f5d7fe..50543fc9ca 100755 --- a/src/Eto.Wpf/Forms/Controls/GridHandler.cs +++ b/src/Eto.Wpf/Forms/Controls/GridHandler.cs @@ -13,6 +13,7 @@ using Eto.Drawing; using Eto.Wpf.Drawing; using Eto.Wpf.CustomControls.TreeGridView; +using System.Windows; namespace Eto.Wpf.Forms.Controls { @@ -277,6 +278,20 @@ protected override void Initialize() // the cell is selected. HandleEvent(Eto.Forms.Control.MouseDownEvent); HandleEvent(Eto.Forms.Control.MouseUpEvent); + + Control.Loaded += Control_Loaded; + } + + private void Control_Loaded(object sender, RoutedEventArgs e) + { + // expanded columns don't get autosized, so we flip to star width after they are auto sized. + foreach (var col in Widget.Columns) + { + if (col.Handler is IGridColumnHandler columnHandler) + { + columnHandler.OnLoad(); + } + } } protected class ColumnCollection : EnumerableChangedHandler diff --git a/src/Eto/Forms/Controls/GridColumn.cs b/src/Eto/Forms/Controls/GridColumn.cs index 9d5e151910..8027cbad6a 100644 --- a/src/Eto/Forms/Controls/GridColumn.cs +++ b/src/Eto/Forms/Controls/GridColumn.cs @@ -103,6 +103,49 @@ public bool Visible set { Handler.Visible = value; } } + /// + /// Gets or sets a value indicating whether this column should expand to fill the available space in the Grid + /// + /// + /// If more than one column has this set, they will share the space evenly. + /// + /// true to expand the column; otherwise, false + public bool Expand + { + get => Handler.Expand; + set => Handler.Expand = value; + } + + /// + /// Gets or sets a value to specify the header text alignment for this column + /// + /// TextAlignment for the column header + public TextAlignment HeaderTextAlignment + { + get => Handler.HeaderTextAlignment; + set => Handler.HeaderTextAlignment = value; + } + + /// + /// Gets or sets the minimum width for the column + /// + /// The column minimum width + public int MinWidth + { + get => Handler.MinWidth; + set => Handler.MinWidth = value; + } + + /// + /// Gets or sets the maximum width for the column + /// + /// The column maximum width + public int MaxWidth + { + get => Handler.MaxWidth; + set => Handler.MaxWidth = value; + } + /// /// Handler interface for the . /// @@ -159,6 +202,33 @@ public bool Visible /// /// true if visible; otherwise, false. bool Visible { get; set; } + + /// + /// Gets or sets a value indicating whether this column should expand to fill the available space in the Grid + /// + /// + /// If more than one column has this set, they will share the space evenly. + /// + /// true to expand the column; otherwise, false + bool Expand { get; set; } + + /// + /// Gets or sets a value to specify the header text alignment for this column + /// + /// TextAlignment for the column header + TextAlignment HeaderTextAlignment { get; set; } + + /// + /// Gets or sets the minimum width for the column + /// + /// The column minimum width + int MinWidth { get; set; } + + /// + /// Gets or sets the maximum width for the column + /// + /// The column maximum width + int MaxWidth { get; set; } } } } diff --git a/test/Eto.Test/Sections/Controls/GridViewSection.cs b/test/Eto.Test/Sections/Controls/GridViewSection.cs index c79b238399..17ac5af823 100644 --- a/test/Eto.Test/Sections/Controls/GridViewSection.cs +++ b/test/Eto.Test/Sections/Controls/GridViewSection.cs @@ -111,6 +111,7 @@ Control CreateOptions(GridView grid) layout.AddSeparateRow(null, ReloadDataButton(grid), SetDataButton(grid), + SetTextBoxWidth(grid), null ); layout.AddSeparateRow(null, @@ -127,15 +128,25 @@ Control CreateOptions(GridView grid) return layout; } + Control SetTextBoxWidth(GridView grid) + { + var button = new Button { Text = "Set TextBoxCell.Width" }; + var textBoxCell = grid.Columns.FirstOrDefault(r => r.DataCell is TextBoxCell); + button.Click += (sender, e) => textBoxCell.Width = 100; + return button; + } + Control TextAlignmentDropDown(GridView grid) { var control = new EnumDropDown(); - var textBoxCell = grid.Columns.Select(r => r.DataCell).OfType().First(); - control.SelectedValueBinding.Bind(textBoxCell, c => c.TextAlignment); + var textBoxCell = grid.Columns.Select(r => r.DataCell).OfType().FirstOrDefault(); + if (textBoxCell != null) + control.SelectedValueBinding.Bind(textBoxCell, c => c.TextAlignment); - var imageTextCell = grid.Columns.Select(r => r.DataCell).OfType().First(); - control.SelectedValueBinding.Bind(imageTextCell, c => c.TextAlignment); + var imageTextCell = grid.Columns.Select(r => r.DataCell).OfType().FirstOrDefault(); + if (imageTextCell != null) + control.SelectedValueBinding.Bind(imageTextCell, c => c.TextAlignment); return control; } @@ -143,11 +154,13 @@ Control VerticalAlignmentDropDown(GridView grid) { var control = new EnumDropDown(); - var textBoxCell = grid.Columns.Select(r => r.DataCell).OfType().First(); - control.SelectedValueBinding.Bind(textBoxCell, c => c.VerticalAlignment); + var textBoxCell = grid.Columns.Select(r => r.DataCell).OfType().FirstOrDefault(); + if (textBoxCell != null) + control.SelectedValueBinding.Bind(textBoxCell, c => c.VerticalAlignment); - var imageTextCell = grid.Columns.Select(r => r.DataCell).OfType().First(); - control.SelectedValueBinding.Bind(imageTextCell, c => c.VerticalAlignment); + var imageTextCell = grid.Columns.Select(r => r.DataCell).OfType().FirstOrDefault(); + if (imageTextCell != null) + control.SelectedValueBinding.Bind(imageTextCell, c => c.VerticalAlignment); return control; } @@ -155,11 +168,13 @@ Control AutoSelectModeDropDown(GridView grid) { var control = new EnumDropDown(); - var textBoxCell = grid.Columns.Select(r => r.DataCell).OfType().First(); - control.SelectedValueBinding.Bind(textBoxCell, c => c.AutoSelectMode); + var textBoxCell = grid.Columns.Select(r => r.DataCell).OfType().FirstOrDefault(); + if (textBoxCell != null) + control.SelectedValueBinding.Bind(textBoxCell, c => c.AutoSelectMode); - var imageTextCell = grid.Columns.Select(r => r.DataCell).OfType().First(); - control.SelectedValueBinding.Bind(imageTextCell, c => c.AutoSelectMode); + var imageTextCell = grid.Columns.Select(r => r.DataCell).OfType().FirstOrDefault(); + if (imageTextCell != null) + control.SelectedValueBinding.Bind(imageTextCell, c => c.AutoSelectMode); return control; } diff --git a/test/Eto.Test/UnitTests/Forms/Controls/GridViewTests.cs b/test/Eto.Test/UnitTests/Forms/Controls/GridViewTests.cs index 2e77459872..c3f18ebb30 100755 --- a/test/Eto.Test/UnitTests/Forms/Controls/GridViewTests.cs +++ b/test/Eto.Test/UnitTests/Forms/Controls/GridViewTests.cs @@ -13,7 +13,7 @@ namespace Eto.Test.UnitTests.Forms.Controls { public abstract class GridTests : TestBase - where T: Grid, new() + where T : Grid, new() { class GridTestItem : TreeGridItem { @@ -40,7 +40,8 @@ void AddLogging(CustomCell cell) if (!CustomCell.SupportsControlView) { cell.GetPreferredWidth = args => 100; - cell.Paint += (sender, e) => { + cell.Paint += (sender, e) => + { e.Graphics.DrawText(SystemFonts.Default(), Brushes.Black, e.ClipRectangle, "Cell", alignment: FormattedTextAlignment.Center); }; } @@ -61,7 +62,8 @@ void AddLogging(CustomCell cell) // ugly, there should be a better way to do this.. var colorBinding = textBox.Bind(c => c.TextColor, args, Binding.Property((CellEventArgs a) => a.CellTextColor).Convert(c => args.IsEditing ? SystemColors.ControlText : c)); - args.PropertyChanged += (sender, e) => { + args.PropertyChanged += (sender, e) => + { if (e.PropertyName == nameof(CellEventArgs.IsEditing)) colorBinding.Update(); }; @@ -81,7 +83,7 @@ void AddLogging(CustomCell cell) var customCell2 = new CustomCell(); customCell2.CreateCell = args => { - var dropDown = new DropDown { Items = { "Item 1", "Item 2", "Item 3" }}; + var dropDown = new DropDown { Items = { "Item 1", "Item 2", "Item 3" } }; return dropDown; }; @@ -100,7 +102,7 @@ void AddLogging(CustomCell cell) grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(nameof(GridTestItem.Text)), HeaderText = "TextBoxCell", Editable = true }); - var list = new List(); + var list = new TreeGridItemCollection(); list.Add(new GridTestItem { Text = "Item 1" }); list.Add(new GridTestItem { Text = "Item 2" }); list.Add(new GridTestItem { Text = "Item 3" }); @@ -108,19 +110,22 @@ void AddLogging(CustomCell cell) // using MouseDown so the buttons don't get focus var beginEditButton = new Button { Text = "BeginEdit" }; - beginEditButton.MouseDown += (sender, e) => { + beginEditButton.MouseDown += (sender, e) => + { grid.BeginEdit(1, 0); e.Handled = true; }; var commitEditButton = new Button { Text = "CommitEdit" }; - commitEditButton.MouseDown += (sender, e) => { + commitEditButton.MouseDown += (sender, e) => + { grid.CommitEdit(); e.Handled = true; }; var cancelEditButton = new Button { Text = "CancelEdit" }; - cancelEditButton.MouseDown += (sender, e) => { + cancelEditButton.MouseDown += (sender, e) => + { grid.CancelEdit(); e.Handled = true; }; @@ -132,6 +137,135 @@ void AddLogging(CustomCell cell) }); } + IEnumerable CreateDataStore() + { + var list = new TreeGridItemCollection(); + for (int i = 0; i < 20; i++) + { + list.Add(new GridTestItem { Text = $"Item {i}", Values = new[] { $"col {i}.2", $"col {i}.3", $"col {i}.4" } }); + } + return list; + } + + [ManualTest] + [TestCase(0)] + [TestCase(1)] + [TestCase(2)] + public void ExpandedColumnShouldExpand(int columnToExpand) + { + ManualForm("First Column should be expanded, and change size with the Grid", form => + { + var grid = new T(); + SetDataStore(grid, CreateDataStore()); + + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell { Binding = Binding.Property((GridTestItem m) => m.Text) } }); + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(0) }); + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(1) }); + + var expandColumn = grid.Columns[columnToExpand]; + expandColumn.HeaderText = "Expanded"; + expandColumn.Expand = true; + + + return grid; + }); + } + + [ManualTest] + [TestCase(0)] + [TestCase(1)] + [TestCase(2)] + public void ExpandedColumnShouldAutoSize(int columnToExpand) + { + ManualForm("First Column should be expanded, and change size with the Grid", form => + { + var grid = new T(); + SetDataStore(grid, CreateDataStore()); + + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell { Binding = Binding.Property((GridTestItem m) => m.Text) } }); + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(0) }); + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(1) }); + + var expandColumn = grid.Columns[columnToExpand]; + expandColumn.HeaderText = "Expanded"; + expandColumn.Expand = true; + + return TableLayout.AutoSized(grid); + }); + } + + [Test, ManualTest] + public void HeaderTextAlignmentShouldWork() + { + ManualForm("Check alignment for each header", form => + { + var grid = new T(); + grid.Height = 200; + SetDataStore(grid, CreateDataStore()); + + grid.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell { Binding = Binding.Property((GridTestItem m) => m.Text) }, + HeaderText = "Left Aligned", + Width = 200 + }); + grid.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell(0), + HeaderText = "Also Left", + HeaderTextAlignment = TextAlignment.Left, + Width = 200 + }); + grid.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell(1), + HeaderText = "Center", + HeaderTextAlignment = TextAlignment.Center, + Width = 200 + }); + grid.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell(2), + HeaderText = "Right", + HeaderTextAlignment = TextAlignment.Right, + Width = 200 + }); + + return grid; + }); + } + + [Test, ManualTest] + public void SettingWidthShouldDisableAutosize() + { + ManualForm("Width of column should be 300px and not change when scrolling", + form => + { + var control = new T(); + control.Width = 400; + control.Height = 200; + var column = new GridColumn + { + DataCell = new TextBoxCell(0), + AutoSize = true, + Width = 300, // setting width should set AutoSize to false + HeaderText = "Cell" + }; + control.Columns.Add(column); + + Assert.IsFalse(column.AutoSize, "#1"); + + var dd = new TreeGridItemCollection(); + for (int i = 0; i < 1000; i++) + { + dd.Add(new TreeGridItem { Values = new[] { "Row " + i } }); + } + SetDataStore(control, dd); + + return control; + }); + } + protected abstract void SetDataStore(T grid, IEnumerable dataStore); } @@ -319,7 +453,7 @@ class CustomCellWithTableLayout : CustomCell protected override Control OnCreateCell(CellEventArgs args) { var label = new Label { Text = "Hello" }; - + var button = new Button { MinimumSize = Size.Empty, Text = "..." }; button.Bind(c => c.Visible, args, a => a.IsSelected); // kaboom when reloading! @@ -389,7 +523,8 @@ public void ClickingWithEmptyDataShouldNotCrash(bool allowEmptySelection, bool a HeaderText = "Text Cell" }); control.DataStore = dd; - Application.Instance.AsyncInvoke(() => { + Application.Instance.AsyncInvoke(() => + { // can crash when had selection initially but no selection after. try { @@ -408,35 +543,5 @@ public void ClickingWithEmptyDataShouldNotCrash(bool allowEmptySelection, bool a if (exception != null) ExceptionDispatchInfo.Capture(exception).Throw(); } - - [Test, ManualTest] - public void SettingWidthShouldDisableAutosize() - { - ManualForm("Width of column should be 300px and not change when scrolling", - form => { - var control = new GridView(); - control.Width = 400; - control.Height = 200; - var column = new GridColumn - { - DataCell = new TextBoxCell(0), - AutoSize = true, - Width = 300, // setting width should set AutoSize to false - HeaderText = "Cell" - }; - control.Columns.Add(column); - - Assert.IsFalse(column.AutoSize, "#1"); - - var dd = new List(); - for (int i = 0; i < 1000; i++) - { - dd.Add(new GridItem { Values = new[] { "Row " + i } }); - } - control.DataStore = dd; - - return control; - }); - } } } diff --git a/test/Eto.Test/UnitTests/Forms/Controls/TreeGridViewTests.cs b/test/Eto.Test/UnitTests/Forms/Controls/TreeGridViewTests.cs index 1a54243558..f6f35d2221 100644 --- a/test/Eto.Test/UnitTests/Forms/Controls/TreeGridViewTests.cs +++ b/test/Eto.Test/UnitTests/Forms/Controls/TreeGridViewTests.cs @@ -4,11 +4,12 @@ using System.Linq; using Eto.Drawing; using System.Runtime.ExceptionServices; +using System.Collections.Generic; namespace Eto.Test.UnitTests.Forms.Controls { [TestFixture] - public class TreeGridViewTests : TestBase + public class TreeGridViewTests : GridTests { [Test] public void SelectedItemsShouldNotCrash() @@ -152,5 +153,10 @@ public void ClickingWithEmptyDataShouldNotCrash(bool allowEmptySelection, bool a ExceptionDispatchInfo.Capture(exception).Throw(); } + + protected override void SetDataStore(TreeGridView grid, IEnumerable dataStore) + { + grid.DataStore = (ITreeGridStore)dataStore; + } } }