csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
3.1 KiB
104 lines
3.1 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Avalonia.VisualTree;
|
|
|
|
namespace Avalonia.Rendering
|
|
{
|
|
/// <summary>
|
|
/// Stores a list of dirty visuals for an <see cref="IRenderer"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This class stores the dirty visuals for a scene, ordered by their distance to the root
|
|
/// visual. TODO: We probably want to put an upper limit on the number of visuals that can be
|
|
/// stored and if we reach that limit, assume all visuals are dirty.
|
|
/// </remarks>
|
|
internal class DirtyVisuals : IEnumerable<IVisual>
|
|
{
|
|
private SortedDictionary<int, List<IVisual>> _inner = new SortedDictionary<int, List<IVisual>>();
|
|
private Dictionary<IVisual, int> _index = new Dictionary<IVisual, int>();
|
|
private int _enumerating;
|
|
|
|
/// <summary>
|
|
/// Gets the number of dirty visuals.
|
|
/// </summary>
|
|
public int Count => _index.Count;
|
|
|
|
/// <summary>
|
|
/// Adds a visual to the dirty list.
|
|
/// </summary>
|
|
/// <param name="visual">The dirty visual.</param>
|
|
public void Add(IVisual visual)
|
|
{
|
|
if (_enumerating > 0)
|
|
{
|
|
throw new InvalidOperationException("Visual was invalidated during a render pass");
|
|
}
|
|
|
|
var distance = visual.CalculateDistanceFromAncestor(visual.VisualRoot);
|
|
|
|
if (_index.TryGetValue(visual, out var existingDistance))
|
|
{
|
|
if (distance == existingDistance)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_inner[existingDistance].Remove(visual);
|
|
_index.Remove(visual);
|
|
}
|
|
|
|
if (!_inner.TryGetValue(distance, out var list))
|
|
{
|
|
list = new List<IVisual>();
|
|
_inner.Add(distance, list);
|
|
}
|
|
|
|
list.Add(visual);
|
|
_index.Add(visual, distance);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the list.
|
|
/// </summary>
|
|
public void Clear()
|
|
{
|
|
if (_enumerating > 0)
|
|
{
|
|
throw new InvalidOperationException("Cannot clear while enumerating");
|
|
}
|
|
|
|
_inner.Clear();
|
|
_index.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the dirty visuals, in ascending order of distance to their root.
|
|
/// </summary>
|
|
/// <returns>A collection of visuals.</returns>
|
|
public IEnumerator<IVisual> GetEnumerator()
|
|
{
|
|
_enumerating++;
|
|
try
|
|
{
|
|
foreach (var i in _inner)
|
|
{
|
|
foreach (var j in i.Value)
|
|
{
|
|
yield return j;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
_enumerating--;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the dirty visuals, in ascending order of distance to their root.
|
|
/// </summary>
|
|
/// <returns>A collection of visuals.</returns>
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
}
|
|
|