Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Avalonia.Base/Layout/Layoutable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ protected static void AffectsArrange<T>(params AvaloniaProperty[] properties)
/// </remarks>
protected virtual Size MeasureCore(Size availableSize)
{
ApplyStyling();

if (IsVisible)
{
var margin = Margin;
Expand All @@ -555,7 +557,6 @@ protected virtual Size MeasureCore(Size availableSize)
margin = LayoutHelper.RoundLayoutThickness(margin, scale);
}

ApplyStyling();
ApplyTemplate();

var minMax = new MinMax(this);
Expand Down
5 changes: 3 additions & 2 deletions src/Avalonia.Controls/StackPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,16 @@ protected override Size MeasureOverride(Size availableSize)
// Get next child.
var child = children[i];

// Measure the child.
child.Measure(layoutSlotSize);

bool isVisible = child.IsVisible;

if (isVisible && !hasVisibleChild)
{
hasVisibleChild = true;
}

// Measure the child.
child.Measure(layoutSlotSize);
Size childDesiredSize = child.DesiredSize;

// Accumulate child size.
Expand Down
29 changes: 29 additions & 0 deletions tests/Avalonia.Base.UnitTests/Layout/MeasureTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
using Avalonia.Controls;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Xunit;

namespace Avalonia.Base.UnitTests.Layout
{
public class MeasureTests
{
[Fact]
public void Style_Hiding_Control_Should_Be_Applied_Before_Measuring()
{
var child = new Border
{
Width = 100,
Height = 100,
Classes = { "hidden" }
};
var target = new Decorator
{
Child = child
};
var root = new TestRoot(target);

root.Styles.Add(new Style(x => x.OfType<Border>().Class("hidden"))
{
Setters = { new Setter(Visual.IsVisibleProperty, false) }
});

target.Measure(Size.Infinity);

Assert.False(child.IsVisible);
Assert.Equal(new Size(0,0), child.DesiredSize);
Assert.Equal(new Size(0,0), target.DesiredSize);
}

[Fact]
public void Margin_Should_Be_Included_In_DesiredSize()
{
Expand Down
34 changes: 34 additions & 0 deletions tests/Avalonia.Controls.UnitTests/StackPanelTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using Avalonia.Layout;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Xunit;

Expand Down Expand Up @@ -330,6 +331,39 @@ public void Spacing_Not_Added_For_Invisible_Children(Orientation orientation)
Assert.Equal(sizeWithTwoChildren, sizeWithThreeChildren);
}

[Theory]
[InlineData(Orientation.Horizontal)]
[InlineData(Orientation.Vertical)]
public void Spacing_Not_Added_For_Children_Hidden_By_Style_Applied_During_Measure(Orientation orientation)
{
var target = new StackPanel
{
Spacing = 40,
Orientation = orientation,
Children =
{
new StackPanel { Width = 10, Height = 10, Classes = { "hidden" } },
new StackPanel { Width = 10, Height = 10 },
new StackPanel { Width = 10, Height = 10 },
}
};

var root = new TestRoot(target);

root.Styles.Add(new Style(x => x.OfType<StackPanel>().Class("hidden"))
{
Setters = { new Setter(Visual.IsVisibleProperty, false) }
});

target.Measure(Size.Infinity);

var expected = orientation == Orientation.Horizontal ?
new Size(60, 10) :
new Size(10, 60);

Assert.Equal(expected, target.DesiredSize);
}

[Theory]
[InlineData(Orientation.Horizontal)]
[InlineData(Orientation.Vertical)]
Expand Down
77 changes: 77 additions & 0 deletions tests/Avalonia.Controls.UnitTests/WindowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,83 @@ public void WindowDecorationsTheme_Should_Apply_To_Decorations()
}
}

[Fact]
public void IsVisible_Setter_Should_Affect_Measurements_Inside_WindowDrawnDecorationsContent()
{
using var app = UnitTestApplication.Start(TestServices.StyledWindow);

var windowImpl = MockWindowingPlatform.CreateWindowMock();
windowImpl.Setup(x => x.NeedsManagedDecorations).Returns(true);
windowImpl.Setup(x => x.RequestedDrawnDecorations).Returns(PlatformRequestedDrawnDecoration.TitleBar);

var window = new Window(windowImpl.Object);

var stackPanel = new StackPanel
{
Width = 32,
Spacing = 2,
Children =
{
new Control { Height = 32 },
new Control
{
Height = 32,
Classes = { "hidden-by-style" }
},
}
};

var contentControl = new ContentControl
{
Content = new Control
{
Height = 32,
Width = 32,
Classes = { "hidden-by-style" }
}
};

var content = new WindowDrawnDecorationsContent
{
Overlay = new ContentControl
{
Content = new Panel
{
Children = { stackPanel, contentControl }
}
}
};

var template = new WindowDrawnDecorationsTemplate
{
Content = (IServiceProvider? _) => new TemplateResult<WindowDrawnDecorationsContent>(content, new NameScope())
};

var theme = new ControlTheme(typeof(WindowDrawnDecorations))
{
Setters =
{
new Setter(WindowDrawnDecorations.TemplateProperty, template)
}
};

var style = new Style(x => x.Is<WindowDrawnDecorations>().Template().OfType<Control>().Class("hidden-by-style"))
{
Setters =
{
new Setter(Visual.IsVisibleProperty, false)
}
};

window.WindowDecorationsTheme = theme;
window.Styles.Add(style);
window.Show();
window.Measure(Size.Infinity);

Assert.Equal(new Size(), contentControl.DesiredSize);
Assert.Equal(new Size(32, 32), stackPanel.DesiredSize);
}

public class TitleBarDecorationsTests : ScopedTestBase
{
private static Window CreateWindowWithDrawnDecorations(PlatformAllowedWindowActions allowedActions = PlatformAllowedWindowActions.All)
Expand Down