|
|
|
@ -17,8 +17,8 @@ namespace Avalonia.Rendering |
|
|
|
{ |
|
|
|
private SortedDictionary<int, List<IVisual>> _inner = new SortedDictionary<int, List<IVisual>>(); |
|
|
|
private Dictionary<IVisual, int> _index = new Dictionary<IVisual, int>(); |
|
|
|
private List<(DeferredChange change, IVisual visual)> _deferredChanges = new List<(DeferredChange, IVisual)>(); |
|
|
|
private bool _deferring; |
|
|
|
private List<IVisual> _deferredChanges = new List<IVisual>(); |
|
|
|
private int _deferring; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the number of dirty visuals.
|
|
|
|
@ -31,9 +31,9 @@ namespace Avalonia.Rendering |
|
|
|
/// <param name="visual">The dirty visual.</param>
|
|
|
|
public void Add(IVisual visual) |
|
|
|
{ |
|
|
|
if (_deferring) |
|
|
|
if (_deferring > 0) |
|
|
|
{ |
|
|
|
_deferredChanges.Add((DeferredChange.Add, visual)); |
|
|
|
_deferredChanges.Add(visual); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
@ -65,42 +65,23 @@ namespace Avalonia.Rendering |
|
|
|
/// </summary>
|
|
|
|
public void Clear() |
|
|
|
{ |
|
|
|
if (_deferring) |
|
|
|
if (_deferring > 0) |
|
|
|
{ |
|
|
|
_deferredChanges.Add((DeferredChange.Clear, null)); |
|
|
|
return; |
|
|
|
throw new InvalidOperationException("Cannot clear while enumerating"); |
|
|
|
} |
|
|
|
|
|
|
|
_inner.Clear(); |
|
|
|
_index.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Removes a visual from the dirty list.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="visual">The visual.</param>
|
|
|
|
public void Remove(IVisual visual) |
|
|
|
{ |
|
|
|
if (_deferring) |
|
|
|
{ |
|
|
|
_deferredChanges.Add((DeferredChange.Remove, visual)); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (_index.TryGetValue(visual, out var distance)) |
|
|
|
{ |
|
|
|
_inner[distance].Remove(visual); |
|
|
|
_index.Remove(visual); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the dirty visuals, in ascending order of distance to their root.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A collection of visuals.</returns>
|
|
|
|
public IEnumerator<IVisual> GetEnumerator() |
|
|
|
{ |
|
|
|
using (DeferChanges()) |
|
|
|
BeginDefer(); |
|
|
|
try |
|
|
|
{ |
|
|
|
foreach (var i in _inner) |
|
|
|
{ |
|
|
|
@ -110,34 +91,24 @@ namespace Avalonia.Rendering |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
EndDefer(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private DeferDisposer DeferChanges() |
|
|
|
private void BeginDefer() |
|
|
|
{ |
|
|
|
_deferring = true; |
|
|
|
return new DeferDisposer(this); |
|
|
|
++_deferring; |
|
|
|
} |
|
|
|
|
|
|
|
private void EndDefer() |
|
|
|
{ |
|
|
|
if (!_deferring) return; |
|
|
|
if (--_deferring > 0) return; |
|
|
|
|
|
|
|
_deferring = false; |
|
|
|
|
|
|
|
foreach (var change in _deferredChanges) |
|
|
|
foreach (var visual in _deferredChanges) |
|
|
|
{ |
|
|
|
switch (change.change) |
|
|
|
{ |
|
|
|
case DeferredChange.Add: |
|
|
|
Add(change.visual); |
|
|
|
break; |
|
|
|
case DeferredChange.Remove: |
|
|
|
Remove(change.visual); |
|
|
|
break; |
|
|
|
case DeferredChange.Clear: |
|
|
|
Clear(); |
|
|
|
break; |
|
|
|
} |
|
|
|
Add(visual); |
|
|
|
} |
|
|
|
|
|
|
|
_deferredChanges.Clear(); |
|
|
|
@ -148,21 +119,5 @@ namespace Avalonia.Rendering |
|
|
|
/// </summary>
|
|
|
|
/// <returns>A collection of visuals.</returns>
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); |
|
|
|
|
|
|
|
private struct DeferDisposer : IDisposable |
|
|
|
{ |
|
|
|
private DirtyVisuals _parent; |
|
|
|
|
|
|
|
internal DeferDisposer(DirtyVisuals parent) => _parent = parent; |
|
|
|
|
|
|
|
public void Dispose() => _parent?.EndDefer(); |
|
|
|
} |
|
|
|
|
|
|
|
private enum DeferredChange |
|
|
|
{ |
|
|
|
Add, |
|
|
|
Remove, |
|
|
|
Clear |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|