Browse Source

Merge pull request #3157 from donandren/issues/grid

fixed for few major issues with grid
pull/3175/head
Jumar Macato 7 years ago
committed by GitHub
parent
commit
1a4bc738c4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/Avalonia.Controls/ColumnDefinition.cs
  2. 21
      src/Avalonia.Controls/DefinitionBase.cs
  3. 12
      src/Avalonia.Controls/Grid.cs
  4. 11
      src/Avalonia.Controls/RowDefinition.cs
  5. 251
      tests/Avalonia.Controls.UnitTests/GridTests.cs

11
src/Avalonia.Controls/ColumnDefinition.cs

@ -26,6 +26,14 @@ namespace Avalonia.Controls
public static readonly StyledProperty<GridLength> WidthProperty =
AvaloniaProperty.Register<ColumnDefinition, GridLength>(nameof(Width), new GridLength(1, GridUnitType.Star));
/// <summary>
/// Initializes static members of the <see cref="ColumnDefinition"/> class.
/// </summary>
static ColumnDefinition()
{
AffectsParentMeasure(WidthProperty, MinWidthProperty, MaxWidthProperty);
}
/// <summary>
/// Initializes a new instance of the <see cref="ColumnDefinition"/> class.
/// </summary>
@ -68,7 +76,6 @@ namespace Avalonia.Controls
}
set
{
Parent?.InvalidateMeasure();
SetValue(MaxWidthProperty, value);
}
}
@ -84,7 +91,6 @@ namespace Avalonia.Controls
}
set
{
Parent?.InvalidateMeasure();
SetValue(MinWidthProperty, value);
}
}
@ -100,7 +106,6 @@ namespace Avalonia.Controls
}
set
{
Parent?.InvalidateMeasure();
SetValue(WidthProperty, value);
}
}

21
src/Avalonia.Controls/DefinitionBase.cs

@ -50,6 +50,8 @@ namespace Avalonia.Controls
}
}
}
Parent?.InvalidateMeasure();
}
/// <summary>
@ -63,6 +65,8 @@ namespace Avalonia.Controls
_sharedState.RemoveMember(this);
_sharedState = null;
}
Parent?.InvalidateMeasure();
}
/// <summary>
@ -730,5 +734,22 @@ namespace Avalonia.Controls
SharedSizeGroupProperty.Changed.AddClassHandler<DefinitionBase>(OnSharedSizeGroupPropertyChanged);
PrivateSharedSizeScopeProperty.Changed.AddClassHandler<DefinitionBase>(OnPrivateSharedSizeScopePropertyChanged);
}
/// <summary>
/// Marks a property on a definition as affecting the parent grid's measurement.
/// </summary>
/// <param name="properties">The properties.</param>
protected static void AffectsParentMeasure(params AvaloniaProperty[] properties)
{
void Invalidate(AvaloniaPropertyChangedEventArgs e)
{
(e.Sender as DefinitionBase)?.Parent?.InvalidateMeasure();
}
foreach (var property in properties)
{
property.Changed.Subscribe(Invalidate);
}
}
}
}

12
src/Avalonia.Controls/Grid.cs

@ -6,6 +6,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Threading;
@ -178,6 +179,7 @@ namespace Avalonia.Controls
if (_data == null) { _data = new ExtendedData(); }
_data.ColumnDefinitions = value;
_data.ColumnDefinitions.Parent = this;
InvalidateMeasure();
}
}
@ -198,6 +200,7 @@ namespace Avalonia.Controls
if (_data == null) { _data = new ExtendedData(); }
_data.RowDefinitions = value;
_data.RowDefinitions.Parent = this;
InvalidateMeasure();
}
}
@ -569,6 +572,15 @@ namespace Avalonia.Controls
return (arrangeSize);
}
/// <summary>
/// <see cref="Panel.ChildrenChanged"/>
/// </summary>
protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
{
CellsStructureDirty = true;
base.ChildrenChanged(sender, e);
}
/// <summary>
/// Invalidates grid caches and makes the grid dirty for measure.
/// </summary>

