Browse Source

Don't layout invisible controls.

And fix unit tests that were relying on this behavior.
pull/10864/head
Steven Kirk 3 years ago
parent
commit
6dd9106fe5
  1. 24
      src/Avalonia.Base/Layout/LayoutManager.cs
  2. 2
      tests/Avalonia.Controls.UnitTests/MenuItemTests.cs
  3. 1
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  4. 2
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlThemeTests.cs

24
src/Avalonia.Base/Layout/LayoutManager.cs

@ -269,21 +269,25 @@ namespace Avalonia.Layout
}
}
private void Measure(Layoutable control)
private bool Measure(Layoutable control)
{
if (!control.IsVisible || !control.IsAttachedToVisualTree)
return false;
// Controls closest to the visual root need to be arranged first. We don't try to store
// ordered invalidation lists, instead we traverse the tree upwards, measuring the
// controls closest to the root first. This has been shown by benchmarks to be the
// fastest and most memory-efficient algorithm.
if (control.VisualParent is Layoutable parent)
{
Measure(parent);
if (!Measure(parent))
return false;
}
// If the control being measured has IsMeasureValid == true here then its measure was
// handed by an ancestor and can be ignored. The measure may have also caused the
// control to be removed.
if (!control.IsMeasureValid && control.IsAttachedToVisualTree)
if (!control.IsMeasureValid)
{
if (control is ILayoutRoot root)
{
@ -294,16 +298,22 @@ namespace Avalonia.Layout
control.Measure(control.PreviousMeasure.Value);
}
}
return true;
}
private void Arrange(Layoutable control)
private bool Arrange(Layoutable control)
{
if (!control.IsVisible || !control.IsAttachedToVisualTree)
return false;
if (control.VisualParent is Layoutable parent)
{
Arrange(parent);
if (!Arrange(parent))
return false;
}
if (!control.IsArrangeValid && control.IsAttachedToVisualTree)
if (control.IsMeasureValid && !control.IsArrangeValid)
{
if (control is IEmbeddedLayoutRoot embeddedRoot)
control.Arrange(new Rect(embeddedRoot.AllocatedSize));
@ -316,6 +326,8 @@ namespace Avalonia.Layout
control.Arrange(control.PreviousArrange.Value);
}
}
return true;
}
private void QueueLayoutPass()

2
tests/Avalonia.Controls.UnitTests/MenuItemTests.cs

@ -334,6 +334,7 @@ namespace Avalonia.Controls.UnitTests
};
var window = new Window { Content = menu };
window.Show();
window.LayoutManager.ExecuteInitialLayoutPass();
topLevelMenu.IsSubMenuOpen = true;
@ -371,6 +372,7 @@ namespace Avalonia.Controls.UnitTests
};
var window = new Window { Content = menu };
window.Show();
window.LayoutManager.ExecuteInitialLayoutPass();
var panel = Assert.IsType<StackPanel>(menu.Presenter.Panel);

1
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -1116,6 +1116,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
private static Window PreparedWindow(object content = null)
{
var w = new Window { Content = content };
w.Show();
w.ApplyStyling();
w.ApplyTemplate();
return w;

2
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlThemeTests.cs

@ -27,6 +27,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var button = Assert.IsType<TestTemplatedControl>(window.Content);
window.Show();
window.LayoutManager.ExecuteInitialLayoutPass();
Assert.NotNull(button.Template);
@ -63,6 +64,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
var button = Assert.IsType<TestTemplatedControl>(window.Content);
window.Show();
window.LayoutManager.ExecuteInitialLayoutPass();
Assert.NotNull(button.Template);

Loading…
Cancel
Save