From a3589c15f8d7083af43d96738dedb9c0480b30b4 Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Fri, 2 Dec 2022 14:50:33 -0800 Subject: [PATCH] Mac: Fix issues autosizing columns in some cases - Now properly handles all the different styles of NSTableView/NSOutlineView from Big Sur - Fixed warning in test app with unreachable code - Fixed warning when running wrt. the EtoFontManager constructor. --- lib/monomac | 2 +- src/Eto.Mac/Drawing/EtoFontManager.cs | 2 +- src/Eto.Mac/Forms/Controls/GridHandler.cs | 46 +++++++-- test/Eto.Test.Mac/Eto.Test.Mac64.csproj | 20 ++++ test/Eto.Test.Mac/Eto.Test.XamMac2.csproj | 15 +++ test/Eto.Test.Mac/Eto.Test.macOS.csproj | 13 +++ test/Eto.Test.Mac/Startup.cs | 15 +-- test/Eto.Test.Mac/UnitTests/BitmapTests.cs | 8 -- test/Eto.Test.Mac/UnitTests/ButtonTests.cs | 7 -- test/Eto.Test.Mac/UnitTests/CheckBoxTests.cs | 8 -- test/Eto.Test.Mac/UnitTests/GridViewTests.cs | 98 +++++++++++++++++++ test/Eto.Test.Mac/UnitTests/IconTests.cs | 8 -- .../UnitTests/NativeParentWindowTests.cs | 8 -- .../UnitTests/RadioButtonTests.cs | 8 -- .../Sections/Behaviors/ScreenSection.cs | 2 - .../UnitTests/Forms/Controls/GridTests.cs | 10 +- 16 files changed, 206 insertions(+), 64 deletions(-) create mode 100644 test/Eto.Test.Mac/UnitTests/GridViewTests.cs diff --git a/lib/monomac b/lib/monomac index ad69c30a7e..a8aeac79a3 160000 --- a/lib/monomac +++ b/lib/monomac @@ -1 +1 @@ -Subproject commit ad69c30a7e6cafebe07a305ccdd322125e9cdf5d +Subproject commit a8aeac79a3dc24d8dbd9f2b46248f916e63c9968 diff --git a/src/Eto.Mac/Drawing/EtoFontManager.cs b/src/Eto.Mac/Drawing/EtoFontManager.cs index bb18fac32d..fbb04538da 100644 --- a/src/Eto.Mac/Drawing/EtoFontManager.cs +++ b/src/Eto.Mac/Drawing/EtoFontManager.cs @@ -8,7 +8,7 @@ public EtoFontManager() { } - public EtoFontManager(IntPtr handle) + public EtoFontManager(NativeHandle handle) : base(handle) { } diff --git a/src/Eto.Mac/Forms/Controls/GridHandler.cs b/src/Eto.Mac/Forms/Controls/GridHandler.cs index fb2fb53258..47b31542b5 100644 --- a/src/Eto.Mac/Forms/Controls/GridHandler.cs +++ b/src/Eto.Mac/Forms/Controls/GridHandler.cs @@ -352,6 +352,33 @@ public override void OnLoadComplete(EventArgs e) NSRange autoSizeRange; + static Lazy supportsTableStyle = new Lazy(() => ObjCExtensions.InstancesRespondToSelector(Selector.GetHandle("effectiveStyle"))); + + nfloat GetTableRowInsets() + { + // oh I love magic numbers, but there doesn't seem to be any APIs that will return these.. + // https://developer.apple.com/documentation/macos-release-notes/appkit-release-notes-for-macos-12 + if (supportsTableStyle.Value) + { + switch (Control.EffectiveStyle) + { + case NSTableViewStyle.Inset: + return 32; + case NSTableViewStyle.FullWidth: + return 12; + case NSTableViewStyle.SourceList: + return 32; + case NSTableViewStyle.Plain: + default: + return Control.IntercellSpacing.Width; + } + } + else + { + return Control.IntercellSpacing.Width; + } + } + public bool AutoSizeColumns(bool force, bool forceNewSize = false) { if (Widget.Loaded) @@ -363,37 +390,44 @@ public bool AutoSizeColumns(bool force, bool forceNewSize = false) || (autoSizeRange.Location != newRange.Value.Location || autoSizeRange.Length != newRange.Value.Length)) { IsAutoSizingColumns = true; + int expandCount = 0; nfloat requiredWidth = 0; nfloat expandedWidth = 0; + + // remove all spacing that isn't part of column widths var intercellSpacingWidth = Table.IntercellSpacing.Width; + rect.Width -= intercellSpacingWidth * (Table.ColumnCount - 1); + rect.Width -= GetTableRowInsets(); + foreach (var col in ColumnHandlers) { col.AutoSizeColumn(newRange, forceNewSize); if (col.Expand) { expandCount++; - expandedWidth += col.Control.Width + intercellSpacingWidth; + expandedWidth += col.Control.Width; } else { - requiredWidth += col.Control.Width + intercellSpacingWidth; + requiredWidth += col.Control.Width; } } if (expandCount > 0 && !forceNewSize) { - var remaining = (nfloat)Math.Max(0, rect.Width - requiredWidth + (int)Math.Round(intercellSpacingWidth / 3) - 1); + var remaining = (nfloat)Math.Max(0, rect.Width - requiredWidth); // System.Diagnostics.Debug.WriteLine($"Remaining: {remaining}, Required: {requiredWidth}, Width: {rect.Width}"); if (remaining > 0) { - var each = (nfloat)Math.Max(0, (remaining / expandCount) - intercellSpacingWidth); + var each = remaining / expandCount; + foreach (var col in ColumnHandlers) { if (col.Expand) { - var existingWidth = col.Control.Width + intercellSpacingWidth; + var existingWidth = col.Control.Width; var weightedWidth = existingWidth / expandedWidth * remaining; - col.Control.Width = (nfloat)Math.Max(0, weightedWidth - intercellSpacingWidth); + col.Control.Width = weightedWidth; } } } diff --git a/test/Eto.Test.Mac/Eto.Test.Mac64.csproj b/test/Eto.Test.Mac/Eto.Test.Mac64.csproj index 74f5a1bfb3..e9643231cf 100644 --- a/test/Eto.Test.Mac/Eto.Test.Mac64.csproj +++ b/test/Eto.Test.Mac/Eto.Test.Mac64.csproj @@ -11,6 +11,7 @@ osx-x64;osx-arm64 MONOMAC + 10.0 @@ -19,6 +20,25 @@ True + + + + + + + + + + + + + + + + + + + diff --git a/test/Eto.Test.Mac/Eto.Test.XamMac2.csproj b/test/Eto.Test.Mac/Eto.Test.XamMac2.csproj index 680bff1fa1..4b92999576 100644 --- a/test/Eto.Test.Mac/Eto.Test.XamMac2.csproj +++ b/test/Eto.Test.Mac/Eto.Test.XamMac2.csproj @@ -14,12 +14,27 @@ XAMMAC;XAMMAC2 10.15 CA1416 + 10 SdkOnly + + + + + + + + + + + + + + diff --git a/test/Eto.Test.Mac/Eto.Test.macOS.csproj b/test/Eto.Test.Mac/Eto.Test.macOS.csproj index 9a6d044fb8..1c21124824 100644 --- a/test/Eto.Test.Mac/Eto.Test.macOS.csproj +++ b/test/Eto.Test.Mac/Eto.Test.macOS.csproj @@ -17,6 +17,19 @@ SdkOnly + + + + + + + + + + + + + diff --git a/test/Eto.Test.Mac/Startup.cs b/test/Eto.Test.Mac/Startup.cs index c4948bd3ca..e60585b561 100644 --- a/test/Eto.Test.Mac/Startup.cs +++ b/test/Eto.Test.Mac/Startup.cs @@ -6,12 +6,6 @@ using Eto.Mac.Forms.ToolBar; using Eto.Forms; -#if MONOMAC -using MonoMac.AppKit; -#else -using AppKit; -#endif - namespace Eto.Test.Mac { class Startup @@ -77,7 +71,16 @@ static void AddStyles() //handler.Control.DisplayMode = NSToolbarDisplayMode.Icon; }); + Style.Add(null, c => StyleGrid(c.Control)); + Style.Add(null, c => StyleGrid(c.Control)); + } + + private static void StyleGrid(NSTableView control) + { + // macOS Big Sur changed default from 3,2 to 17,0. This appears to be more sane for our purposes. + // control.IntercellSpacing = new CGSize(3, 2); } + } } diff --git a/test/Eto.Test.Mac/UnitTests/BitmapTests.cs b/test/Eto.Test.Mac/UnitTests/BitmapTests.cs index 5c7ea3ad26..6a2493710c 100644 --- a/test/Eto.Test.Mac/UnitTests/BitmapTests.cs +++ b/test/Eto.Test.Mac/UnitTests/BitmapTests.cs @@ -3,14 +3,6 @@ using Eto.Test.UnitTests; using NUnit.Framework; -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -#else -using AppKit; -using CoreGraphics; -#endif - namespace Eto.Test.Mac.UnitTests { [TestFixture] diff --git a/test/Eto.Test.Mac/UnitTests/ButtonTests.cs b/test/Eto.Test.Mac/UnitTests/ButtonTests.cs index f9599b65c5..561db4932a 100644 --- a/test/Eto.Test.Mac/UnitTests/ButtonTests.cs +++ b/test/Eto.Test.Mac/UnitTests/ButtonTests.cs @@ -8,13 +8,6 @@ using System.Threading.Tasks; using Eto.Mac; -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -#else -using AppKit; -using CoreGraphics; -#endif namespace Eto.Test.Mac.UnitTests { [TestFixture] diff --git a/test/Eto.Test.Mac/UnitTests/CheckBoxTests.cs b/test/Eto.Test.Mac/UnitTests/CheckBoxTests.cs index 44731c1e98..98461c8cfe 100644 --- a/test/Eto.Test.Mac/UnitTests/CheckBoxTests.cs +++ b/test/Eto.Test.Mac/UnitTests/CheckBoxTests.cs @@ -5,14 +5,6 @@ using Eto.Test.UnitTests; using NUnit.Framework; -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -#else -using AppKit; -using CoreGraphics; -#endif - namespace Eto.Test.Mac.UnitTests { [TestFixture] diff --git a/test/Eto.Test.Mac/UnitTests/GridViewTests.cs b/test/Eto.Test.Mac/UnitTests/GridViewTests.cs new file mode 100644 index 0000000000..9cf4ca3e14 --- /dev/null +++ b/test/Eto.Test.Mac/UnitTests/GridViewTests.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Eto.Drawing; +using Eto.Forms; +using Eto.Mac; +using Eto.Test.UnitTests; +using NUnit.Framework; + +namespace Eto.Test.Mac.UnitTests +{ + public abstract class GridTests : TestBase + where T: Grid, new() + { + class GridTestItem : TreeGridItem + { + public string Text { get; set; } + + public Image Image { get; set; } + + public override string ToString() => Text ?? base.ToString(); + } + + protected abstract void SetDataStore(T grid, IEnumerable dataStore); + + public IEnumerable CreateDataStore(int rows = 40) + { + var list = new TreeGridItemCollection(); + for (int i = 0; i < rows; i++) + { + Image image = i % 2 == 0 ? (Image)TestIcons.Logo : (Image)TestIcons.TestImage; + list.Add(new GridTestItem { Text = $"Item {i}", Image = image, Values = new[] { $"col {i}.2", $"col {i}.3", $"col {i}.4", $"col {i}.5" } }); + } + return list; + } + + [ManualTest] + [TestCase(NSTableViewStyle.FullWidth, -1, 1)] + [TestCase(NSTableViewStyle.FullWidth, -1, 3)] + [TestCase(NSTableViewStyle.FullWidth, 3, 3)] + [TestCase(NSTableViewStyle.Inset, -1, 1)] + [TestCase(NSTableViewStyle.Inset, -1, 3)] + [TestCase(NSTableViewStyle.Inset, 3, 3)] + [TestCase(NSTableViewStyle.SourceList, -1, 1)] + [TestCase(NSTableViewStyle.SourceList, -1, 3)] + [TestCase(NSTableViewStyle.SourceList, 3, 3)] + [TestCase(NSTableViewStyle.Plain, -1, 1)] + [TestCase(NSTableViewStyle.Plain, -1, 3)] + [TestCase(NSTableViewStyle.Plain, 3, 3)] + public void ScrollingExpandedColumnShouldKeepItsSize(NSTableViewStyle style, int intercellSpacing, int numColumns) + { + ManualForm("Scrolling should not cause the widths of the columns to go beyond the width of the grid,\nso the horizontal scrollbar should never show up.", form => + { + form.Title = $"TesNSTableViewStyle: {style}"; + var grid = new T(); + grid.Height = 200; + if (grid.ControlObject is NSTableView tableView) + { + if (ObjCExtensions.InstancesRespondToSelector(Selector.GetHandle("style"))) + tableView.Style = style; + else + { + // macos 10.15 and older + if (style == NSTableViewStyle.SourceList) + tableView.SelectionHighlightStyle = NSTableViewSelectionHighlightStyle.SourceList; + } + if (intercellSpacing >= 0) + tableView.IntercellSpacing = new CGSize(intercellSpacing, 2); + } + + SetDataStore(grid, CreateDataStore()); + + grid.Columns.Add(new GridColumn { DataCell = new ImageTextCell { TextBinding = Binding.Property((GridTestItem m) => m.Text), ImageBinding = Binding.Property((GridTestItem m) => m.Image) } }); + for (int i = 0; i < numColumns; i++) + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(i) }); + + var expandColumn = grid.Columns[0]; + expandColumn.HeaderText = "Expanded"; + expandColumn.Expand = true; + + return grid; + }); + } + } + + [TestFixture] + public class GridViewTests : GridTests + { + protected override void SetDataStore(GridView grid, IEnumerable dataStore) => grid.DataStore = dataStore; + } + + [TestFixture] + public class TreeGridViewTests : GridTests + { + protected override void SetDataStore(TreeGridView grid, IEnumerable dataStore) => grid.DataStore = (ITreeGridStore)dataStore; + } +} \ No newline at end of file diff --git a/test/Eto.Test.Mac/UnitTests/IconTests.cs b/test/Eto.Test.Mac/UnitTests/IconTests.cs index f638ef0961..b980cf5c36 100644 --- a/test/Eto.Test.Mac/UnitTests/IconTests.cs +++ b/test/Eto.Test.Mac/UnitTests/IconTests.cs @@ -5,14 +5,6 @@ using NUnit.Framework; using Eto.Mac; -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -#else -using AppKit; -using CoreGraphics; -#endif - namespace Eto.Test.Mac64.UnitTests { [TestFixture] diff --git a/test/Eto.Test.Mac/UnitTests/NativeParentWindowTests.cs b/test/Eto.Test.Mac/UnitTests/NativeParentWindowTests.cs index d903428dd7..6636016c6f 100644 --- a/test/Eto.Test.Mac/UnitTests/NativeParentWindowTests.cs +++ b/test/Eto.Test.Mac/UnitTests/NativeParentWindowTests.cs @@ -4,14 +4,6 @@ using Eto.Forms; using System.Threading; -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -#else -using AppKit; -using CoreGraphics; -#endif - namespace Eto.Test.Mac.UnitTests { [TestFixture] diff --git a/test/Eto.Test.Mac/UnitTests/RadioButtonTests.cs b/test/Eto.Test.Mac/UnitTests/RadioButtonTests.cs index 9d38407222..0ce97efc01 100644 --- a/test/Eto.Test.Mac/UnitTests/RadioButtonTests.cs +++ b/test/Eto.Test.Mac/UnitTests/RadioButtonTests.cs @@ -5,14 +5,6 @@ using Eto.Test.UnitTests; using NUnit.Framework; -#if MONOMAC -using MonoMac.AppKit; -using MonoMac.CoreGraphics; -#else -using AppKit; -using CoreGraphics; -#endif - namespace Eto.Test.Mac.UnitTests { [TestFixture] diff --git a/test/Eto.Test/Sections/Behaviors/ScreenSection.cs b/test/Eto.Test/Sections/Behaviors/ScreenSection.cs index 35af22d038..f3e8a0b9c3 100755 --- a/test/Eto.Test/Sections/Behaviors/ScreenSection.cs +++ b/test/Eto.Test/Sections/Behaviors/ScreenSection.cs @@ -233,8 +233,6 @@ void SetAdjacentSize() cornerWindows.Add(adjacentForm); - return; - int i = 0; foreach (var screen in Screen.Screens) { diff --git a/test/Eto.Test/UnitTests/Forms/Controls/GridTests.cs b/test/Eto.Test/UnitTests/Forms/Controls/GridTests.cs index 488f7d67d0..6f0d631ccd 100644 --- a/test/Eto.Test/UnitTests/Forms/Controls/GridTests.cs +++ b/test/Eto.Test/UnitTests/Forms/Controls/GridTests.cs @@ -11,6 +11,8 @@ public abstract class GridTests : TestBase class GridTestItem : TreeGridItem { public string Text { get; set; } + + public Image Image { get; set; } public override string ToString() => Text ?? base.ToString(); } @@ -137,7 +139,8 @@ public IEnumerable CreateDataStore(int rows = 20) var list = new TreeGridItemCollection(); for (int i = 0; i < rows; i++) { - list.Add(new GridTestItem { Text = $"Item {i}", Values = new[] { $"col {i}.2", $"col {i}.3", $"col {i}.4" } }); + Image image = i % 2 == 0 ? (Image)TestIcons.Logo : (Image)TestIcons.TestImage; + list.Add(new GridTestItem { Text = $"Item {i}", Image = image, Values = new[] { $"col {i}.2", $"col {i}.3", $"col {i}.4", $"col {i}.5" } }); } return list; } @@ -154,11 +157,16 @@ public void ExpandedColumnShouldExpand(int columnToExpand, int secondColumn) ManualForm("First Column should be expanded, and change size with the Grid", form => { var grid = new T(); + // grid.RowHeight = 48; + // grid.ShowHeader = false; SetDataStore(grid, CreateDataStore()); + // grid.Columns.Add(new GridColumn { DataCell = new ImageTextCell { TextBinding = Binding.Property((GridTestItem m) => m.Text), ImageBinding = Binding.Property((GridTestItem m) => m.Image) } }); 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) }); + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(2) }); + grid.Columns.Add(new GridColumn { DataCell = new TextBoxCell(3) }); var expandColumn = grid.Columns[columnToExpand]; expandColumn.HeaderText = "Expanded";