Browse Source

Tweak measure/arrange algorithm.

To ensure that parent controls are measured/arranged before children.
pull/545/head
Steven Kirk 10 years ago
parent
commit
8e6976a0da
  1. 35
      src/Avalonia.Layout/LayoutManager.cs

35
src/Avalonia.Layout/LayoutManager.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Avalonia.Logging; using Avalonia.Logging;
using Avalonia.Threading; using Avalonia.Threading;
@ -13,8 +14,8 @@ namespace Avalonia.Layout
/// </summary> /// </summary>
public class LayoutManager : ILayoutManager public class LayoutManager : ILayoutManager
{ {
private readonly Queue<ILayoutable> _toMeasure = new Queue<ILayoutable>(); private readonly HashSet<ILayoutable> _toMeasure = new HashSet<ILayoutable>();
private readonly Queue<ILayoutable> _toArrange = new Queue<ILayoutable>(); private readonly HashSet<ILayoutable> _toArrange = new HashSet<ILayoutable>();
private bool _queued; private bool _queued;
private bool _running; private bool _running;
@ -29,8 +30,8 @@ namespace Avalonia.Layout
Contract.Requires<ArgumentNullException>(control != null); Contract.Requires<ArgumentNullException>(control != null);
Dispatcher.UIThread.VerifyAccess(); Dispatcher.UIThread.VerifyAccess();
_toMeasure.Enqueue(control); _toMeasure.Add(control);
_toArrange.Enqueue(control); _toArrange.Add(control);
QueueLayoutPass(); QueueLayoutPass();
} }
@ -40,7 +41,7 @@ namespace Avalonia.Layout
Contract.Requires<ArgumentNullException>(control != null); Contract.Requires<ArgumentNullException>(control != null);
Dispatcher.UIThread.VerifyAccess(); Dispatcher.UIThread.VerifyAccess();
_toArrange.Enqueue(control); _toArrange.Add(control);
QueueLayoutPass(); QueueLayoutPass();
} }
@ -107,7 +108,7 @@ namespace Avalonia.Layout
{ {
while (_toMeasure.Count > 0) while (_toMeasure.Count > 0)
{ {
var next = _toMeasure.Dequeue(); var next = _toMeasure.First();
Measure(next); Measure(next);
} }
} }
@ -116,7 +117,7 @@ namespace Avalonia.Layout
{ {
while (_toArrange.Count > 0 && _toMeasure.Count == 0) while (_toArrange.Count > 0 && _toMeasure.Count == 0)
{ {
var next = _toArrange.Dequeue(); var next = _toArrange.First();
Arrange(next); Arrange(next);
} }
} }
@ -124,29 +125,45 @@ namespace Avalonia.Layout
private void Measure(ILayoutable control) private void Measure(ILayoutable control)
{ {
var root = control as ILayoutRoot; var root = control as ILayoutRoot;
var parent = control.VisualParent as ILayoutable;
if (root != null) if (root != null)
{ {
root.Measure(root.MaxClientSize); root.Measure(root.MaxClientSize);
} }
else if (control.PreviousMeasure.HasValue) else if (parent != null)
{
Measure(parent);
}
if (!control.IsMeasureValid)
{ {
control.Measure(control.PreviousMeasure.Value); control.Measure(control.PreviousMeasure.Value);
} }
_toMeasure.Remove(control);
} }
private void Arrange(ILayoutable control) private void Arrange(ILayoutable control)
{ {
var root = control as ILayoutRoot; var root = control as ILayoutRoot;
var parent = control.VisualParent as ILayoutable;
if (root != null) if (root != null)
{ {
root.Arrange(new Rect(root.DesiredSize)); root.Arrange(new Rect(root.DesiredSize));
} }
else if (control.PreviousArrange.HasValue) else if (parent != null)
{
Measure(parent);
}
if (control.PreviousArrange.HasValue)
{ {
control.Arrange(control.PreviousArrange.Value); control.Arrange(control.PreviousArrange.Value);
} }
_toArrange.Remove(control);
} }
private void QueueLayoutPass() private void QueueLayoutPass()

Loading…
Cancel
Save