11
src/Avalonia.Controls/RowDefinition.cs

@ -26,6 +26,14 @@ namespace Avalonia.Controls
public static readonly StyledProperty<GridLength> HeightProperty =
AvaloniaProperty.Register<RowDefinition, GridLength>(nameof(Height), new GridLength(1, GridUnitType.Star));
/// <summary>
/// Initializes static members of the <see cref="RowDefinition"/> class.
/// </summary>
static RowDefinition()
{
AffectsParentMeasure(HeightProperty, MaxHeightProperty, MinHeightProperty);
}
/// <summary>
/// Initializes a new instance of the <see cref="RowDefinition"/> class.
/// </summary>
@ -68,7 +76,6 @@ namespace Avalonia.Controls
}
set
{
Parent?.InvalidateMeasure();
SetValue(MaxHeightProperty, value);
}
}
@ -84,7 +91,6 @@ namespace Avalonia.Controls
}
set
{
Parent?.InvalidateMeasure();
SetValue(MinHeightProperty, value);
}
}
@ -100,7 +106,6 @@ namespace Avalonia.Controls
}
set
{
Parent?.InvalidateMeasure();
SetValue(HeightProperty, value);
}
}

251
tests/Avalonia.Controls.UnitTests/GridTests.cs

@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.UnitTests;
using Moq;
using Xunit;
using Xunit.Abstractions;
@ -34,7 +29,6 @@ namespace Avalonia.Controls.UnitTests
private Grid CreateGrid(params (string name, GridLength width, double minWidth, double maxWidth)[] columns)
{
var grid = new Grid();
foreach (var k in columns.Select(c => new ColumnDefinition
{
@ -1270,11 +1264,11 @@ namespace Avalonia.Controls.UnitTests
// grid.Measure(new Size(100, 100));
// grid.Arrange(new Rect(new Point(), new Point(100, 100)));
// PrintColumnDefinitions(grid);
// NOTE: THIS IS BROKEN IN WPF
// all in group are equal to width (MinWidth) of the sizer in the second column
// Assert.All(grid.ColumnDefinitions.Where(cd => cd.SharedSizeGroup == "A"), cd => Assert.Equal(6 + 1 * 6, cd.ActualWidth));
// NOTE: THIS IS BROKEN IN WPF
// grid.ColumnDefinitions[2].SharedSizeGroup = null;
@ -1382,6 +1376,245 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Size(100, 100), grid.Bounds.Size);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Changing_Column_Width_Should_Invalidate_Grid(bool setUsingAvaloniaProperty)
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
if (setUsingAvaloniaProperty)
grid.ColumnDefinitions[0][ColumnDefinition.WidthProperty] = new GridLength(5);
else
grid.ColumnDefinitions[0].Width = new GridLength(5);
});
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Changing_Column_MinWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty)
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
if (setUsingAvaloniaProperty)
grid.ColumnDefinitions[0][ColumnDefinition.MinWidthProperty] = 5;
else
grid.ColumnDefinitions[0].MinWidth = 5;
});
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Changing_Column_MaxWidth_Should_Invalidate_Grid(bool setUsingAvaloniaProperty)
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
if (setUsingAvaloniaProperty)
grid.ColumnDefinitions[0][ColumnDefinition.MaxWidthProperty] = 5;
else
grid.ColumnDefinitions[0].MaxWidth = 5;
});
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Changing_Row_Height_Should_Invalidate_Grid(bool setUsingAvaloniaProperty)
{
var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
if (setUsingAvaloniaProperty)
grid.RowDefinitions[0][RowDefinition.HeightProperty] = new GridLength(5);
else
grid.RowDefinitions[0].Height = new GridLength(5);
});
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Changing_Row_MinHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty)
{
var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
if (setUsingAvaloniaProperty)
grid.RowDefinitions[0][RowDefinition.MinHeightProperty] = 5;
else
grid.RowDefinitions[0].MinHeight = 5;
});
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void Changing_Row_MaxHeight_Should_Invalidate_Grid(bool setUsingAvaloniaProperty)
{
var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
if (setUsingAvaloniaProperty)
grid.RowDefinitions[0][RowDefinition.MaxHeightProperty] = 5;
else
grid.RowDefinitions[0].MaxHeight = 5;
});
}
[Fact]
public void Adding_Column_Should_Invalidate_Grid()
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
grid.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(5)));
});
}
[Fact]
public void Adding_Row_Should_Invalidate_Grid()
{
var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
grid.RowDefinitions.Add(new RowDefinition(new GridLength(5)));
});
}
[Fact]
public void Replacing_Columns_Should_Invalidate_Grid()
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
grid.ColumnDefinitions = ColumnDefinitions.Parse("2*,1*");
});
}
[Fact]
public void Replacing_Rows_Should_Invalidate_Grid()
{
var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
grid.RowDefinitions = RowDefinitions.Parse("2*,1*");
});
}
[Fact]
public void Removing_Column_Should_Invalidate_Grid()
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
grid.ColumnDefinitions.RemoveAt(0);
});
}
[Fact]
public void Removing_Row_Should_Invalidate_Grid()
{
var grid = new Grid { RowDefinitions = RowDefinitions.Parse("1*,1*") };
Change_Property_And_Verify_Measure_Requested(grid, () =>
{
grid.RowDefinitions.RemoveAt(0);
});
}
[Fact]
public void Removing_Child_Should_Invalidate_Grid_And_Be_Operational()
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("*,Auto") };
grid.Children.Add(new Decorator() { [Grid.ColumnProperty] = 0 });
grid.Children.Add(new Decorator() { Width = 10, Height = 10, [Grid.ColumnProperty] = 1 });
var size = new Size(100, 100);
grid.Measure(size);
grid.Arrange(new Rect(size));
Assert.True(grid.IsMeasureValid);
Assert.True(grid.IsArrangeValid);
Assert.Equal(90, grid.Children[0].Bounds.Width);
Assert.Equal(10, grid.Children[1].Bounds.Width);
grid.Children.RemoveAt(1);
Assert.False(grid.IsMeasureValid);
Assert.False(grid.IsArrangeValid);
grid.Measure(size);
grid.Arrange(new Rect(size));
Assert.True(grid.IsMeasureValid);
Assert.True(grid.IsArrangeValid);
Assert.Equal(100, grid.Children[0].Bounds.Width);
}
[Fact]
public void Adding_Child_Should_Invalidate_Grid_And_Be_Operational()
{
var grid = new Grid { ColumnDefinitions = ColumnDefinitions.Parse("*,Auto") };
grid.Children.Add(new Decorator() { [Grid.ColumnProperty] = 0 });
var size = new Size(100, 100);
grid.Measure(size);
grid.Arrange(new Rect(size));
Assert.True(grid.IsMeasureValid);
Assert.True(grid.IsArrangeValid);
Assert.Equal(100, grid.Children[0].Bounds.Width);
grid.Children.Add(new Decorator() { Width = 10, Height = 10, [Grid.ColumnProperty] = 1 });
Assert.False(grid.IsMeasureValid);
Assert.False(grid.IsArrangeValid);
grid.Measure(size);
grid.Arrange(new Rect(size));
Assert.True(grid.IsMeasureValid);
Assert.True(grid.IsArrangeValid);
Assert.Equal(90, grid.Children[0].Bounds.Width);
Assert.Equal(10, grid.Children[1].Bounds.Width);
}
private static void Change_Property_And_Verify_Measure_Requested(Grid grid, Action change)
{
grid.Measure(new Size(100, 100));
grid.Arrange(new Rect(grid.DesiredSize));
Assert.True(grid.IsMeasureValid);
Assert.True(grid.IsArrangeValid);
change();
Assert.False(grid.IsMeasureValid);
Assert.False(grid.IsArrangeValid);
}
private class TestControl : Control
{
public Size MeasureSize { get; set; }

Loading…
Cancel
Save