Browse Source
It was only needed for pseudoclasses. Move pseudoclass registration to an engine that doesn't require `AvaloniaProperty.Initialized`, implemented in `PseudoclassEngine`.pull/3292/head
11 changed files with 126 additions and 206 deletions
@ -0,0 +1,120 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Avalonia.Controls; |
||||
|
|
||||
|
namespace Avalonia |
||||
|
{ |
||||
|
internal static class PseudoclassEngine |
||||
|
{ |
||||
|
private static Dictionary<Type, List<IEntry>> _entries = new Dictionary<Type, List<IEntry>>(); |
||||
|
private static Dictionary<AvaloniaProperty, List<IEntry>> _properties = new Dictionary<AvaloniaProperty, List<IEntry>>(); |
||||
|
private static Dictionary<Type, List<IEntry>> _cache = new Dictionary<Type, List<IEntry>>(); |
||||
|
|
||||
|
public static void Created(StyledElement element) |
||||
|
{ |
||||
|
var t = element.GetType(); |
||||
|
|
||||
|
if (!_cache.TryGetValue(t, out var list)) |
||||
|
{ |
||||
|
list = new List<IEntry>(); |
||||
|
|
||||
|
foreach (var i in _entries) |
||||
|
{ |
||||
|
if (i.Key.IsAssignableFrom(t)) |
||||
|
{ |
||||
|
list.AddRange(i.Value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
_cache.Add(t, list); |
||||
|
} |
||||
|
|
||||
|
foreach (var i in list) |
||||
|
{ |
||||
|
i.Update(element); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void Register<T>( |
||||
|
Type type, |
||||
|
AvaloniaProperty<T> property, |
||||
|
Func<T, bool> selector, |
||||
|
string className) |
||||
|
{ |
||||
|
if (!_entries.TryGetValue(type, out var list)) |
||||
|
{ |
||||
|
list = new List<IEntry>(); |
||||
|
_entries.Add(type, list); |
||||
|
} |
||||
|
|
||||
|
var entry = new Entry<T>(type, property, selector, className); |
||||
|
list.Add(entry); |
||||
|
|
||||
|
if (!_properties.TryGetValue(property, out list)) |
||||
|
{ |
||||
|
list = new List<IEntry>(); |
||||
|
_properties.Add(property, list); |
||||
|
property.Changed.Subscribe(ValueChanged); |
||||
|
} |
||||
|
|
||||
|
list.Add(entry); |
||||
|
} |
||||
|
|
||||
|
private static void ValueChanged(AvaloniaPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
if (e.Sender is StyledElement element && |
||||
|
_properties.TryGetValue(e.Property, out var list)) |
||||
|
{ |
||||
|
var t = e.Sender.GetType(); |
||||
|
|
||||
|
foreach (var i in list) |
||||
|
{ |
||||
|
if (i.Type.IsAssignableFrom(t)) |
||||
|
{ |
||||
|
i.Update(element); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private interface IEntry |
||||
|
{ |
||||
|
Type Type { get; } |
||||
|
void Update(StyledElement element); |
||||
|
} |
||||
|
|
||||
|
private class Entry<T> : IEntry |
||||
|
{ |
||||
|
public Entry( |
||||
|
Type type, |
||||
|
AvaloniaProperty<T> property, |
||||
|
Func<T, bool> selector, |
||||
|
string className) |
||||
|
{ |
||||
|
Type = type; |
||||
|
Property = property; |
||||
|
Selector = selector; |
||||
|
ClassName = className; |
||||
|
} |
||||
|
|
||||
|
public Type Type { get; } |
||||
|
public AvaloniaProperty<T> Property { get; } |
||||
|
public Func<T, bool> Selector { get; } |
||||
|
public string ClassName { get; } |
||||
|
|
||||
|
public void Update(StyledElement element) |
||||
|
{ |
||||
|
var value = element.GetValue(Property); |
||||
|
|
||||
|
if (Selector(value)) |
||||
|
{ |
||||
|
((IPseudoClasses)element.Classes).Add(ClassName); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
((IPseudoClasses)element.Classes).Remove(ClassName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue