Browse Source

Queue controls for another arrange after measure.

If an ancestor control results in a control not being arranged, then we need to queue that control for another arrange pass after the next measure pass.

Fixes #7706.
pull/11233/head
Steven Kirk 4 years ago
parent
commit
7fe8d67374
  1. 27
      src/Avalonia.Base/Layout/LayoutManager.cs

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

@ -21,6 +21,7 @@ namespace Avalonia.Layout
private readonly Layoutable _owner; private readonly Layoutable _owner;
private readonly LayoutQueue<Layoutable> _toMeasure = new LayoutQueue<Layoutable>(v => !v.IsMeasureValid); private readonly LayoutQueue<Layoutable> _toMeasure = new LayoutQueue<Layoutable>(v => !v.IsMeasureValid);
private readonly LayoutQueue<Layoutable> _toArrange = new LayoutQueue<Layoutable>(v => !v.IsArrangeValid); private readonly LayoutQueue<Layoutable> _toArrange = new LayoutQueue<Layoutable>(v => !v.IsArrangeValid);
private readonly List<Layoutable> _toArrangeAfterMeasure = new();
private readonly Action _executeLayoutPass; private readonly Action _executeLayoutPass;
private List<EffectiveViewportChangedListener>? _effectiveViewportChangedListeners; private List<EffectiveViewportChangedListener>? _effectiveViewportChangedListeners;
private bool _disposed; private bool _disposed;
@ -266,9 +267,14 @@ namespace Avalonia.Layout
if (!control.IsArrangeValid) if (!control.IsArrangeValid)
{ {
Arrange(control); if (Arrange(control) == ArrangeResult.AncestorMeasureInvalid)
_toArrangeAfterMeasure.Add(control);
} }
} }
foreach (var i in _toArrangeAfterMeasure)
InvalidateArrange(i);
_toArrangeAfterMeasure.Clear();
} }
private bool Measure(Layoutable control) private bool Measure(Layoutable control)
@ -304,19 +310,19 @@ namespace Avalonia.Layout
return true; return true;
} }
private bool Arrange(Layoutable control) private ArrangeResult Arrange(Layoutable control)
{ {
if (!control.IsVisible || !control.IsAttachedToVisualTree) if (!control.IsVisible || !control.IsAttachedToVisualTree)
return false; return ArrangeResult.NotVisible;
if (control.VisualParent is Layoutable parent) if (control.VisualParent is Layoutable parent)
{ {
if (!Arrange(parent)) if (Arrange(parent) is var parentResult && parentResult != ArrangeResult.Arranged)
return false; return parentResult;
} }
if (!control.IsMeasureValid) if (!control.IsMeasureValid)
return false; return ArrangeResult.AncestorMeasureInvalid;
if (!control.IsArrangeValid) if (!control.IsArrangeValid)
{ {
@ -332,7 +338,7 @@ namespace Avalonia.Layout
} }
} }
return true; return ArrangeResult.Arranged;
} }
private void QueueLayoutPass() private void QueueLayoutPass()
@ -435,5 +441,12 @@ namespace Avalonia.Layout
public Layoutable Listener { get; } public Layoutable Listener { get; }
public Rect Viewport { get; set; } public Rect Viewport { get; set; }
} }
private enum ArrangeResult
{
Arranged,
NotVisible,
AncestorMeasureInvalid,
}
} }
} }

Loading…
Cancel
Save