Removed a number of interfaces.
`IAvaloniaObject`, `IControl`, `ILayoutable`, `IPanel`, `IStyledElement`, `IVisual`.
This commit is contained in:
@@ -293,10 +293,10 @@ namespace ControlCatalog.ViewModels
|
||||
/// <remarks>
|
||||
/// Any one of the parameters may be null, but not both.
|
||||
/// </remarks>
|
||||
private static IVisual GetVisualParent(IVisual? from, IVisual? to)
|
||||
private static Visual GetVisualParent(Visual? from, Visual? to)
|
||||
{
|
||||
var p1 = (from ?? to)!.VisualParent;
|
||||
var p2 = (to ?? from)!.VisualParent;
|
||||
var p1 = (from ?? to)!.GetVisualParent();
|
||||
var p2 = (to ?? from)!.GetVisualParent();
|
||||
|
||||
if (p1 != null && p2 != null && p1 != p2)
|
||||
{
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
|
||||
? new CompositingRenderer(root, AndroidPlatform.Compositor)
|
||||
: AndroidPlatform.Options.UseDeferredRendering
|
||||
? new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService<IRenderLoop>()) { RenderOnlyOnRenderThread = true }
|
||||
: new ImmediateRenderer(root);
|
||||
: new ImmediateRenderer((Visual)root);
|
||||
|
||||
public virtual void Hide()
|
||||
{
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Avalonia.Animation
|
||||
/// <remarks>
|
||||
/// Any one of the parameters may be null, but not both.
|
||||
/// </remarks>
|
||||
protected static IVisual GetVisualParent(IVisual? from, IVisual? to)
|
||||
protected static Visual GetVisualParent(Visual? from, Visual? to)
|
||||
{
|
||||
var p1 = (from ?? to)!.VisualParent;
|
||||
var p2 = (to ?? from)!.VisualParent;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Avalonia
|
||||
/// </summary>
|
||||
/// <typeparam name="TOwner">The owner type.</typeparam>
|
||||
/// <returns>The property.</returns>
|
||||
public new AttachedProperty<TValue> AddOwner<TOwner>() where TOwner : IAvaloniaObject
|
||||
public new AttachedProperty<TValue> AddOwner<TOwner>() where TOwner : AvaloniaObject
|
||||
{
|
||||
AvaloniaPropertyRegistry.Instance.Register(typeof(TOwner), this);
|
||||
return this;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Avalonia
|
||||
/// <remarks>
|
||||
/// This class is analogous to DependencyObject in WPF.
|
||||
/// </remarks>
|
||||
public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged
|
||||
public class AvaloniaObject : IAvaloniaObjectDebug, INotifyPropertyChanged
|
||||
{
|
||||
private readonly ValueStore _values;
|
||||
private AvaloniaObject? _inheritanceParent;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Avalonia
|
||||
/// <remarks>
|
||||
/// The subscription to <paramref name="o"/> is created using a weak reference.
|
||||
/// </remarks>
|
||||
public static IObservable<object?> GetObservable(this IAvaloniaObject o, AvaloniaProperty property)
|
||||
public static IObservable<object?> GetObservable(this AvaloniaObject o, AvaloniaProperty property)
|
||||
{
|
||||
return new AvaloniaPropertyObservable<object?>(
|
||||
o ?? throw new ArgumentNullException(nameof(o)),
|
||||
@@ -56,7 +56,7 @@ namespace Avalonia
|
||||
/// <remarks>
|
||||
/// The subscription to <paramref name="o"/> is created using a weak reference.
|
||||
/// </remarks>
|
||||
public static IObservable<T> GetObservable<T>(this IAvaloniaObject o, AvaloniaProperty<T> property)
|
||||
public static IObservable<T> GetObservable<T>(this AvaloniaObject o, AvaloniaProperty<T> property)
|
||||
{
|
||||
return new AvaloniaPropertyObservable<T>(
|
||||
o ?? throw new ArgumentNullException(nameof(o)),
|
||||
@@ -76,7 +76,7 @@ namespace Avalonia
|
||||
/// The subscription to <paramref name="o"/> is created using a weak reference.
|
||||
/// </remarks>
|
||||
public static IObservable<BindingValue<object?>> GetBindingObservable(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty property)
|
||||
{
|
||||
return new AvaloniaPropertyBindingObservable<object?>(
|
||||
@@ -98,7 +98,7 @@ namespace Avalonia
|
||||
/// The subscription to <paramref name="o"/> is created using a weak reference.
|
||||
/// </remarks>
|
||||
public static IObservable<BindingValue<T>> GetBindingObservable<T>(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty<T> property)
|
||||
{
|
||||
return new AvaloniaPropertyBindingObservable<T>(
|
||||
@@ -115,11 +115,11 @@ namespace Avalonia
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>
|
||||
/// An observable which when subscribed pushes the property changed event args
|
||||
/// each time a <see cref="IAvaloniaObject.PropertyChanged"/> event is raised
|
||||
/// each time a <see cref="AvaloniaObject.PropertyChanged"/> event is raised
|
||||
/// for the specified property.
|
||||
/// </returns>
|
||||
public static IObservable<AvaloniaPropertyChangedEventArgs> GetPropertyChangedObservable(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty property)
|
||||
{
|
||||
return new AvaloniaPropertyChangedObservable(
|
||||
@@ -140,7 +140,7 @@ namespace Avalonia
|
||||
/// property.
|
||||
/// </returns>
|
||||
public static ISubject<object?> GetSubject(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty property,
|
||||
BindingPriority priority = BindingPriority.LocalValue)
|
||||
{
|
||||
@@ -163,7 +163,7 @@ namespace Avalonia
|
||||
/// property.
|
||||
/// </returns>
|
||||
public static ISubject<T> GetSubject<T>(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty<T> property,
|
||||
BindingPriority priority = BindingPriority.LocalValue)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ namespace Avalonia
|
||||
/// property.
|
||||
/// </returns>
|
||||
public static ISubject<BindingValue<object?>> GetBindingSubject(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty property,
|
||||
BindingPriority priority = BindingPriority.LocalValue)
|
||||
{
|
||||
@@ -214,7 +214,7 @@ namespace Avalonia
|
||||
/// property.
|
||||
/// </returns>
|
||||
public static ISubject<BindingValue<T>> GetBindingSubject<T>(
|
||||
this IAvaloniaObject o,
|
||||
this AvaloniaObject o,
|
||||
AvaloniaProperty<T> property,
|
||||
BindingPriority priority = BindingPriority.LocalValue)
|
||||
{
|
||||
@@ -241,7 +241,7 @@ namespace Avalonia
|
||||
/// A disposable which can be used to terminate the binding.
|
||||
/// </returns>
|
||||
public static IDisposable Bind<T>(
|
||||
this IAvaloniaObject target,
|
||||
this AvaloniaObject target,
|
||||
AvaloniaProperty<T> property,
|
||||
IObservable<BindingValue<T>> source,
|
||||
BindingPriority priority = BindingPriority.LocalValue)
|
||||
@@ -250,17 +250,12 @@ namespace Avalonia
|
||||
property = property ?? throw new ArgumentNullException(nameof(property));
|
||||
source = source ?? throw new ArgumentNullException(nameof(source));
|
||||
|
||||
if (target is AvaloniaObject ao)
|
||||
return property switch
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
StyledPropertyBase<T> styled => ao.Bind(styled, source, priority),
|
||||
DirectPropertyBase<T> direct => ao.Bind(direct, source),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type."),
|
||||
};
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
|
||||
StyledPropertyBase<T> styled => target.Bind(styled, source, priority),
|
||||
DirectPropertyBase<T> direct => target.Bind(direct, source),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type."),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -274,22 +269,17 @@ namespace Avalonia
|
||||
/// A disposable which can be used to terminate the binding.
|
||||
/// </returns>
|
||||
public static IDisposable Bind<T>(
|
||||
this IAvaloniaObject target,
|
||||
this AvaloniaObject target,
|
||||
AvaloniaProperty<T> property,
|
||||
IObservable<T> source,
|
||||
BindingPriority priority = BindingPriority.LocalValue)
|
||||
{
|
||||
if (target is AvaloniaObject ao)
|
||||
return property switch
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
StyledPropertyBase<T> styled => ao.Bind(styled, source, priority),
|
||||
DirectPropertyBase<T> direct => ao.Bind(direct, source),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type."),
|
||||
};
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
|
||||
StyledPropertyBase<T> styled => target.Bind(styled, source, priority),
|
||||
DirectPropertyBase<T> direct => target.Bind(direct, source),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type."),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -306,7 +296,7 @@ namespace Avalonia
|
||||
/// </param>
|
||||
/// <returns>An <see cref="IDisposable"/> which can be used to cancel the binding.</returns>
|
||||
public static IDisposable Bind(
|
||||
this IAvaloniaObject target,
|
||||
this AvaloniaObject target,
|
||||
AvaloniaProperty property,
|
||||
IBinding binding,
|
||||
object? anchor = null)
|
||||
@@ -340,23 +330,17 @@ namespace Avalonia
|
||||
/// <param name="target">The object.</param>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public static T GetValue<T>(this IAvaloniaObject target, AvaloniaProperty<T> property)
|
||||
public static T GetValue<T>(this AvaloniaObject target, AvaloniaProperty<T> property)
|
||||
{
|
||||
target = target ?? throw new ArgumentNullException(nameof(target));
|
||||
property = property ?? throw new ArgumentNullException(nameof(property));
|
||||
|
||||
if (target is AvaloniaObject ao)
|
||||
return property switch
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
StyledPropertyBase<T> styled => ao.GetValue(styled),
|
||||
DirectPropertyBase<T> direct => ao.GetValue(direct),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type.")
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
|
||||
StyledPropertyBase<T> styled => target.GetValue(styled),
|
||||
DirectPropertyBase<T> direct => target.GetValue(direct),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type.")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -372,15 +356,13 @@ namespace Avalonia
|
||||
/// For direct properties returns the current value of the property.
|
||||
/// </remarks>
|
||||
public static object? GetBaseValue(
|
||||
this IAvaloniaObject target,
|
||||
this AvaloniaObject target,
|
||||
AvaloniaProperty property)
|
||||
{
|
||||
target = target ?? throw new ArgumentNullException(nameof(target));
|
||||
property = property ?? throw new ArgumentNullException(nameof(property));
|
||||
|
||||
if (target is AvaloniaObject ao)
|
||||
return property.RouteGetBaseValue(ao);
|
||||
throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
|
||||
return property.RouteGetBaseValue(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -396,24 +378,18 @@ namespace Avalonia
|
||||
/// For direct properties returns the current value of the property.
|
||||
/// </remarks>
|
||||
public static Optional<T> GetBaseValue<T>(
|
||||
this IAvaloniaObject target,
|
||||
this AvaloniaObject target,
|
||||
AvaloniaProperty<T> property)
|
||||
{
|
||||
target = target ?? throw new ArgumentNullException(nameof(target));
|
||||
property = property ?? throw new ArgumentNullException(nameof(property));
|
||||
|
||||
if (target is AvaloniaObject ao)
|
||||
return property switch
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
StyledPropertyBase<T> styled => ao.GetBaseValue(styled),
|
||||
DirectPropertyBase<T> direct => ao.GetValue(direct),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type.")
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
|
||||
StyledPropertyBase<T> styled => target.GetBaseValue(styled),
|
||||
DirectPropertyBase<T> direct => target.GetValue(direct),
|
||||
_ => throw new NotSupportedException("Unsupported AvaloniaProperty type.")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -474,7 +450,7 @@ namespace Avalonia
|
||||
}
|
||||
|
||||
public InstancedBinding? Initiate(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty? targetProperty,
|
||||
object? anchor = null,
|
||||
bool enableDataValidation = false)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Avalonia
|
||||
Type valueType,
|
||||
Type ownerType,
|
||||
AvaloniaPropertyMetadata metadata,
|
||||
Action<IAvaloniaObject, bool>? notifying = null)
|
||||
Action<AvaloniaObject, bool>? notifying = null)
|
||||
{
|
||||
_ = name ?? throw new ArgumentNullException(nameof(name));
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Avalonia
|
||||
/// will be true before the property change notifications are sent and false afterwards. This
|
||||
/// callback is intended to support Control.IsDataContextChanging.
|
||||
/// </remarks>
|
||||
public Action<IAvaloniaObject, bool>? Notifying { get; }
|
||||
public Action<AvaloniaObject, bool>? Notifying { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the integer ID that represents this property.
|
||||
@@ -238,9 +238,9 @@ namespace Avalonia
|
||||
bool inherits = false,
|
||||
BindingMode defaultBindingMode = BindingMode.OneWay,
|
||||
Func<TValue, bool>? validate = null,
|
||||
Func<IAvaloniaObject, TValue, TValue>? coerce = null,
|
||||
Action<IAvaloniaObject, bool>? notifying = null)
|
||||
where TOwner : IAvaloniaObject
|
||||
Func<AvaloniaObject, TValue, TValue>? coerce = null,
|
||||
Action<AvaloniaObject, bool>? notifying = null)
|
||||
where TOwner : AvaloniaObject
|
||||
{
|
||||
_ = name ?? throw new ArgumentNullException(nameof(name));
|
||||
|
||||
@@ -279,8 +279,8 @@ namespace Avalonia
|
||||
bool inherits = false,
|
||||
BindingMode defaultBindingMode = BindingMode.OneWay,
|
||||
Func<TValue, bool>? validate = null,
|
||||
Func<IAvaloniaObject, TValue, TValue>? coerce = null)
|
||||
where THost : IAvaloniaObject
|
||||
Func<AvaloniaObject, TValue, TValue>? coerce = null)
|
||||
where THost : AvaloniaObject
|
||||
{
|
||||
_ = name ?? throw new ArgumentNullException(nameof(name));
|
||||
|
||||
@@ -316,8 +316,8 @@ namespace Avalonia
|
||||
bool inherits = false,
|
||||
BindingMode defaultBindingMode = BindingMode.OneWay,
|
||||
Func<TValue, bool>? validate = null,
|
||||
Func<IAvaloniaObject, TValue, TValue>? coerce = null)
|
||||
where THost : IAvaloniaObject
|
||||
Func<AvaloniaObject, TValue, TValue>? coerce = null)
|
||||
where THost : AvaloniaObject
|
||||
{
|
||||
_ = name ?? throw new ArgumentNullException(nameof(name));
|
||||
|
||||
@@ -354,7 +354,7 @@ namespace Avalonia
|
||||
TValue unsetValue = default!,
|
||||
BindingMode defaultBindingMode = BindingMode.OneWay,
|
||||
bool enableDataValidation = false)
|
||||
where TOwner : IAvaloniaObject
|
||||
where TOwner : AvaloniaObject
|
||||
{
|
||||
_ = name ?? throw new ArgumentNullException(nameof(name));
|
||||
_ = getter ?? throw new ArgumentNullException(nameof(getter));
|
||||
@@ -415,7 +415,7 @@ namespace Avalonia
|
||||
/// <returns>
|
||||
/// The property metadata.
|
||||
/// </returns>
|
||||
public AvaloniaPropertyMetadata GetMetadata<T>() where T : IAvaloniaObject
|
||||
public AvaloniaPropertyMetadata GetMetadata<T>() where T : AvaloniaObject
|
||||
{
|
||||
return GetMetadata(typeof(T));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Avalonia
|
||||
public abstract class AvaloniaPropertyChangedEventArgs : EventArgs
|
||||
{
|
||||
public AvaloniaPropertyChangedEventArgs(
|
||||
IAvaloniaObject sender,
|
||||
AvaloniaObject sender,
|
||||
BindingPriority priority)
|
||||
{
|
||||
Sender = sender;
|
||||
@@ -18,7 +18,7 @@ namespace Avalonia
|
||||
}
|
||||
|
||||
internal AvaloniaPropertyChangedEventArgs(
|
||||
IAvaloniaObject sender,
|
||||
AvaloniaObject sender,
|
||||
BindingPriority priority,
|
||||
bool isEffectiveValueChange)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ namespace Avalonia
|
||||
/// Gets the <see cref="AvaloniaObject"/> that the property changed on.
|
||||
/// </summary>
|
||||
/// <value>The sender object.</value>
|
||||
public IAvaloniaObject Sender { get; }
|
||||
public AvaloniaObject Sender { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property that changed.
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Avalonia
|
||||
/// <param name="newValue">The new value of the property.</param>
|
||||
/// <param name="priority">The priority of the binding that produced the value.</param>
|
||||
public AvaloniaPropertyChangedEventArgs(
|
||||
IAvaloniaObject sender,
|
||||
AvaloniaObject sender,
|
||||
AvaloniaProperty<T> property,
|
||||
Optional<T> oldValue,
|
||||
BindingValue<T> newValue,
|
||||
@@ -26,7 +26,7 @@ namespace Avalonia
|
||||
}
|
||||
|
||||
internal AvaloniaPropertyChangedEventArgs(
|
||||
IAvaloniaObject sender,
|
||||
AvaloniaObject sender,
|
||||
AvaloniaProperty<T> property,
|
||||
Optional<T> oldValue,
|
||||
BindingValue<T> newValue,
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace Avalonia
|
||||
/// </summary>
|
||||
/// <param name="o">The object.</param>
|
||||
/// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
|
||||
public IReadOnlyList<AvaloniaProperty> GetRegistered(IAvaloniaObject o)
|
||||
public IReadOnlyList<AvaloniaProperty> GetRegistered(AvaloniaObject o)
|
||||
{
|
||||
_ = o ?? throw new ArgumentNullException(nameof(o));
|
||||
|
||||
@@ -205,7 +205,7 @@ namespace Avalonia
|
||||
/// The registered.
|
||||
/// </returns>
|
||||
public DirectPropertyBase<T> GetRegisteredDirect<T>(
|
||||
IAvaloniaObject o,
|
||||
AvaloniaObject o,
|
||||
DirectPropertyBase<T> property)
|
||||
{
|
||||
return FindRegisteredDirect(o, property) ??
|
||||
@@ -260,7 +260,7 @@ namespace Avalonia
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// The property name contains a '.'.
|
||||
/// </exception>
|
||||
public AvaloniaProperty? FindRegistered(IAvaloniaObject o, string name)
|
||||
public AvaloniaProperty? FindRegistered(AvaloniaObject o, string name)
|
||||
{
|
||||
_ = o ?? throw new ArgumentNullException(nameof(o));
|
||||
_ = name ?? throw new ArgumentNullException(nameof(name));
|
||||
@@ -277,7 +277,7 @@ namespace Avalonia
|
||||
/// The registered property or null if no matching property found.
|
||||
/// </returns>
|
||||
public DirectPropertyBase<T>? FindRegisteredDirect<T>(
|
||||
IAvaloniaObject o,
|
||||
AvaloniaObject o,
|
||||
DirectPropertyBase<T> property)
|
||||
{
|
||||
if (property.Owner == o.GetType())
|
||||
@@ -362,7 +362,7 @@ namespace Avalonia
|
||||
/// <param name="property">The property.</param>
|
||||
/// <remarks>
|
||||
/// You won't usually want to call this method directly, instead use the
|
||||
/// <see cref="AvaloniaProperty.Register{TOwner, TValue}(string, TValue, bool, Data.BindingMode, Func{TValue, bool}, Func{IAvaloniaObject, TValue, TValue}, Action{IAvaloniaObject, bool})"/>
|
||||
/// <see cref="AvaloniaProperty.Register{TOwner, TValue}(string, TValue, bool, Data.BindingMode, Func{TValue, bool}, Func{AvaloniaObject, TValue, TValue}, Action{AvaloniaObject, bool})"/>
|
||||
/// method.
|
||||
/// </remarks>
|
||||
public void Register(Type type, AvaloniaProperty property)
|
||||
@@ -413,7 +413,7 @@ namespace Avalonia
|
||||
/// <param name="property">The property.</param>
|
||||
/// <remarks>
|
||||
/// You won't usually want to call this method directly, instead use the
|
||||
/// <see cref="AvaloniaProperty.RegisterAttached{THost, TValue}(string, Type, TValue, bool, Data.BindingMode, Func{TValue, bool}, Func{IAvaloniaObject, TValue, TValue})"/>
|
||||
/// <see cref="AvaloniaProperty.RegisterAttached{THost, TValue}(string, Type, TValue, bool, Data.BindingMode, Func{TValue, bool}, Func{AvaloniaObject, TValue, TValue})"/>
|
||||
/// method.
|
||||
/// </remarks>
|
||||
public void RegisterAttached(Type type, AvaloniaProperty property)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Avalonia
|
||||
string name,
|
||||
Type ownerType,
|
||||
AvaloniaPropertyMetadata metadata,
|
||||
Action<IAvaloniaObject, bool>? notifying = null)
|
||||
Action<AvaloniaObject, bool>? notifying = null)
|
||||
: base(name, typeof(TValue), ownerType, metadata, notifying)
|
||||
{
|
||||
_changed = new Subject<AvaloniaPropertyChangedEventArgs<TValue>>();
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Avalonia
|
||||
private static readonly Dictionary<string, AvaloniaProperty> s_RegisteredProperties =
|
||||
new Dictionary<string, AvaloniaProperty>();
|
||||
|
||||
public static IDisposable Bind(IStyledElement target, string className, IBinding source, object anchor)
|
||||
public static IDisposable Bind(StyledElement target, string className, IBinding source, object anchor)
|
||||
{
|
||||
if (!s_RegisteredProperties.TryGetValue(className, out var prop))
|
||||
s_RegisteredProperties[className] = prop = RegisterClassProxyProperty(className);
|
||||
@@ -21,7 +21,7 @@ namespace Avalonia
|
||||
var prop = AvaloniaProperty.Register<StyledElement, bool>("__AvaloniaReserved::Classes::" + className);
|
||||
prop.Changed.Subscribe(args =>
|
||||
{
|
||||
var classes = ((IStyledElement)args.Sender).Classes;
|
||||
var classes = ((StyledElement)args.Sender).Classes;
|
||||
classes.Set(className, args.NewValue.GetValueOrDefault());
|
||||
});
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ using Avalonia.Utilities;
|
||||
namespace Avalonia.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds a collection of style classes for an <see cref="IStyledElement"/>.
|
||||
/// Holds a collection of style classes for an <see cref="StyledElement"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Similar to CSS, each control may have any number of styling classes applied.
|
||||
|
||||
@@ -17,6 +17,6 @@ namespace Avalonia.Controls
|
||||
/// Sets the control's inheritance parent.
|
||||
/// </summary>
|
||||
/// <param name="parent">The parent.</param>
|
||||
void SetParent(IAvaloniaObject? parent);
|
||||
void SetParent(AvaloniaObject? parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Reactive;
|
||||
using Avalonia.Styling;
|
||||
|
||||
#nullable enable
|
||||
|
||||
@@ -49,7 +50,7 @@ namespace Avalonia.Controls
|
||||
return true;
|
||||
}
|
||||
|
||||
current = (current as IStyledElement)?.StylingParent as IResourceNode;
|
||||
current = (current as IStyleHost)?.StylingParent as IResourceNode;
|
||||
}
|
||||
|
||||
value = null;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Avalonia.Data
|
||||
public static readonly object DoNothing = new DoNothingType();
|
||||
|
||||
/// <summary>
|
||||
/// Applies an <see cref="InstancedBinding"/> a property on an <see cref="IAvaloniaObject"/>.
|
||||
/// Applies an <see cref="InstancedBinding"/> a property on an <see cref="AvaloniaObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="property">The property to bind.</param>
|
||||
@@ -22,7 +22,7 @@ namespace Avalonia.Data
|
||||
/// </param>
|
||||
/// <returns>An <see cref="IDisposable"/> which can be used to cancel the binding.</returns>
|
||||
public static IDisposable Apply(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty property,
|
||||
InstancedBinding binding,
|
||||
object? anchor)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Avalonia.Data.Core
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Target.TryGetTarget(out var target) && target is IAvaloniaObject obj)
|
||||
if (Target.TryGetTarget(out var target) && target is AvaloniaObject obj)
|
||||
{
|
||||
obj.SetValue(_property, value, priority);
|
||||
return true;
|
||||
@@ -39,7 +39,7 @@ namespace Avalonia.Data.Core
|
||||
|
||||
protected override void StartListeningCore(WeakReference<object?> reference)
|
||||
{
|
||||
if (reference.TryGetTarget(out var target) && target is IAvaloniaObject obj)
|
||||
if (reference.TryGetTarget(out var target) && target is AvaloniaObject obj)
|
||||
{
|
||||
_subscription = new AvaloniaPropertyObservable<object?>(obj, _property).Subscribe(ValueChanged);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Avalonia.Data
|
||||
/// A <see cref="InstancedBinding"/> or null if the binding could not be resolved.
|
||||
/// </returns>
|
||||
InstancedBinding? Initiate(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty? targetProperty,
|
||||
object? anchor = null,
|
||||
bool enableDataValidation = false);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
public class IndexerBinding : IBinding
|
||||
{
|
||||
public IndexerBinding(
|
||||
IAvaloniaObject source,
|
||||
AvaloniaObject source,
|
||||
AvaloniaProperty property,
|
||||
BindingMode mode)
|
||||
{
|
||||
@@ -12,12 +12,12 @@
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
private IAvaloniaObject Source { get; }
|
||||
private AvaloniaObject Source { get; }
|
||||
public AvaloniaProperty Property { get; }
|
||||
private BindingMode Mode { get; }
|
||||
|
||||
public InstancedBinding? Initiate(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty? targetProperty,
|
||||
object? anchor = null,
|
||||
bool enableDataValidation = false)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Avalonia.Data
|
||||
/// <remarks>
|
||||
/// Whereas an <see cref="IBinding"/> holds a description of a binding such as "Bind to the X
|
||||
/// property on a control's DataContext"; this class represents a binding that has been
|
||||
/// *instanced* by calling <see cref="IBinding.Initiate(IAvaloniaObject, AvaloniaProperty, object, bool)"/>
|
||||
/// *instanced* by calling <see cref="IBinding.Initiate(AvaloniaObject, AvaloniaProperty, object, bool)"/>
|
||||
/// on a target object.
|
||||
/// </remarks>
|
||||
public class InstancedBinding
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Avalonia.Diagnostics
|
||||
public interface IAvaloniaObjectDebug
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the subscriber list for the <see cref="IAvaloniaObject.PropertyChanged"/>
|
||||
/// Gets the subscriber list for the <see cref="AvaloniaObject.PropertyChanged"/>
|
||||
/// event.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Avalonia
|
||||
/// allows the avalonia property system to read and write the current value.
|
||||
/// </remarks>
|
||||
public class DirectProperty<TOwner, TValue> : DirectPropertyBase<TValue>, IDirectPropertyAccessor
|
||||
where TOwner : IAvaloniaObject
|
||||
where TOwner : AvaloniaObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DirectProperty{TOwner, TValue}"/> class.
|
||||
@@ -151,13 +151,13 @@ namespace Avalonia
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override TValue InvokeGetter(IAvaloniaObject instance)
|
||||
internal override TValue InvokeGetter(AvaloniaObject instance)
|
||||
{
|
||||
return Getter((TOwner)instance);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override void InvokeSetter(IAvaloniaObject instance, BindingValue<TValue> value)
|
||||
internal override void InvokeSetter(AvaloniaObject instance, BindingValue<TValue> value)
|
||||
{
|
||||
if (Setter == null)
|
||||
{
|
||||
@@ -171,13 +171,13 @@ namespace Avalonia
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
object? IDirectPropertyAccessor.GetValue(IAvaloniaObject instance)
|
||||
object? IDirectPropertyAccessor.GetValue(AvaloniaObject instance)
|
||||
{
|
||||
return Getter((TOwner)instance);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IDirectPropertyAccessor.SetValue(IAvaloniaObject instance, object? value)
|
||||
void IDirectPropertyAccessor.SetValue(AvaloniaObject instance, object? value)
|
||||
{
|
||||
if (Setter == null)
|
||||
{
|
||||
|
||||
@@ -54,14 +54,14 @@ namespace Avalonia
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
internal abstract TValue InvokeGetter(IAvaloniaObject instance);
|
||||
internal abstract TValue InvokeGetter(AvaloniaObject instance);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the property on the instance.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
internal abstract void InvokeSetter(IAvaloniaObject instance, BindingValue<TValue> value);
|
||||
internal abstract void InvokeSetter(AvaloniaObject instance, BindingValue<TValue> value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unset value for the property on the specified type.
|
||||
@@ -91,7 +91,7 @@ namespace Avalonia
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type.</typeparam>
|
||||
/// <param name="metadata">The metadata.</param>
|
||||
public void OverrideMetadata<T>(DirectPropertyMetadata<TValue> metadata) where T : IAvaloniaObject
|
||||
public void OverrideMetadata<T>(DirectPropertyMetadata<TValue> metadata) where T : AvaloniaObject
|
||||
{
|
||||
base.OverrideMetadata(typeof(T), metadata);
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
using System;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Avalonia
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for getting/setting <see cref="AvaloniaProperty"/> values on an object.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface IAvaloniaObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised when a <see cref="AvaloniaProperty"/> value changes on this object.
|
||||
/// </summary>
|
||||
event EventHandler<AvaloniaPropertyChangedEventArgs>? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Clears an <see cref="AvaloniaProperty"/>'s local value.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
void ClearValue(AvaloniaProperty property);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="AvaloniaProperty"/> value.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>The value.</returns>
|
||||
object? GetValue(AvaloniaProperty property);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a <see cref="AvaloniaProperty"/> is animating.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>True if the property is animating, otherwise false.</returns>
|
||||
bool IsAnimating(AvaloniaProperty property);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a <see cref="AvaloniaProperty"/> is set on this object.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>True if the property is set, otherwise false.</returns>
|
||||
bool IsSet(AvaloniaProperty property);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a <see cref="AvaloniaProperty"/> value.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="priority">The priority of the value.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="IDisposable"/> if setting the property can be undone, otherwise null.
|
||||
/// </returns>
|
||||
IDisposable? SetValue(
|
||||
AvaloniaProperty property,
|
||||
object? value,
|
||||
BindingPriority priority = BindingPriority.LocalValue);
|
||||
|
||||
/// <summary>
|
||||
/// Binds a <see cref="AvaloniaProperty"/> to an observable.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <param name="source">The observable.</param>
|
||||
/// <param name="priority">The priority of the binding.</param>
|
||||
/// <returns>
|
||||
/// A disposable which can be used to terminate the binding.
|
||||
/// </returns>
|
||||
IDisposable Bind(
|
||||
AvaloniaProperty property,
|
||||
IObservable<object?> source,
|
||||
BindingPriority priority = BindingPriority.LocalValue);
|
||||
|
||||
/// <summary>
|
||||
/// Coerces the specified <see cref="AvaloniaProperty"/>.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
void CoerceValue(AvaloniaProperty property);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Avalonia
|
||||
/// Defines an element with a data context that can be used for binding.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface IDataContextProvider : IAvaloniaObject
|
||||
public interface IDataContextProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the element's data context.
|
||||
|
||||
@@ -24,13 +24,13 @@ namespace Avalonia
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <returns>The property value.</returns>
|
||||
object? GetValue(IAvaloniaObject instance);
|
||||
object? GetValue(AvaloniaObject instance);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the property on the instance.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void SetValue(IAvaloniaObject instance, object? value);
|
||||
void SetValue(AvaloniaObject instance, object? value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Avalonia
|
||||
{
|
||||
[NotClientImplementable]
|
||||
public interface IStyledElement :
|
||||
IStyleable,
|
||||
IStyleHost,
|
||||
ILogical,
|
||||
IResourceHost,
|
||||
IDataContextProvider,
|
||||
ISupportInitialize
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when the control has finished initialization.
|
||||
/// </summary>
|
||||
event EventHandler? Initialized;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the element has finished initialization.
|
||||
/// </summary>
|
||||
bool IsInitialized { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the control's styling classes.
|
||||
/// </summary>
|
||||
new Classes Classes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the control's logical parent.
|
||||
/// </summary>
|
||||
IStyledElement? Parent { get; }
|
||||
}
|
||||
}
|
||||
@@ -182,13 +182,13 @@ namespace Avalonia.Input
|
||||
// find all controls who have registered that access key.
|
||||
var text = e.Key.ToString().ToUpper();
|
||||
var matches = _registered
|
||||
.Where(x => x.Item1 == text && x.Item2.IsEffectivelyVisible)
|
||||
.Where(x => x.Item1 == text && ((Visual)x.Item2).IsEffectivelyVisible)
|
||||
.Select(x => x.Item2);
|
||||
|
||||
// If the menu is open, only match controls in the menu's visual tree.
|
||||
if (menuIsOpen)
|
||||
{
|
||||
matches = matches.Where(x => x is not null && MainMenu!.IsVisualAncestorOf(x));
|
||||
matches = matches.Where(x => x is not null && ((Visual)MainMenu!).IsVisualAncestorOf((Visual)x));
|
||||
}
|
||||
|
||||
var match = matches.FirstOrDefault();
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace Avalonia.Input
|
||||
|
||||
private Interactive? GetTarget(IInputRoot root, Point local)
|
||||
{
|
||||
var target = root.InputHitTest(local)?.GetSelfAndVisualAncestors()?.OfType<Interactive>()?.FirstOrDefault();
|
||||
var hit = root.InputHitTest(local) as Visual;
|
||||
var target = hit?.GetSelfAndVisualAncestors()?.OfType<Interactive>()?.FirstOrDefault();
|
||||
if (target != null && DragDrop.GetAllowDrop(target))
|
||||
return target;
|
||||
return null;
|
||||
@@ -24,7 +25,7 @@ namespace Avalonia.Input
|
||||
if (target == null)
|
||||
return DragDropEffects.None;
|
||||
|
||||
var p = inputRoot.TranslatePoint(point, target);
|
||||
var p = ((Visual)inputRoot).TranslatePoint(point, target);
|
||||
|
||||
if (!p.HasValue)
|
||||
return DragDropEffects.None;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Avalonia.Input
|
||||
|
||||
public KeyModifiers KeyModifiers { get; private set; }
|
||||
|
||||
public Point GetPosition(IVisual relativeTo)
|
||||
public Point GetPosition(Visual relativeTo)
|
||||
{
|
||||
var point = new Point(0, 0);
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace Avalonia.Input
|
||||
/// </summary>
|
||||
/// <param name="e">The element.</param>
|
||||
/// <returns>True if the element can be focused.</returns>
|
||||
private static bool CanFocus(IInputElement e) => e.Focusable && e.IsEffectivelyEnabled && e.IsVisible;
|
||||
private static bool CanFocus(IInputElement e) => e.Focusable && e.IsEffectivelyEnabled && IsVisible(e);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the focus scope ancestors of the specified control, traversing popups.
|
||||
@@ -198,14 +198,15 @@ namespace Avalonia.Input
|
||||
|
||||
while (c != null)
|
||||
{
|
||||
var scope = c as IFocusScope;
|
||||
|
||||
if (scope != null && c.VisualRoot?.IsVisible == true)
|
||||
if (c is IFocusScope scope &&
|
||||
c is Visual v &&
|
||||
v.VisualRoot is Visual root &&
|
||||
root.IsVisible)
|
||||
{
|
||||
yield return scope;
|
||||
}
|
||||
|
||||
c = c.GetVisualParent<IInputElement>() ??
|
||||
c = (c as Visual)?.GetVisualParent<IInputElement>() ??
|
||||
((c as IHostedVisualTreeRoot)?.Host as IInputElement);
|
||||
}
|
||||
}
|
||||
@@ -221,11 +222,11 @@ namespace Avalonia.Input
|
||||
return;
|
||||
|
||||
var ev = (PointerPressedEventArgs)e;
|
||||
var visual = (IVisual)sender;
|
||||
var visual = (Visual)sender;
|
||||
|
||||
if (sender == e.Source && ev.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
IVisual? element = ev.Pointer?.Captured ?? e.Source as IInputElement;
|
||||
Visual? element = ev.Pointer?.Captured as Visual ?? e.Source as Visual;
|
||||
|
||||
while (element != null)
|
||||
{
|
||||
@@ -240,5 +241,7 @@ namespace Avalonia.Input
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsVisible(IInputElement e) => (e as Visual)?.IsVisible ?? true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace Avalonia.Input.GestureRecognizers
|
||||
if (_inputElement is ILogical logicalParent && recognizer is ISetLogicalParent logical)
|
||||
{
|
||||
logical.SetParent(logicalParent);
|
||||
if (recognizer is IStyleable styleableRecognizer
|
||||
&& _inputElement is IStyleable styleableParent)
|
||||
if (recognizer is StyledElement styleableRecognizer
|
||||
&& _inputElement is StyledElement styleableParent)
|
||||
styleableRecognizer.Bind(StyledElement.TemplatedParentProperty,
|
||||
styleableParent.GetObservable(StyledElement.TemplatedParentProperty));
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Avalonia.Input.GestureRecognizers
|
||||
EndGesture();
|
||||
_tracking = e.Pointer;
|
||||
_gestureId = ScrollGestureEventArgs.GetNextFreeId();
|
||||
_trackedRootPoint = e.GetPosition(_target);
|
||||
_trackedRootPoint = e.GetPosition((Visual?)_target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Avalonia.Input.GestureRecognizers
|
||||
{
|
||||
if (e.Pointer == _tracking)
|
||||
{
|
||||
var rootPoint = e.GetPosition(_target);
|
||||
var rootPoint = e.GetPosition((Visual?)_target);
|
||||
if (!_scrolling)
|
||||
{
|
||||
if (CanHorizontallyScroll && Math.Abs(_trackedRootPoint.X - rootPoint.X) > ScrollStartDistance)
|
||||
|
||||
@@ -92,13 +92,13 @@ namespace Avalonia.Input
|
||||
if (ev.Route == RoutingStrategies.Bubble)
|
||||
{
|
||||
var e = (PointerPressedEventArgs)ev;
|
||||
var visual = (IVisual)ev.Source;
|
||||
var visual = (Visual)ev.Source;
|
||||
|
||||
if (e.ClickCount % 2 == 1)
|
||||
{
|
||||
s_isDoubleTapped = false;
|
||||
s_lastPress.SetTarget(ev.Source);
|
||||
s_lastPressPoint = e.GetPosition((IVisual)ev.Source);
|
||||
s_lastPressPoint = e.GetPosition((Visual)ev.Source);
|
||||
}
|
||||
else if (e.ClickCount % 2 == 0 && e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
@@ -121,7 +121,7 @@ namespace Avalonia.Input
|
||||
target == e.Source &&
|
||||
e.InitialPressMouseButton is MouseButton.Left or MouseButton.Right)
|
||||
{
|
||||
var point = e.GetCurrentPoint((IVisual)target);
|
||||
var point = e.GetCurrentPoint((Visual)target);
|
||||
var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
|
||||
var tapSize = settings?.GetTapSize(point.Pointer.Type) ?? new Size(4, 4);
|
||||
var tapRect = new Rect(s_lastPressPoint, new Size())
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Avalonia.Input
|
||||
/// Defines input-related functionality for a control.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface IInputElement : IInteractive, IVisual
|
||||
public interface IInputElement : IInteractive
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when the control receives focus.
|
||||
@@ -93,7 +93,12 @@ namespace Avalonia.Input
|
||||
/// <see cref="IsEnabled"/> value of this control and its parent controls.
|
||||
/// </remarks>
|
||||
bool IsEffectivelyEnabled { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this control and all its parents are visible.
|
||||
/// </summary>
|
||||
bool IsEffectivelyVisible { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether keyboard focus is anywhere within the element or its visual tree child elements.
|
||||
/// </summary>
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Avalonia.Input
|
||||
/// Defines the interface for a window's main menu.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface IMainMenu : IVisual
|
||||
public interface IMainMenu
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the menu is open.
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Avalonia.Input
|
||||
/// </summary>
|
||||
public static class InputExtensions
|
||||
{
|
||||
private static readonly Func<IVisual, bool> s_hitTestDelegate = IsHitTestVisible;
|
||||
private static readonly Func<Visual, bool> s_hitTestDelegate = IsHitTestVisible;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the active input elements at a point on an <see cref="IInputElement"/>.
|
||||
@@ -26,7 +26,8 @@ namespace Avalonia.Input
|
||||
{
|
||||
element = element ?? throw new ArgumentNullException(nameof(element));
|
||||
|
||||
return element.GetVisualsAt(p, s_hitTestDelegate).Cast<IInputElement>();
|
||||
return (element as Visual)?.GetVisualsAt(p, s_hitTestDelegate).Cast<IInputElement>() ??
|
||||
Enumerable.Empty<IInputElement>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -39,7 +40,7 @@ namespace Avalonia.Input
|
||||
{
|
||||
element = element ?? throw new ArgumentNullException(nameof(element));
|
||||
|
||||
return element.GetVisualAt(p, s_hitTestDelegate) as IInputElement;
|
||||
return (element as Visual)?.GetVisualAt(p, s_hitTestDelegate) as IInputElement;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,22 +56,22 @@ namespace Avalonia.Input
|
||||
public static IInputElement? InputHitTest(
|
||||
this IInputElement element,
|
||||
Point p,
|
||||
Func<IVisual, bool> filter)
|
||||
Func<Visual, bool> filter)
|
||||
{
|
||||
element = element ?? throw new ArgumentNullException(nameof(element));
|
||||
filter = filter ?? throw new ArgumentNullException(nameof(filter));
|
||||
|
||||
return element.GetVisualAt(p, x => s_hitTestDelegate(x) && filter(x)) as IInputElement;
|
||||
return (element as Visual)?.GetVisualAt(p, x => s_hitTestDelegate(x) && filter(x)) as IInputElement;
|
||||
}
|
||||
|
||||
private static bool IsHitTestVisible(IVisual visual)
|
||||
private static bool IsHitTestVisible(Visual visual)
|
||||
{
|
||||
var element = visual as IInputElement;
|
||||
return element != null &&
|
||||
element.IsVisible &&
|
||||
visual.IsVisible &&
|
||||
element.IsHitTestVisible &&
|
||||
element.IsEffectivelyEnabled &&
|
||||
element.IsAttachedToVisualTree;
|
||||
visual.IsAttachedToVisualTree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Runtime.CompilerServices;
|
||||
using Avalonia.Input.Raw;
|
||||
using Avalonia.Input.TextInput;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Avalonia.Input
|
||||
{
|
||||
@@ -37,18 +36,21 @@ namespace Avalonia.Input
|
||||
ie.IsKeyboardFocusWithin = false;
|
||||
}
|
||||
|
||||
el = (IInputElement?)el.VisualParent;
|
||||
el = (IInputElement?)(el as Visual)?.VisualParent;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearFocusWithin(IInputElement element, bool clearRoot)
|
||||
{
|
||||
foreach (var visual in element.VisualChildren)
|
||||
if (element is Visual v)
|
||||
{
|
||||
if (visual is IInputElement el && el.IsKeyboardFocusWithin)
|
||||
foreach (var visual in v.VisualChildren)
|
||||
{
|
||||
ClearFocusWithin(el, true);
|
||||
break;
|
||||
if (visual is IInputElement el && el.IsKeyboardFocusWithin)
|
||||
{
|
||||
ClearFocusWithin(el, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ namespace Avalonia.Input
|
||||
break;
|
||||
}
|
||||
|
||||
el = el.VisualParent as IInputElement;
|
||||
el = (el as Visual)?.VisualParent as IInputElement;
|
||||
}
|
||||
|
||||
el = oldElement;
|
||||
@@ -100,18 +102,21 @@ namespace Avalonia.Input
|
||||
ie.IsKeyboardFocusWithin = true;
|
||||
}
|
||||
|
||||
el = el.VisualParent as IInputElement;
|
||||
el = (el as Visual)?.VisualParent as IInputElement;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearChildrenFocusWithin(IInputElement element, bool clearRoot)
|
||||
{
|
||||
foreach (var visual in element.VisualChildren)
|
||||
if (element is Visual v)
|
||||
{
|
||||
if (visual is IInputElement el && el.IsKeyboardFocusWithin)
|
||||
foreach (var visual in v.VisualChildren)
|
||||
{
|
||||
ClearChildrenFocusWithin(el, true);
|
||||
break;
|
||||
if (visual is IInputElement el && el.IsKeyboardFocusWithin)
|
||||
{
|
||||
ClearChildrenFocusWithin(el, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +136,8 @@ namespace Avalonia.Input
|
||||
var interactive = FocusedElement as IInteractive;
|
||||
|
||||
if (FocusedElement != null &&
|
||||
(!FocusedElement.IsAttachedToVisualTree ||
|
||||
_focusedRoot != element?.VisualRoot as IInputRoot) &&
|
||||
(!((Visual)FocusedElement).IsAttachedToVisualTree ||
|
||||
_focusedRoot != ((Visual?)element)?.VisualRoot as IInputRoot) &&
|
||||
_focusedRoot != null)
|
||||
{
|
||||
ClearChildrenFocusWithin(_focusedRoot, true);
|
||||
@@ -140,7 +145,7 @@ namespace Avalonia.Input
|
||||
|
||||
SetIsFocusWithin(FocusedElement, element);
|
||||
_focusedElement = element;
|
||||
_focusedRoot = _focusedElement?.VisualRoot as IInputRoot;
|
||||
_focusedRoot = ((Visual?)_focusedElement)?.VisualRoot as IInputRoot;
|
||||
|
||||
interactive?.RaiseEvent(new RoutedEventArgs
|
||||
{
|
||||
@@ -191,8 +196,8 @@ namespace Avalonia.Input
|
||||
KeyModifiers = keyInput.Modifiers.ToKeyModifiers(),
|
||||
Source = element,
|
||||
};
|
||||
|
||||
IVisual? currentHandler = element;
|
||||
|
||||
var currentHandler = element as Visual;
|
||||
while (currentHandler != null && !ev.Handled && keyInput.Type == RawKeyEventType.KeyDown)
|
||||
{
|
||||
var bindings = (currentHandler as IInputElement)?.KeyBindings;
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Avalonia.Input
|
||||
/// <param name="value">The tab index.</param>
|
||||
public static void SetTabIndex(IInputElement element, int value)
|
||||
{
|
||||
((IAvaloniaObject)element).SetValue(TabIndexProperty, value);
|
||||
((AvaloniaObject)element).SetValue(TabIndexProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Avalonia.Input
|
||||
element = element ?? throw new ArgumentNullException(nameof(element));
|
||||
|
||||
// If there's a custom keyboard navigation handler as an ancestor, use that.
|
||||
var custom = element.FindAncestorOfType<ICustomKeyboardNavigation>(true);
|
||||
var custom = (element as Visual)?.FindAncestorOfType<ICustomKeyboardNavigation>(true);
|
||||
if (custom is object && HandlePreCustomNavigation(custom, element, direction, out var ce))
|
||||
return ce;
|
||||
|
||||
@@ -156,9 +156,9 @@ namespace Avalonia.Input
|
||||
NavigationDirection direction,
|
||||
[NotNullWhen(true)] out IInputElement? result)
|
||||
{
|
||||
if (newElement is object)
|
||||
if (newElement is Visual v)
|
||||
{
|
||||
var customHandler = newElement.FindAncestorOfType<ICustomKeyboardNavigation>(true);
|
||||
var customHandler = v.FindAncestorOfType<ICustomKeyboardNavigation>(true);
|
||||
|
||||
if (customHandler is object)
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Avalonia.Input
|
||||
_lastClickRect = new Rect(p, new Size())
|
||||
.Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
|
||||
_lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton();
|
||||
var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount);
|
||||
var e = new PointerPressedEventArgs(source, _pointer, (Visual)root, p, timestamp, properties, inputModifiers, _clickCount);
|
||||
source.RaiseEvent(e);
|
||||
return e.Handled;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ namespace Avalonia.Input
|
||||
|
||||
if (source is object)
|
||||
{
|
||||
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root,
|
||||
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)root,
|
||||
p, timestamp, properties, inputModifiers, intermediatePoints);
|
||||
|
||||
source.RaiseEvent(e);
|
||||
@@ -181,7 +181,7 @@ namespace Avalonia.Input
|
||||
|
||||
if (source is not null)
|
||||
{
|
||||
var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers,
|
||||
var e = new PointerReleasedEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers,
|
||||
_lastMouseDownButton);
|
||||
|
||||
source?.RaiseEvent(e);
|
||||
@@ -204,7 +204,7 @@ namespace Avalonia.Input
|
||||
|
||||
if (source is not null)
|
||||
{
|
||||
var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta);
|
||||
var e = new PointerWheelEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
|
||||
|
||||
source?.RaiseEvent(e);
|
||||
return e.Handled;
|
||||
@@ -224,7 +224,7 @@ namespace Avalonia.Input
|
||||
if (source != null)
|
||||
{
|
||||
var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureMagnifyEvent, source,
|
||||
_pointer, root, p, timestamp, props, inputModifiers, delta);
|
||||
_pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
|
||||
|
||||
source?.RaiseEvent(e);
|
||||
return e.Handled;
|
||||
@@ -244,7 +244,7 @@ namespace Avalonia.Input
|
||||
if (source != null)
|
||||
{
|
||||
var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureRotateEvent, source,
|
||||
_pointer, root, p, timestamp, props, inputModifiers, delta);
|
||||
_pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
|
||||
|
||||
source?.RaiseEvent(e);
|
||||
return e.Handled;
|
||||
@@ -264,7 +264,7 @@ namespace Avalonia.Input
|
||||
if (source != null)
|
||||
{
|
||||
var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureSwipeEvent, source,
|
||||
_pointer, root, p, timestamp, props, inputModifiers, delta);
|
||||
_pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
|
||||
|
||||
source?.RaiseEvent(e);
|
||||
return e.Handled;
|
||||
|
||||
@@ -10,13 +10,21 @@ namespace Avalonia.Input.Navigation
|
||||
/// </summary>
|
||||
/// <param name="e">The element.</param>
|
||||
/// <returns>True if the element can be focused.</returns>
|
||||
public static bool CanFocus(this IInputElement e) => e.Focusable && e.IsEffectivelyEnabled && e.IsVisible;
|
||||
public static bool CanFocus(this IInputElement e)
|
||||
{
|
||||
var visible = (e as Visual)?.IsVisible ?? true;
|
||||
return e.Focusable && e.IsEffectivelyEnabled && visible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if descendants of the specified element can be focused.
|
||||
/// </summary>
|
||||
/// <param name="e">The element.</param>
|
||||
/// <returns>True if descendants of the element can be focused.</returns>
|
||||
public static bool CanFocusDescendants(this IInputElement e) => e.IsEffectivelyEnabled && e.IsVisible;
|
||||
public static bool CanFocusDescendants(this IInputElement e)
|
||||
{
|
||||
var visible = (e as Visual)?.IsVisible ?? true;
|
||||
return e.IsEffectivelyEnabled && visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,9 +212,10 @@ namespace Avalonia.Input.Navigation
|
||||
if (!IsFocusScope(e))
|
||||
{
|
||||
// Verify if focusedElement is a visual descendant of e
|
||||
if (focusedElement is IVisual visualFocusedElement &&
|
||||
if (focusedElement is Visual visualFocusedElement &&
|
||||
e is Visual v &&
|
||||
visualFocusedElement != e &&
|
||||
e.IsVisualAncestorOf(visualFocusedElement))
|
||||
v.IsVisualAncestorOf(visualFocusedElement))
|
||||
{
|
||||
return focusedElement;
|
||||
}
|
||||
@@ -236,7 +237,7 @@ namespace Avalonia.Input.Navigation
|
||||
|
||||
if (uiElement is null || IsVisibleAndEnabled(uiElement))
|
||||
{
|
||||
if (e is IVisual elementAsVisual)
|
||||
if (e is Visual elementAsVisual)
|
||||
{
|
||||
var children = elementAsVisual.VisualChildren;
|
||||
var count = children.Count;
|
||||
@@ -272,7 +273,7 @@ namespace Avalonia.Input.Navigation
|
||||
|
||||
if (uiElement == null || IsVisibleAndEnabled(uiElement))
|
||||
{
|
||||
var elementAsVisual = e as IVisual;
|
||||
var elementAsVisual = e as Visual;
|
||||
|
||||
if (elementAsVisual != null)
|
||||
{
|
||||
@@ -385,7 +386,7 @@ namespace Avalonia.Input.Navigation
|
||||
|
||||
private static IInputElement? GetNextSibling(IInputElement e)
|
||||
{
|
||||
if (GetParent(e) is IVisual parentAsVisual && e is IVisual elementAsVisual)
|
||||
if (GetParent(e) is Visual parentAsVisual && e is Visual elementAsVisual)
|
||||
{
|
||||
var children = parentAsVisual.VisualChildren;
|
||||
var count = children.Count;
|
||||
@@ -589,7 +590,7 @@ namespace Avalonia.Input.Navigation
|
||||
|
||||
private static IInputElement? GetPreviousSibling(IInputElement e)
|
||||
{
|
||||
if (GetParent(e) is IVisual parentAsVisual && e is IVisual elementAsVisual)
|
||||
if (GetParent(e) is Visual parentAsVisual && e is Visual elementAsVisual)
|
||||
{
|
||||
var children = parentAsVisual.VisualChildren;
|
||||
var count = children.Count;
|
||||
@@ -646,7 +647,7 @@ namespace Avalonia.Input.Navigation
|
||||
private static IInputElement? GetParent(IInputElement e)
|
||||
{
|
||||
// For Visual - go up the visual parent chain until we find Visual.
|
||||
if (e is IVisual v)
|
||||
if (e is Visual v)
|
||||
return v.FindAncestorOfType<IInputElement>();
|
||||
|
||||
// This will need to be implemented when we have non-visual input elements.
|
||||
@@ -669,6 +670,7 @@ namespace Avalonia.Input.Navigation
|
||||
}
|
||||
|
||||
private static bool IsTabStopOrGroup(IInputElement e) => IsTabStop(e) || IsGroup(e);
|
||||
private static bool IsVisibleAndEnabled(IInputElement e) => e.IsVisible && e.IsEnabled;
|
||||
private static bool IsVisible(IInputElement e) => (e as Visual)?.IsVisible ?? true;
|
||||
private static bool IsVisibleAndEnabled(IInputElement e) => IsVisible(e) && e.IsEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Avalonia.Input
|
||||
_lastClickRect = new Rect(p, new Size())
|
||||
.Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
|
||||
_lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton();
|
||||
var e = new PointerPressedEventArgs(source, pointer, root, p, timestamp, properties, inputModifiers, _clickCount);
|
||||
var e = new PointerPressedEventArgs(source, pointer, (Visual)root, p, timestamp, properties, inputModifiers, _clickCount);
|
||||
source.RaiseEvent(e);
|
||||
return e.Handled;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ namespace Avalonia.Input
|
||||
|
||||
if (source is not null)
|
||||
{
|
||||
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, root,
|
||||
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, (Visual)root,
|
||||
p, timestamp, properties, inputModifiers, intermediatePoints);
|
||||
|
||||
source.RaiseEvent(e);
|
||||
@@ -126,7 +126,7 @@ namespace Avalonia.Input
|
||||
|
||||
if (source is not null)
|
||||
{
|
||||
var e = new PointerReleasedEventArgs(source, pointer, root, p, timestamp, properties, inputModifiers,
|
||||
var e = new PointerReleasedEventArgs(source, pointer, (Visual)root, p, timestamp, properties, inputModifiers,
|
||||
_lastMouseDownButton);
|
||||
|
||||
source?.RaiseEvent(e);
|
||||
|
||||
@@ -21,10 +21,10 @@ namespace Avalonia.Input
|
||||
|
||||
IInputElement? FindCommonParent(IInputElement? control1, IInputElement? control2)
|
||||
{
|
||||
if (control1 == null || control2 == null)
|
||||
if (control1 is not Visual c1 || control2 is not Visual c2)
|
||||
return null;
|
||||
var seen = new HashSet<IInputElement>(control1.GetSelfAndVisualAncestors().OfType<IInputElement>());
|
||||
return control2.GetSelfAndVisualAncestors().OfType<IInputElement>().FirstOrDefault(seen.Contains);
|
||||
var seen = new HashSet<IInputElement>(c1.GetSelfAndVisualAncestors().OfType<IInputElement>());
|
||||
return c2.GetSelfAndVisualAncestors().OfType<IInputElement>().FirstOrDefault(seen.Contains);
|
||||
}
|
||||
|
||||
protected virtual void PlatformCapture(IInputElement? element)
|
||||
@@ -34,15 +34,15 @@ namespace Avalonia.Input
|
||||
|
||||
public void Capture(IInputElement? control)
|
||||
{
|
||||
if (Captured != null)
|
||||
Captured.DetachedFromVisualTree -= OnCaptureDetached;
|
||||
if (Captured is Visual v1)
|
||||
v1.DetachedFromVisualTree -= OnCaptureDetached;
|
||||
var oldCapture = Captured;
|
||||
Captured = control;
|
||||
PlatformCapture(control);
|
||||
if (oldCapture != null)
|
||||
if (oldCapture is Visual v2)
|
||||
{
|
||||
var commonParent = FindCommonParent(control, oldCapture);
|
||||
foreach (var notifyTarget in oldCapture.GetSelfAndVisualAncestors().OfType<IInputElement>())
|
||||
foreach (var notifyTarget in v2.GetSelfAndVisualAncestors().OfType<IInputElement>())
|
||||
{
|
||||
if (notifyTarget == commonParent)
|
||||
break;
|
||||
@@ -50,11 +50,11 @@ namespace Avalonia.Input
|
||||
}
|
||||
}
|
||||
|
||||
if (Captured != null)
|
||||
Captured.DetachedFromVisualTree += OnCaptureDetached;
|
||||
if (Captured is Visual v3)
|
||||
v3.DetachedFromVisualTree += OnCaptureDetached;
|
||||
}
|
||||
|
||||
IInputElement? GetNextCapture(IVisual parent)
|
||||
IInputElement? GetNextCapture(Visual parent)
|
||||
{
|
||||
return parent as IInputElement ?? parent.FindAncestorOfType<IInputElement>();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Avalonia.Input
|
||||
public Vector Delta { get; set; }
|
||||
|
||||
internal PointerDeltaEventArgs(RoutedEvent routedEvent, IInteractive? source,
|
||||
IPointer pointer, IVisual rootVisual, Point rootVisualPosition, ulong timestamp,
|
||||
IPointer pointer, Visual rootVisual, Point rootVisualPosition, ulong timestamp,
|
||||
PointerPointProperties properties, KeyModifiers modifiers, Vector delta)
|
||||
: base(routedEvent, source, pointer, rootVisual, rootVisualPosition,
|
||||
timestamp, properties, modifiers)
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Avalonia.Input
|
||||
{
|
||||
public class PointerEventArgs : RoutedEventArgs
|
||||
{
|
||||
private readonly IVisual? _rootVisual;
|
||||
private readonly Visual? _rootVisual;
|
||||
private readonly Point _rootVisualPosition;
|
||||
private readonly PointerPointProperties _properties;
|
||||
private readonly Lazy<IReadOnlyList<RawPointerPoint>?>? _previousPoints;
|
||||
@@ -16,7 +16,7 @@ namespace Avalonia.Input
|
||||
internal PointerEventArgs(RoutedEvent routedEvent,
|
||||
IInteractive? source,
|
||||
IPointer pointer,
|
||||
IVisual? rootVisual, Point rootVisualPosition,
|
||||
Visual? rootVisual, Point rootVisualPosition,
|
||||
ulong timestamp,
|
||||
PointerPointProperties properties,
|
||||
KeyModifiers modifiers)
|
||||
@@ -34,7 +34,7 @@ namespace Avalonia.Input
|
||||
internal PointerEventArgs(RoutedEvent routedEvent,
|
||||
IInteractive? source,
|
||||
IPointer pointer,
|
||||
IVisual? rootVisual, Point rootVisualPosition,
|
||||
Visual? rootVisual, Point rootVisualPosition,
|
||||
ulong timestamp,
|
||||
PointerPointProperties properties,
|
||||
KeyModifiers modifiers,
|
||||
@@ -59,7 +59,7 @@ namespace Avalonia.Input
|
||||
/// </summary>
|
||||
public KeyModifiers KeyModifiers { get; }
|
||||
|
||||
private Point GetPosition(Point pt, IVisual? relativeTo)
|
||||
private Point GetPosition(Point pt, Visual? relativeTo)
|
||||
{
|
||||
if (_rootVisual == null)
|
||||
return default;
|
||||
@@ -74,14 +74,14 @@ namespace Avalonia.Input
|
||||
/// </summary>
|
||||
/// <param name="relativeTo">The control.</param>
|
||||
/// <returns>The pointer position in the control's coordinates.</returns>
|
||||
public Point GetPosition(IVisual? relativeTo) => GetPosition(_rootVisualPosition, relativeTo);
|
||||
public Point GetPosition(Visual? relativeTo) => GetPosition(_rootVisualPosition, relativeTo);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the PointerPoint associated with the current event
|
||||
/// </summary>
|
||||
/// <param name="relativeTo">The visual which coordinate system to use. Pass null for toplevel coordinate system</param>
|
||||
/// <returns></returns>
|
||||
public PointerPoint GetCurrentPoint(IVisual? relativeTo)
|
||||
public PointerPoint GetCurrentPoint(Visual? relativeTo)
|
||||
=> new PointerPoint(Pointer, GetPosition(relativeTo), _properties);
|
||||
|
||||
/// <summary>
|
||||
@@ -89,7 +89,7 @@ namespace Avalonia.Input
|
||||
/// </summary>
|
||||
/// <param name="relativeTo">The visual which coordinate system to use. Pass null for toplevel coordinate system</param>
|
||||
/// <returns></returns>
|
||||
public IReadOnlyList<PointerPoint> GetIntermediatePoints(IVisual? relativeTo)
|
||||
public IReadOnlyList<PointerPoint> GetIntermediatePoints(Visual? relativeTo)
|
||||
{
|
||||
var previousPoints = _previousPoints?.Value;
|
||||
if (previousPoints == null || previousPoints.Count == 0)
|
||||
@@ -127,7 +127,7 @@ namespace Avalonia.Input
|
||||
internal PointerPressedEventArgs(
|
||||
IInteractive source,
|
||||
IPointer pointer,
|
||||
IVisual rootVisual, Point rootVisualPosition,
|
||||
Visual rootVisual, Point rootVisualPosition,
|
||||
ulong timestamp,
|
||||
PointerPointProperties properties,
|
||||
KeyModifiers modifiers,
|
||||
@@ -145,7 +145,7 @@ namespace Avalonia.Input
|
||||
{
|
||||
internal PointerReleasedEventArgs(
|
||||
IInteractive source, IPointer pointer,
|
||||
IVisual rootVisual, Point rootVisualPosition, ulong timestamp,
|
||||
Visual rootVisual, Point rootVisualPosition, ulong timestamp,
|
||||
PointerPointProperties properties, KeyModifiers modifiers,
|
||||
MouseButton initialPressMouseButton)
|
||||
: base(InputElement.PointerReleasedEvent, source, pointer, rootVisual, rootVisualPosition,
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Avalonia.Input
|
||||
&& _lastPointer is (var lastPointer, var lastPosition))
|
||||
{
|
||||
_lastPointer = null;
|
||||
ClearPointerOver(lastPointer, args.Root, 0, args.Root.PointToClient(lastPosition),
|
||||
ClearPointerOver(lastPointer, args.Root, 0, PointToClient(args.Root, lastPosition),
|
||||
new PointerPointProperties(args.InputModifiers, args.Type.ToUpdateKind()),
|
||||
args.InputModifiers.ToKeyModifiers());
|
||||
}
|
||||
@@ -64,14 +64,14 @@ namespace Avalonia.Input
|
||||
{
|
||||
if (_lastPointer is (var pointer, var position))
|
||||
{
|
||||
var clientPoint = _inputRoot.PointToClient(position);
|
||||
var clientPoint = PointToClient(_inputRoot, position);
|
||||
|
||||
if (dirtyRect.Contains(clientPoint))
|
||||
{
|
||||
var element = pointer.Captured ?? _inputRoot.InputHitTest(clientPoint);
|
||||
SetPointerOver(pointer, _inputRoot, element, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None);
|
||||
}
|
||||
else if (!_inputRoot.Bounds.Contains(clientPoint))
|
||||
else if (!((Visual)_inputRoot).Bounds.Contains(clientPoint))
|
||||
{
|
||||
ClearPointerOver(pointer, _inputRoot, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ namespace Avalonia.Input
|
||||
{
|
||||
if (_lastPointer is (var pointer, var position))
|
||||
{
|
||||
var clientPoint = _inputRoot.PointToClient(position);
|
||||
var clientPoint = PointToClient(_inputRoot, position);
|
||||
ClearPointerOver(pointer, _inputRoot, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None);
|
||||
}
|
||||
_lastPointer = null;
|
||||
@@ -101,10 +101,10 @@ namespace Avalonia.Input
|
||||
// Do not pass rootVisual, when we have unknown position,
|
||||
// so GetPosition won't return invalid values.
|
||||
var e = new PointerEventArgs(InputElement.PointerExitedEvent, element, pointer,
|
||||
position.HasValue ? root : null, position.HasValue ? position.Value : default,
|
||||
position.HasValue ? root as Visual : null, position.HasValue ? position.Value : default,
|
||||
timestamp, properties, inputModifiers);
|
||||
|
||||
if (element != null && !element.IsAttachedToVisualTree)
|
||||
if (element is Visual v && !v.IsAttachedToVisualTree)
|
||||
{
|
||||
// element has been removed from visual tree so do top down cleanup
|
||||
if (root.IsPointerOver)
|
||||
@@ -117,7 +117,7 @@ namespace Avalonia.Input
|
||||
e.Source = element;
|
||||
e.Handled = false;
|
||||
element.RaiseEvent(e);
|
||||
element = (IInputElement?)element.VisualParent;
|
||||
element = GetVisualParent(element);
|
||||
}
|
||||
|
||||
root.PointerOverElement = null;
|
||||
@@ -127,14 +127,18 @@ namespace Avalonia.Input
|
||||
|
||||
private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element, bool clearRoot)
|
||||
{
|
||||
foreach (IInputElement el in element.VisualChildren)
|
||||
if (element is Visual v)
|
||||
{
|
||||
if (el.IsPointerOver)
|
||||
foreach (IInputElement el in v.VisualChildren)
|
||||
{
|
||||
ClearChildrenPointerOver(e, el, true);
|
||||
break;
|
||||
if (el.IsPointerOver)
|
||||
{
|
||||
ClearChildrenPointerOver(e, el, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clearRoot)
|
||||
{
|
||||
e.Source = element;
|
||||
@@ -160,7 +164,7 @@ namespace Avalonia.Input
|
||||
}
|
||||
}
|
||||
|
||||
_lastPointer = (pointer, root.PointToScreen(position));
|
||||
_lastPointer = (pointer, ((Visual)root).PointToScreen(position));
|
||||
}
|
||||
|
||||
private void SetPointerOverToElement(IPointer pointer, IInputRoot root, IInputElement element,
|
||||
@@ -177,14 +181,14 @@ namespace Avalonia.Input
|
||||
branch = el;
|
||||
break;
|
||||
}
|
||||
el = (IInputElement?)el.VisualParent;
|
||||
el = GetVisualParent(el);
|
||||
}
|
||||
|
||||
el = root.PointerOverElement;
|
||||
|
||||
var e = new PointerEventArgs(InputElement.PointerExitedEvent, el, pointer, root, position,
|
||||
var e = new PointerEventArgs(InputElement.PointerExitedEvent, el, pointer, (Visual)root, position,
|
||||
timestamp, properties, inputModifiers);
|
||||
if (el != null && branch != null && !el.IsAttachedToVisualTree)
|
||||
if (el is Visual v && branch != null && !v.IsAttachedToVisualTree)
|
||||
{
|
||||
ClearChildrenPointerOver(e, branch, false);
|
||||
}
|
||||
@@ -194,7 +198,7 @@ namespace Avalonia.Input
|
||||
e.Source = el;
|
||||
e.Handled = false;
|
||||
el.RaiseEvent(e);
|
||||
el = (IInputElement?)el.VisualParent;
|
||||
el = GetVisualParent(el);
|
||||
}
|
||||
|
||||
el = root.PointerOverElement = element;
|
||||
@@ -206,8 +210,18 @@ namespace Avalonia.Input
|
||||
e.Source = el;
|
||||
e.Handled = false;
|
||||
el.RaiseEvent(e);
|
||||
el = (IInputElement?)el.VisualParent;
|
||||
el = GetVisualParent(el);
|
||||
}
|
||||
}
|
||||
|
||||
private static IInputElement? GetVisualParent(IInputElement e)
|
||||
{
|
||||
return (e as Visual)?.VisualParent as IInputElement;
|
||||
}
|
||||
|
||||
private static Point PointToClient(IInputRoot root, PixelPoint p)
|
||||
{
|
||||
return ((Visual)root).PointToClient(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Avalonia.Input
|
||||
{
|
||||
public Vector Delta { get; set; }
|
||||
|
||||
internal PointerWheelEventArgs(IInteractive source, IPointer pointer, IVisual rootVisual,
|
||||
internal PointerWheelEventArgs(IInteractive source, IPointer pointer, Visual rootVisual,
|
||||
Point rootVisualPosition, ulong timestamp,
|
||||
PointerPointProperties properties, KeyModifiers modifiers, Vector delta)
|
||||
: base(InputElement.PointerWheelChangedEvent, source, pointer, rootVisual, rootVisualPosition,
|
||||
|
||||
@@ -17,6 +17,6 @@ namespace Avalonia.Input
|
||||
public KeyModifiers KeyModifiers => lastPointerEventArgs.KeyModifiers;
|
||||
public ulong Timestamp => lastPointerEventArgs.Timestamp;
|
||||
|
||||
public Point GetPosition(IVisual? relativeTo) => lastPointerEventArgs.GetPosition(relativeTo);
|
||||
public Point GetPosition(Visual? relativeTo) => lastPointerEventArgs.GetPosition(relativeTo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Avalonia.Input.TextInput
|
||||
/// <summary>
|
||||
/// The visual that's showing the text
|
||||
/// </summary>
|
||||
IVisual TextViewVisual { get; }
|
||||
Visual TextViewVisual { get; }
|
||||
/// <summary>
|
||||
/// Should be fired when text-hosting visual is changed
|
||||
/// </summary>
|
||||
|
||||
@@ -73,10 +73,13 @@ namespace Avalonia.Input.TextInput
|
||||
|
||||
private void UpdateCursorRect()
|
||||
{
|
||||
if (_im == null || _client == null || _focusedElement?.VisualRoot == null)
|
||||
if (_im == null ||
|
||||
_client == null ||
|
||||
_focusedElement is not Visual v ||
|
||||
v.VisualRoot is not Visual root)
|
||||
return;
|
||||
|
||||
var transform = _focusedElement.TransformToVisual(_focusedElement.VisualRoot);
|
||||
var transform = v.TransformToVisual(root);
|
||||
if (transform == null)
|
||||
_im.SetCursorRect(default);
|
||||
else
|
||||
@@ -95,7 +98,7 @@ namespace Avalonia.Input.TextInput
|
||||
return;
|
||||
_focusedElement = element;
|
||||
|
||||
var inputMethod = (element?.VisualRoot as ITextInputMethodRoot)?.InputMethod;
|
||||
var inputMethod = ((element as Visual)?.VisualRoot as ITextInputMethodRoot)?.InputMethod;
|
||||
|
||||
if (_im != inputMethod)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Avalonia.Input.TextInput
|
||||
{
|
||||
class TransformTrackingHelper : IDisposable
|
||||
{
|
||||
private IVisual? _visual;
|
||||
private Visual? _visual;
|
||||
private bool _queuedForUpdate;
|
||||
private readonly EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChangedHandler;
|
||||
private readonly List<Visual> _propertyChangedSubscriptions = new List<Visual>();
|
||||
@@ -17,7 +17,7 @@ namespace Avalonia.Input.TextInput
|
||||
_propertyChangedHandler = PropertyChangedHandler;
|
||||
}
|
||||
|
||||
public void SetVisual(IVisual? visual)
|
||||
public void SetVisual(Visual? visual)
|
||||
{
|
||||
Dispose();
|
||||
_visual = visual;
|
||||
@@ -72,7 +72,7 @@ namespace Avalonia.Input.TextInput
|
||||
{
|
||||
Matrix? matrix = null;
|
||||
if (_visual != null && _visual.VisualRoot != null)
|
||||
matrix = _visual.TransformToVisual(_visual.VisualRoot);
|
||||
matrix = _visual.TransformToVisual((Visual)_visual.VisualRoot);
|
||||
if (Matrix != matrix)
|
||||
{
|
||||
Matrix = matrix;
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Avalonia.Input
|
||||
}
|
||||
|
||||
target.RaiseEvent(new PointerPressedEventArgs(target, pointer,
|
||||
args.Root, args.Position, ev.Timestamp,
|
||||
(Visual)args.Root, args.Position, ev.Timestamp,
|
||||
new PointerPointProperties(GetModifiers(args.InputModifiers, true), updateKind),
|
||||
keyModifier, _clickCount));
|
||||
}
|
||||
@@ -86,7 +86,7 @@ namespace Avalonia.Input
|
||||
using (pointer)
|
||||
{
|
||||
target.RaiseEvent(new PointerReleasedEventArgs(target, pointer,
|
||||
args.Root, args.Position, ev.Timestamp,
|
||||
(Visual)args.Root, args.Position, ev.Timestamp,
|
||||
new PointerPointProperties(GetModifiers(args.InputModifiers, false), updateKind),
|
||||
keyModifier, MouseButton.Left));
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace Avalonia.Input
|
||||
|
||||
if (args.Type == RawPointerEventType.TouchUpdate)
|
||||
{
|
||||
target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, args.Root,
|
||||
target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, (Visual)args.Root,
|
||||
args.Position, ev.Timestamp,
|
||||
new PointerPointProperties(GetModifiers(args.InputModifiers, true), updateKind),
|
||||
keyModifier, args.IntermediatePoints));
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Avalonia.Interactivity
|
||||
/// <summary>
|
||||
/// Gets the interactive parent of the object for bubbling and tunneling events.
|
||||
/// </summary>
|
||||
IInteractive? IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive;
|
||||
IInteractive? IInteractive.InteractiveParent => this.VisualParent as IInteractive;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a handler for the specified routed event.
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Avalonia.Layout
|
||||
|
||||
/// <summary>
|
||||
/// Initializes any per-container state the layout requires when it is attached to an
|
||||
/// <see cref="ILayoutable"/> container.
|
||||
/// <see cref="Layoutable"/> container.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// The context object that facilitates communication between the layout and its host
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Avalonia.Layout
|
||||
{
|
||||
internal class ElementManager
|
||||
{
|
||||
private readonly List<ILayoutable?> _realizedElements = new List<ILayoutable?>();
|
||||
private readonly List<Layoutable?> _realizedElements = new List<Layoutable?>();
|
||||
private readonly List<Rect> _realizedElementLayoutBounds = new List<Rect>();
|
||||
private int _firstRealizedDataIndex;
|
||||
private VirtualizingLayoutContext? _context;
|
||||
@@ -69,9 +69,9 @@ namespace Avalonia.Layout
|
||||
return IsVirtualizingContext ? _realizedElements.Count : _context!.ItemCount;
|
||||
}
|
||||
|
||||
public ILayoutable GetAt(int realizedIndex)
|
||||
public Layoutable GetAt(int realizedIndex)
|
||||
{
|
||||
ILayoutable? element;
|
||||
Layoutable? element;
|
||||
|
||||
if (IsVirtualizingContext)
|
||||
{
|
||||
@@ -99,7 +99,7 @@ namespace Avalonia.Layout
|
||||
return element;
|
||||
}
|
||||
|
||||
public void Add(ILayoutable element, int dataIndex)
|
||||
public void Add(Layoutable element, int dataIndex)
|
||||
{
|
||||
if (_realizedElements.Count == 0)
|
||||
{
|
||||
@@ -110,7 +110,7 @@ namespace Avalonia.Layout
|
||||
_realizedElementLayoutBounds.Add(default);
|
||||
}
|
||||
|
||||
public void Insert(int realizedIndex, int dataIndex, ILayoutable? element)
|
||||
public void Insert(int realizedIndex, int dataIndex, Layoutable? element)
|
||||
{
|
||||
if (realizedIndex == 0)
|
||||
{
|
||||
@@ -207,7 +207,7 @@ namespace Avalonia.Layout
|
||||
|
||||
public bool IsIndexValidInData(int currentIndex) => (uint)currentIndex < _context!.ItemCount;
|
||||
|
||||
public ILayoutable? GetRealizedElement(int dataIndex)
|
||||
public Layoutable? GetRealizedElement(int dataIndex)
|
||||
{
|
||||
return IsVirtualizingContext ?
|
||||
GetAt(GetRealizedRangeIndexFromDataIndex(dataIndex)) :
|
||||
@@ -330,7 +330,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
}
|
||||
|
||||
public int GetElementDataIndex(ILayoutable suggestedAnchor)
|
||||
public int GetElementDataIndex(Layoutable suggestedAnchor)
|
||||
{
|
||||
var it = _realizedElements.IndexOf(suggestedAnchor);
|
||||
return it != -1 ? GetDataIndexFromRealizedRangeIndex(it) : -1;
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
|
||||
public Size MeasureElement(
|
||||
ILayoutable element,
|
||||
Layoutable element,
|
||||
int index,
|
||||
Size availableSize,
|
||||
VirtualizingLayoutContext context)
|
||||
@@ -512,9 +512,9 @@ namespace Avalonia.Layout
|
||||
|
||||
private Rect EstimateExtent(Size availableSize, string? layoutId)
|
||||
{
|
||||
ILayoutable? firstRealizedElement = null;
|
||||
Layoutable? firstRealizedElement = null;
|
||||
Rect firstBounds = new Rect();
|
||||
ILayoutable? lastRealizedElement = null;
|
||||
Layoutable? lastRealizedElement = null;
|
||||
Rect lastBounds = new Rect();
|
||||
int firstDataIndex = -1;
|
||||
int lastDataIndex = -1;
|
||||
@@ -727,7 +727,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
}
|
||||
|
||||
public ILayoutable? GetElementIfRealized(int dataIndex)
|
||||
public Layoutable? GetElementIfRealized(int dataIndex)
|
||||
{
|
||||
if (_elementManager.IsDataIndexRealized(dataIndex))
|
||||
{
|
||||
@@ -737,7 +737,7 @@ namespace Avalonia.Layout
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool TryAddElement0(ILayoutable element)
|
||||
public bool TryAddElement0(Layoutable element)
|
||||
{
|
||||
if (_elementManager.GetRealizedElementCount() == 0)
|
||||
{
|
||||
|
||||
@@ -21,14 +21,14 @@ namespace Avalonia.Layout
|
||||
Rect Algorithm_GetExtent(
|
||||
Size availableSize,
|
||||
VirtualizingLayoutContext context,
|
||||
ILayoutable? firstRealized,
|
||||
Layoutable? firstRealized,
|
||||
int firstRealizedItemIndex,
|
||||
Rect firstRealizedLayoutBounds,
|
||||
ILayoutable? lastRealized,
|
||||
Layoutable? lastRealized,
|
||||
int lastRealizedItemIndex,
|
||||
Rect lastRealizedLayoutBounds);
|
||||
void Algorithm_OnElementMeasured(
|
||||
ILayoutable element,
|
||||
Layoutable element,
|
||||
int index,
|
||||
Size availableSize,
|
||||
Size measureSize,
|
||||
|
||||
@@ -18,13 +18,13 @@ namespace Avalonia.Layout
|
||||
/// Notifies the layout manager that a control requires a measure.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
void InvalidateMeasure(ILayoutable control);
|
||||
void InvalidateMeasure(Layoutable control);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the layout manager that a control requires an arrange.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
void InvalidateArrange(ILayoutable control);
|
||||
void InvalidateArrange(Layoutable control);
|
||||
|
||||
/// <summary>
|
||||
/// Executes a layout pass.
|
||||
@@ -48,12 +48,12 @@ namespace Avalonia.Layout
|
||||
/// Registers a control as wanting to receive effective viewport notifications.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
void RegisterEffectiveViewportListener(ILayoutable control);
|
||||
void RegisterEffectiveViewportListener(Layoutable control);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a control as no longer wanting to receive effective viewport notifications.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
void UnregisterEffectiveViewportListener(ILayoutable control);
|
||||
void UnregisterEffectiveViewportListener(Layoutable control);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Avalonia.Layout
|
||||
/// Defines the root of a layoutable tree.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface ILayoutRoot : ILayoutable
|
||||
public interface ILayoutRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// The size available to lay out the controls.
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Avalonia.Layout
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines layout-related functionality for a control.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface ILayoutable : IVisual
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the size that this element computed during the measure pass of the layout process.
|
||||
/// </summary>
|
||||
Size DesiredSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of the element.
|
||||
/// </summary>
|
||||
double Width { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the element.
|
||||
/// </summary>
|
||||
double Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum width of the element.
|
||||
/// </summary>
|
||||
double MinWidth { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum width of the element.
|
||||
/// </summary>
|
||||
double MaxWidth { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum height of the element.
|
||||
/// </summary>
|
||||
double MinHeight { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum height of the element.
|
||||
/// </summary>
|
||||
double MaxHeight { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the margin around the element.
|
||||
/// </summary>
|
||||
Thickness Margin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the element's preferred horizontal alignment in its parent.
|
||||
/// </summary>
|
||||
HorizontalAlignment HorizontalAlignment { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the element's preferred vertical alignment in its parent.
|
||||
/// </summary>
|
||||
VerticalAlignment VerticalAlignment { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the control's layout measure is valid.
|
||||
/// </summary>
|
||||
bool IsMeasureValid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the control's layouts arrange is valid.
|
||||
/// </summary>
|
||||
bool IsArrangeValid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available size passed in the previous layout pass, if any.
|
||||
/// </summary>
|
||||
Size? PreviousMeasure { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layout rect passed in the previous layout pass, if any.
|
||||
/// </summary>
|
||||
Rect? PreviousArrange { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates the visual children of the control, if necessary
|
||||
/// </summary>
|
||||
void ApplyTemplate();
|
||||
|
||||
/// <summary>
|
||||
/// Carries out a measure of the control.
|
||||
/// </summary>
|
||||
/// <param name="availableSize">The available size for the control.</param>
|
||||
void Measure(Size availableSize);
|
||||
|
||||
/// <summary>
|
||||
/// Arranges the control and its children.
|
||||
/// </summary>
|
||||
/// <param name="rect">The control's new bounds.</param>
|
||||
void Arrange(Rect rect);
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates the measurement of the control and queues a new layout pass.
|
||||
/// </summary>
|
||||
void InvalidateMeasure();
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates the arrangement of the control and queues a new layout pass.
|
||||
/// </summary>
|
||||
void InvalidateArrange();
|
||||
|
||||
/// <summary>
|
||||
/// Called when a child control's desired size changes.
|
||||
/// </summary>
|
||||
/// <param name="control">The child control.</param>
|
||||
void ChildDesiredSizeChanged(ILayoutable control);
|
||||
|
||||
/// <summary>
|
||||
/// Used by the <see cref="LayoutManager"/> to notify the control that its effective
|
||||
/// viewport is changed.
|
||||
/// </summary>
|
||||
/// <param name="e">The viewport information.</param>
|
||||
void EffectiveViewportChanged(EffectiveViewportChangedEventArgs e);
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,8 @@ namespace Avalonia.Layout
|
||||
|
||||
protected override int ItemCountCore() => _nonVirtualizingContext.Children.Count;
|
||||
protected override object GetItemAtCore(int index) => _nonVirtualizingContext.Children[index];
|
||||
protected override ILayoutable GetOrCreateElementAtCore(int index, ElementRealizationOptions options) =>
|
||||
protected override Layoutable GetOrCreateElementAtCore(int index, ElementRealizationOptions options) =>
|
||||
_nonVirtualizingContext.Children[index];
|
||||
protected override void RecycleElementCore(ILayoutable element) { }
|
||||
protected override void RecycleElementCore(Layoutable element) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ namespace Avalonia.Layout
|
||||
public static double LayoutEpsilon { get; } = 0.00000153;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a control's size based on its <see cref="ILayoutable.Width"/>,
|
||||
/// <see cref="ILayoutable.Height"/>, <see cref="ILayoutable.MinWidth"/>,
|
||||
/// <see cref="ILayoutable.MaxWidth"/>, <see cref="ILayoutable.MinHeight"/> and
|
||||
/// <see cref="ILayoutable.MaxHeight"/>.
|
||||
/// Calculates a control's size based on its <see cref="Layoutable.Width"/>,
|
||||
/// <see cref="Layoutable.Height"/>, <see cref="Layoutable.MinWidth"/>,
|
||||
/// <see cref="Layoutable.MaxWidth"/>, <see cref="Layoutable.MinHeight"/> and
|
||||
/// <see cref="Layoutable.MaxHeight"/>.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
/// <param name="constraints">The space available for the control.</param>
|
||||
/// <returns>The control's size.</returns>
|
||||
public static Size ApplyLayoutConstraints(ILayoutable control, Size constraints)
|
||||
public static Size ApplyLayoutConstraints(Layoutable control, Size constraints)
|
||||
{
|
||||
var minmax = new MinMax(control);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Avalonia.Layout
|
||||
MathUtilities.Clamp(constraints.Height, minmax.MinHeight, minmax.MaxHeight));
|
||||
}
|
||||
|
||||
public static Size MeasureChild(ILayoutable? control, Size availableSize, Thickness padding,
|
||||
public static Size MeasureChild(Layoutable? control, Size availableSize, Thickness padding,
|
||||
Thickness borderThickness)
|
||||
{
|
||||
if (IsParentLayoutRounded(control, out double scale))
|
||||
@@ -51,7 +51,7 @@ namespace Avalonia.Layout
|
||||
return new Size().Inflate(padding + borderThickness);
|
||||
}
|
||||
|
||||
public static Size MeasureChild(ILayoutable? control, Size availableSize, Thickness padding)
|
||||
public static Size MeasureChild(Layoutable? control, Size availableSize, Thickness padding)
|
||||
{
|
||||
if (IsParentLayoutRounded(control, out double scale))
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Avalonia.Layout
|
||||
return new Size(padding.Left + padding.Right, padding.Bottom + padding.Top);
|
||||
}
|
||||
|
||||
public static Size ArrangeChild(ILayoutable? child, Size availableSize, Thickness padding, Thickness borderThickness)
|
||||
public static Size ArrangeChild(Layoutable? child, Size availableSize, Thickness padding, Thickness borderThickness)
|
||||
{
|
||||
if (IsParentLayoutRounded(child, out double scale))
|
||||
{
|
||||
@@ -78,7 +78,7 @@ namespace Avalonia.Layout
|
||||
return ArrangeChildInternal(child, availableSize, padding + borderThickness);
|
||||
}
|
||||
|
||||
public static Size ArrangeChild(ILayoutable? child, Size availableSize, Thickness padding)
|
||||
public static Size ArrangeChild(Layoutable? child, Size availableSize, Thickness padding)
|
||||
{
|
||||
if(IsParentLayoutRounded(child, out double scale))
|
||||
padding = RoundLayoutThickness(padding, scale, scale);
|
||||
@@ -86,18 +86,18 @@ namespace Avalonia.Layout
|
||||
return ArrangeChildInternal(child, availableSize, padding);
|
||||
}
|
||||
|
||||
private static Size ArrangeChildInternal(ILayoutable? child, Size availableSize, Thickness padding)
|
||||
private static Size ArrangeChildInternal(Layoutable? child, Size availableSize, Thickness padding)
|
||||
{
|
||||
child?.Arrange(new Rect(availableSize).Deflate(padding));
|
||||
|
||||
return availableSize;
|
||||
}
|
||||
|
||||
private static bool IsParentLayoutRounded(ILayoutable? child, out double scale)
|
||||
private static bool IsParentLayoutRounded(Layoutable? child, out double scale)
|
||||
{
|
||||
var layoutableParent = (ILayoutable?)child?.GetVisualParent();
|
||||
var layoutableParent = (child as Visual)?.GetVisualParent() as Layoutable;
|
||||
|
||||
if (layoutableParent == null || !((Layoutable)layoutableParent).UseLayoutRounding)
|
||||
if (layoutableParent == null || !layoutableParent.UseLayoutRounding)
|
||||
{
|
||||
scale = 1.0;
|
||||
return false;
|
||||
@@ -110,11 +110,11 @@ namespace Avalonia.Layout
|
||||
/// <summary>
|
||||
/// Invalidates measure for given control and all visual children recursively.
|
||||
/// </summary>
|
||||
public static void InvalidateSelfAndChildrenMeasure(ILayoutable control)
|
||||
public static void InvalidateSelfAndChildrenMeasure(Layoutable control)
|
||||
{
|
||||
void InnerInvalidateMeasure(IVisual target)
|
||||
void InnerInvalidateMeasure(Visual target)
|
||||
{
|
||||
if (target is ILayoutable targetLayoutable)
|
||||
if (target is Layoutable targetLayoutable)
|
||||
{
|
||||
targetLayoutable.InvalidateMeasure();
|
||||
}
|
||||
@@ -124,13 +124,14 @@ namespace Avalonia.Layout
|
||||
|
||||
for (int i = 0; i < visualChildrenCount; i++)
|
||||
{
|
||||
IVisual child = visualChildren[i];
|
||||
Visual child = visualChildren[i];
|
||||
|
||||
InnerInvalidateMeasure(child);
|
||||
}
|
||||
}
|
||||
|
||||
InnerInvalidateMeasure(control);
|
||||
if (control is Visual v)
|
||||
InnerInvalidateMeasure(v);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -138,9 +139,9 @@ namespace Avalonia.Layout
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
/// <exception cref="Exception">Thrown when control has no root or returned layout scaling is invalid.</exception>
|
||||
public static double GetLayoutScale(ILayoutable control)
|
||||
public static double GetLayoutScale(Layoutable control)
|
||||
{
|
||||
var visualRoot = control.VisualRoot;
|
||||
var visualRoot = (control as Visual)?.VisualRoot;
|
||||
|
||||
var result = (visualRoot as ILayoutRoot)?.LayoutScaling ?? 1.0;
|
||||
|
||||
@@ -289,7 +290,7 @@ namespace Avalonia.Layout
|
||||
/// </summary>
|
||||
private readonly struct MinMax
|
||||
{
|
||||
public MinMax(ILayoutable e)
|
||||
public MinMax(Layoutable e)
|
||||
{
|
||||
MaxHeight = e.MaxHeight;
|
||||
MinHeight = e.MinHeight;
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace Avalonia.Layout
|
||||
public class LayoutManager : ILayoutManager, IDisposable
|
||||
{
|
||||
private const int MaxPasses = 3;
|
||||
private readonly ILayoutRoot _owner;
|
||||
private readonly LayoutQueue<ILayoutable> _toMeasure = new LayoutQueue<ILayoutable>(v => !v.IsMeasureValid);
|
||||
private readonly LayoutQueue<ILayoutable> _toArrange = new LayoutQueue<ILayoutable>(v => !v.IsArrangeValid);
|
||||
private readonly Layoutable _owner;
|
||||
private readonly LayoutQueue<Layoutable> _toMeasure = new LayoutQueue<Layoutable>(v => !v.IsMeasureValid);
|
||||
private readonly LayoutQueue<Layoutable> _toArrange = new LayoutQueue<Layoutable>(v => !v.IsArrangeValid);
|
||||
private readonly Action _executeLayoutPass;
|
||||
private List<EffectiveViewportChangedListener>? _effectiveViewportChangedListeners;
|
||||
private bool _disposed;
|
||||
@@ -27,14 +27,14 @@ namespace Avalonia.Layout
|
||||
|
||||
public LayoutManager(ILayoutRoot owner)
|
||||
{
|
||||
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
|
||||
_owner = owner as Layoutable ?? throw new ArgumentNullException(nameof(owner));
|
||||
_executeLayoutPass = ExecuteQueuedLayoutPass;
|
||||
}
|
||||
|
||||
public virtual event EventHandler? LayoutUpdated;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void InvalidateMeasure(ILayoutable control)
|
||||
public virtual void InvalidateMeasure(Layoutable control)
|
||||
{
|
||||
control = control ?? throw new ArgumentNullException(nameof(control));
|
||||
Dispatcher.UIThread.VerifyAccess();
|
||||
@@ -65,7 +65,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void InvalidateArrange(ILayoutable control)
|
||||
public virtual void InvalidateArrange(Layoutable control)
|
||||
{
|
||||
control = control ?? throw new ArgumentNullException(nameof(control));
|
||||
Dispatcher.UIThread.VerifyAccess();
|
||||
@@ -203,7 +203,7 @@ namespace Avalonia.Layout
|
||||
_toArrange.Dispose();
|
||||
}
|
||||
|
||||
void ILayoutManager.RegisterEffectiveViewportListener(ILayoutable control)
|
||||
void ILayoutManager.RegisterEffectiveViewportListener(Layoutable control)
|
||||
{
|
||||
_effectiveViewportChangedListeners ??= new List<EffectiveViewportChangedListener>();
|
||||
_effectiveViewportChangedListeners.Add(new EffectiveViewportChangedListener(
|
||||
@@ -211,7 +211,7 @@ namespace Avalonia.Layout
|
||||
CalculateEffectiveViewport(control)));
|
||||
}
|
||||
|
||||
void ILayoutManager.UnregisterEffectiveViewportListener(ILayoutable control)
|
||||
void ILayoutManager.UnregisterEffectiveViewportListener(Layoutable control)
|
||||
{
|
||||
if (_effectiveViewportChangedListeners is object)
|
||||
{
|
||||
@@ -265,13 +265,13 @@ namespace Avalonia.Layout
|
||||
}
|
||||
}
|
||||
|
||||
private void Measure(ILayoutable control)
|
||||
private void Measure(Layoutable control)
|
||||
{
|
||||
// Controls closest to the visual root need to be arranged first. We don't try to store
|
||||
// ordered invalidation lists, instead we traverse the tree upwards, measuring the
|
||||
// controls closest to the root first. This has been shown by benchmarks to be the
|
||||
// fastest and most memory-efficient algorithm.
|
||||
if (control.VisualParent is ILayoutable parent)
|
||||
if (control.VisualParent is Layoutable parent)
|
||||
{
|
||||
Measure(parent);
|
||||
}
|
||||
@@ -283,7 +283,7 @@ namespace Avalonia.Layout
|
||||
{
|
||||
if (control is ILayoutRoot root)
|
||||
{
|
||||
root.Measure(Size.Infinity);
|
||||
control.Measure(Size.Infinity);
|
||||
}
|
||||
else if (control.PreviousMeasure.HasValue)
|
||||
{
|
||||
@@ -292,9 +292,9 @@ namespace Avalonia.Layout
|
||||
}
|
||||
}
|
||||
|
||||
private void Arrange(ILayoutable control)
|
||||
private void Arrange(Layoutable control)
|
||||
{
|
||||
if (control.VisualParent is ILayoutable parent)
|
||||
if (control.VisualParent is Layoutable parent)
|
||||
{
|
||||
Arrange(parent);
|
||||
}
|
||||
@@ -304,7 +304,7 @@ namespace Avalonia.Layout
|
||||
if (control is IEmbeddedLayoutRoot embeddedRoot)
|
||||
control.Arrange(new Rect(embeddedRoot.AllocatedSize));
|
||||
else if (control is ILayoutRoot root)
|
||||
control.Arrange(new Rect(root.DesiredSize));
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
else if (control.PreviousArrange != null)
|
||||
{
|
||||
// Has been observed that PreviousArrange sometimes is null, probably a bug somewhere else.
|
||||
@@ -350,7 +350,7 @@ namespace Avalonia.Layout
|
||||
|
||||
if (viewport != l.Viewport)
|
||||
{
|
||||
l.Listener.EffectiveViewportChanged(new EffectiveViewportChangedEventArgs(viewport));
|
||||
l.Listener.RaiseEffectiveViewportChanged(new EffectiveViewportChangedEventArgs(viewport));
|
||||
l.Viewport = viewport;
|
||||
}
|
||||
}
|
||||
@@ -364,14 +364,14 @@ namespace Avalonia.Layout
|
||||
return startCount != _toMeasure.Count + _toArrange.Count;
|
||||
}
|
||||
|
||||
private Rect CalculateEffectiveViewport(IVisual control)
|
||||
private Rect CalculateEffectiveViewport(Visual control)
|
||||
{
|
||||
var viewport = new Rect(0, 0, double.PositiveInfinity, double.PositiveInfinity);
|
||||
CalculateEffectiveViewport(control, control, ref viewport);
|
||||
return viewport;
|
||||
}
|
||||
|
||||
private void CalculateEffectiveViewport(IVisual target, IVisual control, ref Rect viewport)
|
||||
private void CalculateEffectiveViewport(Visual target, Visual control, ref Rect viewport)
|
||||
{
|
||||
// Recurse until the top level control.
|
||||
if (control.VisualParent is object)
|
||||
@@ -405,13 +405,13 @@ namespace Avalonia.Layout
|
||||
|
||||
private class EffectiveViewportChangedListener
|
||||
{
|
||||
public EffectiveViewportChangedListener(ILayoutable listener, Rect viewport)
|
||||
public EffectiveViewportChangedListener(Layoutable listener, Rect viewport)
|
||||
{
|
||||
Listener = listener;
|
||||
Viewport = viewport;
|
||||
}
|
||||
|
||||
public ILayoutable Listener { get; }
|
||||
public Layoutable Listener { get; }
|
||||
public Rect Viewport { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Avalonia.Layout
|
||||
/// <summary>
|
||||
/// Implements layout-related functionality for a control.
|
||||
/// </summary>
|
||||
public class Layoutable : Visual, ILayoutable
|
||||
public class Layoutable : Visual
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="DesiredSize"/> property.
|
||||
@@ -323,15 +323,12 @@ namespace Avalonia.Layout
|
||||
set { SetValue(UseLayoutRoundingProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the available size passed in the previous layout pass, if any.
|
||||
/// </summary>
|
||||
Size? ILayoutable.PreviousMeasure => _previousMeasure;
|
||||
internal Size? PreviousMeasure => _previousMeasure;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layout rect passed in the previous layout pass, if any.
|
||||
/// </summary>
|
||||
Rect? ILayoutable.PreviousArrange => _previousArrange;
|
||||
internal Rect? PreviousArrange => _previousArrange;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the visual children of the control, if necessary
|
||||
@@ -380,7 +377,7 @@ namespace Avalonia.Layout
|
||||
|
||||
if (DesiredSize != previousDesiredSize)
|
||||
{
|
||||
this.GetVisualParent<ILayoutable>()?.ChildDesiredSizeChanged(this);
|
||||
this.GetVisualParent<Layoutable>()?.ChildDesiredSizeChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,7 +420,7 @@ namespace Avalonia.Layout
|
||||
IsMeasureValid = false;
|
||||
IsArrangeValid = false;
|
||||
|
||||
if (((ILayoutable)this).IsAttachedToVisualTree)
|
||||
if (IsAttachedToVisualTree)
|
||||
{
|
||||
(VisualRoot as ILayoutRoot)?.LayoutManager.InvalidateMeasure(this);
|
||||
InvalidateVisual();
|
||||
@@ -448,7 +445,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void ILayoutable.ChildDesiredSizeChanged(ILayoutable control)
|
||||
internal void ChildDesiredSizeChanged(Layoutable control)
|
||||
{
|
||||
if (!_measuring)
|
||||
{
|
||||
@@ -456,11 +453,11 @@ namespace Avalonia.Layout
|
||||
}
|
||||
}
|
||||
|
||||
void ILayoutable.EffectiveViewportChanged(EffectiveViewportChangedEventArgs e)
|
||||
internal void RaiseEffectiveViewportChanged(EffectiveViewportChangedEventArgs e)
|
||||
{
|
||||
_effectiveViewportChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Marks a property as affecting the control's measurement.
|
||||
/// </summary>
|
||||
@@ -471,7 +468,7 @@ namespace Avalonia.Layout
|
||||
/// property will cause <see cref="InvalidateMeasure"/> to be called on the element.
|
||||
/// </remarks>
|
||||
protected static void AffectsMeasure<T>(params AvaloniaProperty[] properties)
|
||||
where T : class, ILayoutable
|
||||
where T : Layoutable
|
||||
{
|
||||
void Invalidate(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
@@ -494,7 +491,7 @@ namespace Avalonia.Layout
|
||||
/// property will cause <see cref="InvalidateArrange"/> to be called on the element.
|
||||
/// </remarks>
|
||||
protected static void AffectsArrange<T>(params AvaloniaProperty[] properties)
|
||||
where T : class, ILayoutable
|
||||
where T : Layoutable
|
||||
{
|
||||
void Invalidate(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
@@ -596,9 +593,9 @@ namespace Avalonia.Layout
|
||||
|
||||
for (var i = 0; i < visualCount; i++)
|
||||
{
|
||||
IVisual visual = visualChildren[i];
|
||||
Visual visual = visualChildren[i];
|
||||
|
||||
if (visual is ILayoutable layoutable)
|
||||
if (visual is Layoutable layoutable)
|
||||
{
|
||||
layoutable.Measure(availableSize);
|
||||
width = Math.Max(width, layoutable.DesiredSize.Width);
|
||||
@@ -709,9 +706,9 @@ namespace Avalonia.Layout
|
||||
|
||||
for (var i = 0; i < visualCount; i++)
|
||||
{
|
||||
IVisual visual = visualChildren[i];
|
||||
Visual visual = visualChildren[i];
|
||||
|
||||
if (visual is ILayoutable layoutable)
|
||||
if (visual is Layoutable layoutable)
|
||||
{
|
||||
layoutable.Arrange(arrangeRect);
|
||||
}
|
||||
@@ -778,7 +775,7 @@ namespace Avalonia.Layout
|
||||
DesiredSize = default;
|
||||
|
||||
// All changes to visibility cause the parent element to be notified.
|
||||
this.GetVisualParent<ILayoutable>()?.ChildDesiredSizeChanged(this);
|
||||
this.GetVisualParent<Layoutable>()?.ChildDesiredSizeChanged(this);
|
||||
|
||||
// We only invalidate outselves when visibility is changed to true.
|
||||
if (change.GetNewValue<bool>())
|
||||
@@ -789,7 +786,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected sealed override void OnVisualParentChanged(IVisual? oldParent, IVisual? newParent)
|
||||
protected sealed override void OnVisualParentChanged(Visual? oldParent, Visual? newParent)
|
||||
{
|
||||
LayoutHelper.InvalidateSelfAndChildrenMeasure(this);
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ namespace Avalonia.Layout
|
||||
/// <summary>
|
||||
/// Gets the collection of child controls from the container that provides the context.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ILayoutable> Children => ChildrenCore;
|
||||
public IReadOnlyList<Layoutable> Children => ChildrenCore;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the behavior for getting the return value of <see cref="Children"/> in a
|
||||
/// derived or custom <see cref="NonVirtualizingLayoutContext"/>.
|
||||
/// </summary>
|
||||
protected abstract IReadOnlyList<ILayoutable> ChildrenCore { get; }
|
||||
protected abstract IReadOnlyList<Layoutable> ChildrenCore { get; }
|
||||
|
||||
internal VirtualizingLayoutContext GetVirtualizingContextAdapter() =>
|
||||
_contextAdapter ??= new LayoutContextAdapter(this);
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Avalonia.Layout
|
||||
{
|
||||
var element = context.Children[i];
|
||||
|
||||
if (!element.IsVisible)
|
||||
if ((element as Visual)?.IsVisible == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ namespace Avalonia.Layout
|
||||
{
|
||||
var element = context.Children[i];
|
||||
|
||||
if (!element.IsVisible)
|
||||
if ((element as Visual)?.IsVisible == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ namespace Avalonia.Layout
|
||||
Math.Max(finalSize.Height, bounds.Height));
|
||||
}
|
||||
|
||||
private static Rect LayoutVertical(ILayoutable element, double y, Size constraint)
|
||||
private static Rect LayoutVertical(Layoutable element, double y, Size constraint)
|
||||
{
|
||||
var x = 0.0;
|
||||
var width = element.DesiredSize.Width;
|
||||
@@ -138,7 +138,7 @@ namespace Avalonia.Layout
|
||||
return new Rect(x, y, width, element.DesiredSize.Height);
|
||||
}
|
||||
|
||||
private static Rect LayoutHorizontal(ILayoutable element, double x, Size constraint)
|
||||
private static Rect LayoutHorizontal(Layoutable element, double x, Size constraint)
|
||||
{
|
||||
var y = 0.0;
|
||||
var height = element.DesiredSize.Height;
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace Avalonia.Layout
|
||||
internal Rect GetExtent(
|
||||
Size availableSize,
|
||||
VirtualizingLayoutContext context,
|
||||
ILayoutable? firstRealized,
|
||||
Layoutable? firstRealized,
|
||||
int firstRealizedItemIndex,
|
||||
Rect firstRealizedLayoutBounds,
|
||||
ILayoutable? lastRealized,
|
||||
Layoutable? lastRealized,
|
||||
int lastRealizedItemIndex,
|
||||
Rect lastRealizedLayoutBounds)
|
||||
{
|
||||
@@ -121,7 +121,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
|
||||
internal void OnElementMeasured(
|
||||
ILayoutable element,
|
||||
Layoutable element,
|
||||
int index,
|
||||
Size availableSize,
|
||||
Size measureSize,
|
||||
@@ -188,10 +188,10 @@ namespace Avalonia.Layout
|
||||
Rect IFlowLayoutAlgorithmDelegates.Algorithm_GetExtent(
|
||||
Size availableSize,
|
||||
VirtualizingLayoutContext context,
|
||||
ILayoutable? firstRealized,
|
||||
Layoutable? firstRealized,
|
||||
int firstRealizedItemIndex,
|
||||
Rect firstRealizedLayoutBounds,
|
||||
ILayoutable? lastRealized,
|
||||
Layoutable? lastRealized,
|
||||
int lastRealizedItemIndex,
|
||||
Rect lastRealizedLayoutBounds)
|
||||
{
|
||||
@@ -206,7 +206,7 @@ namespace Avalonia.Layout
|
||||
lastRealizedLayoutBounds);
|
||||
}
|
||||
|
||||
void IFlowLayoutAlgorithmDelegates.Algorithm_OnElementMeasured(ILayoutable element, int index, Size availableSize, Size measureSize, Size desiredSize, Size provisionalArrangeSize, VirtualizingLayoutContext context)
|
||||
void IFlowLayoutAlgorithmDelegates.Algorithm_OnElementMeasured(Layoutable element, int index, Size availableSize, Size measureSize, Size desiredSize, Size provisionalArrangeSize, VirtualizingLayoutContext context)
|
||||
{
|
||||
OnElementMeasured(
|
||||
element,
|
||||
|
||||
@@ -338,10 +338,10 @@ namespace Avalonia.Layout
|
||||
Rect IFlowLayoutAlgorithmDelegates.Algorithm_GetExtent(
|
||||
Size availableSize,
|
||||
VirtualizingLayoutContext context,
|
||||
ILayoutable? firstRealized,
|
||||
Layoutable? firstRealized,
|
||||
int firstRealizedItemIndex,
|
||||
Rect firstRealizedLayoutBounds,
|
||||
ILayoutable? lastRealized,
|
||||
Layoutable? lastRealized,
|
||||
int lastRealizedItemIndex,
|
||||
Rect lastRealizedLayoutBounds)
|
||||
{
|
||||
@@ -391,7 +391,7 @@ namespace Avalonia.Layout
|
||||
return extent;
|
||||
}
|
||||
|
||||
void IFlowLayoutAlgorithmDelegates.Algorithm_OnElementMeasured(ILayoutable element, int index, Size availableSize, Size measureSize, Size desiredSize, Size provisionalArrangeSize, VirtualizingLayoutContext context)
|
||||
void IFlowLayoutAlgorithmDelegates.Algorithm_OnElementMeasured(Layoutable element, int index, Size availableSize, Size measureSize, Size desiredSize, Size provisionalArrangeSize, VirtualizingLayoutContext context)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Avalonia.Layout
|
||||
// If it does not, then we need to do context.GetElement(0) at which point we have requested an element and are on point to clear it.
|
||||
// If we are responsible for clearing element 0 we keep m_cachedFirstElement valid.
|
||||
// If we are not (because FlowLayoutAlgorithm is holding it for us) then we just null out this field and use the one from FlowLayoutAlgorithm.
|
||||
private ILayoutable? _cachedFirstElement;
|
||||
private Layoutable? _cachedFirstElement;
|
||||
|
||||
internal FlowLayoutAlgorithm FlowAlgorithm { get; } = new FlowLayoutAlgorithm();
|
||||
internal double EffectiveItemWidth { get; private set; }
|
||||
@@ -91,7 +91,7 @@ namespace Avalonia.Layout
|
||||
}
|
||||
|
||||
private void SetSize(
|
||||
ILayoutable element,
|
||||
Layoutable element,
|
||||
double layoutItemWidth,
|
||||
double layoutItemHeight,
|
||||
Size availableSize,
|
||||
|
||||
@@ -19,18 +19,18 @@ namespace Avalonia.Layout
|
||||
set => _virtualizingContext.LayoutState = value;
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<ILayoutable> ChildrenCore =>
|
||||
protected override IReadOnlyList<Layoutable> ChildrenCore =>
|
||||
_children ?? (_children = new ChildrenCollection(_virtualizingContext));
|
||||
|
||||
private class ChildrenCollection : IReadOnlyList<ILayoutable>
|
||||
private class ChildrenCollection : IReadOnlyList<Layoutable>
|
||||
{
|
||||
private readonly VirtualizingLayoutContext _context;
|
||||
public ChildrenCollection(VirtualizingLayoutContext context) => _context = context;
|
||||
public ILayoutable this[int index] => _context.GetOrCreateElementAt(index);
|
||||
public Layoutable this[int index] => _context.GetOrCreateElementAt(index);
|
||||
public int Count => _context.ItemCount;
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public IEnumerator<ILayoutable> GetEnumerator()
|
||||
public IEnumerator<Layoutable> GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; ++i)
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Avalonia.Layout
|
||||
/// This method calls <see cref="GetOrCreateElementAtCore(int, ElementRealizationOptions)"/>
|
||||
/// with options set to None. GetElementAtCore must be implemented in a derived class.
|
||||
/// </remarks>
|
||||
public ILayoutable GetOrCreateElementAt(int index)
|
||||
public Layoutable GetOrCreateElementAt(int index)
|
||||
=> GetOrCreateElementAtCore(index, ElementRealizationOptions.None);
|
||||
|
||||
/// <summary>
|
||||
@@ -140,7 +140,7 @@ namespace Avalonia.Layout
|
||||
/// advanced layouts that choose to explicitly manage the realization and recycling of
|
||||
/// elements as a performance optimization.
|
||||
/// </remarks>
|
||||
public ILayoutable GetOrCreateElementAt(int index, ElementRealizationOptions options)
|
||||
public Layoutable GetOrCreateElementAt(int index, ElementRealizationOptions options)
|
||||
=> GetOrCreateElementAtCore(index, options);
|
||||
|
||||
/// <summary>
|
||||
@@ -148,10 +148,10 @@ namespace Avalonia.Layout
|
||||
/// </summary>
|
||||
/// <param name="element">The element to clear.</param>
|
||||
/// <remarks>
|
||||
/// This method calls <see cref="RecycleElementCore(ILayoutable)"/>, which must be implemented
|
||||
/// This method calls <see cref="RecycleElementCore(Layoutable)"/>, which must be implemented
|
||||
/// in a derived class.
|
||||
/// </remarks>
|
||||
public void RecycleElement(ILayoutable element) => RecycleElementCore(element);
|
||||
public void RecycleElement(Layoutable element) => RecycleElementCore(element);
|
||||
|
||||
/// <summary>
|
||||
/// When implemented in a derived class, retrieves the number of items in the data.
|
||||
@@ -180,14 +180,14 @@ namespace Avalonia.Layout
|
||||
/// A value of <see cref="ElementRealizationOptions"/> that specifies whether to suppress
|
||||
/// automatic recycling of the retrieved element or force creation of a new element.
|
||||
/// </param>
|
||||
protected abstract ILayoutable GetOrCreateElementAtCore(int index, ElementRealizationOptions options);
|
||||
protected abstract Layoutable GetOrCreateElementAtCore(int index, ElementRealizationOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// When implemented in a derived class, clears the specified UIElement and allows it to be
|
||||
/// either re-used or released.
|
||||
/// </summary>
|
||||
/// <param name="element">The element to clear.</param>
|
||||
protected abstract void RecycleElementCore(ILayoutable element);
|
||||
protected abstract void RecycleElementCore(Layoutable element);
|
||||
|
||||
internal NonVirtualizingLayoutContext GetNonVirtualizingContextAdapter() =>
|
||||
_contextAdapter ?? (_contextAdapter = new VirtualLayoutContextAdapter(this));
|
||||
|
||||
@@ -20,6 +20,6 @@ namespace Avalonia.Layout
|
||||
|
||||
public UvMeasure? Position { get; internal set; }
|
||||
|
||||
public ILayoutable? Element { get; internal set; }
|
||||
public Layoutable? Element { get; internal set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
|
||||
namespace Avalonia.Media
|
||||
{
|
||||
/// <summary>
|
||||
/// Paints an area with an <see cref="IVisual"/>.
|
||||
/// Paints an area with an <see cref="Visual"/>.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface IVisualBrush : ITileBrush
|
||||
@@ -12,6 +12,6 @@ namespace Avalonia.Media
|
||||
/// <summary>
|
||||
/// Gets the visual to draw.
|
||||
/// </summary>
|
||||
IVisual Visual { get; }
|
||||
Visual Visual { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Avalonia.Media.Imaging
|
||||
/// Renders a visual to the <see cref="RenderTargetBitmap"/>.
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual to render.</param>
|
||||
public void Render(IVisual visual) => ImmediateRenderer.Render(visual, this);
|
||||
public void Render(Visual visual) => ImmediateRenderer.Render(visual, this);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a platform-specific implementation for a <see cref="RenderTargetBitmap"/>.
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Avalonia.Media.Immutable
|
||||
/// <param name="tileMode">The tile mode.</param>
|
||||
/// <param name="bitmapInterpolationMode">Controls the quality of interpolation.</param>
|
||||
public ImmutableVisualBrush(
|
||||
IVisual visual,
|
||||
Visual visual,
|
||||
AlignmentX alignmentX = AlignmentX.Center,
|
||||
AlignmentY alignmentY = AlignmentY.Center,
|
||||
RelativeRect? destinationRect = null,
|
||||
@@ -62,6 +62,6 @@ namespace Avalonia.Media.Immutable
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IVisual Visual { get; }
|
||||
public Visual Visual { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@ using Avalonia.VisualTree;
|
||||
namespace Avalonia.Media
|
||||
{
|
||||
/// <summary>
|
||||
/// Paints an area with an <see cref="IVisual"/>.
|
||||
/// Paints an area with an <see cref="Visual"/>.
|
||||
/// </summary>
|
||||
public class VisualBrush : TileBrush, IVisualBrush
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="Visual"/> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<IVisual> VisualProperty =
|
||||
AvaloniaProperty.Register<VisualBrush, IVisual>(nameof(Visual));
|
||||
public static readonly StyledProperty<Visual> VisualProperty =
|
||||
AvaloniaProperty.Register<VisualBrush, Visual>(nameof(Visual));
|
||||
|
||||
static VisualBrush()
|
||||
{
|
||||
@@ -30,7 +30,7 @@ namespace Avalonia.Media
|
||||
/// Initializes a new instance of the <see cref="VisualBrush"/> class.
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual to draw.</param>
|
||||
public VisualBrush(IVisual visual)
|
||||
public VisualBrush(Visual visual)
|
||||
{
|
||||
Visual = visual;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace Avalonia.Media
|
||||
/// <summary>
|
||||
/// Gets or sets the visual to draw.
|
||||
/// </summary>
|
||||
public IVisual Visual
|
||||
public Visual Visual
|
||||
{
|
||||
get { return GetValue(VisualProperty); }
|
||||
set { SetValue(VisualProperty, value); }
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace Avalonia.PropertyStore
|
||||
|
||||
private class UncommonFields
|
||||
{
|
||||
public Func<IAvaloniaObject, T, T>? _coerce;
|
||||
public Func<AvaloniaObject, T, T>? _coerce;
|
||||
public T? _uncoercedValue;
|
||||
public T? _uncoercedBaseValue;
|
||||
}
|
||||
|
||||
@@ -23,18 +23,6 @@ namespace Avalonia.PropertyStore
|
||||
return v;
|
||||
}
|
||||
|
||||
public static bool TryConvertAndValidate(
|
||||
AvaloniaProperty property,
|
||||
object? value,
|
||||
out object? result)
|
||||
{
|
||||
if (TypeUtilities.TryConvertImplicit(property.PropertyType, value, out result))
|
||||
return ((IStyledPropertyAccessor)property).ValidateValue(result);
|
||||
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryConvertAndValidate<T>(
|
||||
StyledPropertyBase<T> property,
|
||||
object? value,
|
||||
|
||||
@@ -6,15 +6,15 @@ namespace Avalonia.Reactive
|
||||
{
|
||||
internal class AvaloniaPropertyBindingObservable<T> : LightweightObservableBase<BindingValue<T>>, IDescription
|
||||
{
|
||||
private readonly WeakReference<IAvaloniaObject> _target;
|
||||
private readonly WeakReference<AvaloniaObject> _target;
|
||||
private readonly AvaloniaProperty _property;
|
||||
private BindingValue<T> _value = BindingValue<T>.Unset;
|
||||
|
||||
public AvaloniaPropertyBindingObservable(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty property)
|
||||
{
|
||||
_target = new WeakReference<IAvaloniaObject>(target);
|
||||
_target = new WeakReference<AvaloniaObject>(target);
|
||||
_property = property;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@ namespace Avalonia.Reactive
|
||||
LightweightObservableBase<AvaloniaPropertyChangedEventArgs>,
|
||||
IDescription
|
||||
{
|
||||
private readonly WeakReference<IAvaloniaObject> _target;
|
||||
private readonly WeakReference<AvaloniaObject> _target;
|
||||
private readonly AvaloniaProperty _property;
|
||||
|
||||
public AvaloniaPropertyChangedObservable(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty property)
|
||||
{
|
||||
_target = new WeakReference<IAvaloniaObject>(target);
|
||||
_target = new WeakReference<AvaloniaObject>(target);
|
||||
_property = property;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@ namespace Avalonia.Reactive
|
||||
{
|
||||
internal class AvaloniaPropertyObservable<T> : LightweightObservableBase<T>, IDescription
|
||||
{
|
||||
private readonly WeakReference<IAvaloniaObject> _target;
|
||||
private readonly WeakReference<AvaloniaObject> _target;
|
||||
private readonly AvaloniaProperty _property;
|
||||
private Optional<T> _value;
|
||||
|
||||
public AvaloniaPropertyObservable(
|
||||
IAvaloniaObject target,
|
||||
AvaloniaObject target,
|
||||
AvaloniaProperty property)
|
||||
{
|
||||
_target = new WeakReference<IAvaloniaObject>(target);
|
||||
_target = new WeakReference<AvaloniaObject>(target);
|
||||
_property = property;
|
||||
}
|
||||
|
||||
@@ -49,31 +49,23 @@ namespace Avalonia.Reactive
|
||||
{
|
||||
if (e.Property == _property)
|
||||
{
|
||||
if (e.Sender is AvaloniaObject ao)
|
||||
T newValue;
|
||||
|
||||
if (e is AvaloniaPropertyChangedEventArgs<T> typed)
|
||||
{
|
||||
T newValue;
|
||||
|
||||
if (e is AvaloniaPropertyChangedEventArgs<T> typed)
|
||||
{
|
||||
newValue = AvaloniaObjectExtensions.GetValue(ao, typed.Property);
|
||||
}
|
||||
else
|
||||
{
|
||||
newValue = (T)e.Sender.GetValue(e.Property)!;
|
||||
}
|
||||
|
||||
if (!_value.HasValue ||
|
||||
!EqualityComparer<T>.Default.Equals(newValue, _value.Value))
|
||||
{
|
||||
_value = newValue;
|
||||
PublishNext(_value.Value!);
|
||||
}
|
||||
newValue = AvaloniaObjectExtensions.GetValue(e.Sender, typed.Property);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
|
||||
newValue = (T)e.Sender.GetValue(e.Property)!;
|
||||
}
|
||||
|
||||
if (!_value.HasValue ||
|
||||
!EqualityComparer<T>.Default.Equals(newValue, _value.Value))
|
||||
{
|
||||
_value = newValue;
|
||||
PublishNext(_value.Value!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CompositingRenderer : IRendererWithCompositor
|
||||
_compositor = compositor;
|
||||
_recordingContext = new DrawingContext(_recorder);
|
||||
CompositionTarget = compositor.CreateCompositionTarget(root.CreateRenderTarget);
|
||||
CompositionTarget.Root = ((Visual)root!.VisualRoot!).AttachToCompositor(compositor);
|
||||
CompositionTarget.Root = ((Visual)root).AttachToCompositor(compositor);
|
||||
_update = Update;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class CompositingRenderer : IRendererWithCompositor
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void AddDirty(IVisual visual)
|
||||
public void AddDirty(Visual visual)
|
||||
{
|
||||
if (_updating)
|
||||
throw new InvalidOperationException("Visual was invalidated during the render pass");
|
||||
@@ -84,7 +84,7 @@ public class CompositingRenderer : IRendererWithCompositor
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool>? filter)
|
||||
public IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool>? filter)
|
||||
{
|
||||
Func<CompositionVisual, bool>? f = null;
|
||||
if (filter != null)
|
||||
@@ -109,14 +109,14 @@ public class CompositingRenderer : IRendererWithCompositor
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IVisual? HitTestFirst(Point p, IVisual root, Func<IVisual, bool>? filter)
|
||||
public Visual? HitTestFirst(Point p, Visual root, Func<Visual, bool>? filter)
|
||||
{
|
||||
// TODO: Optimize
|
||||
return HitTest(p, root, filter).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RecalculateChildren(IVisual visual)
|
||||
public void RecalculateChildren(Visual visual)
|
||||
{
|
||||
if (_updating)
|
||||
throw new InvalidOperationException("Visual was invalidated during the render pass");
|
||||
@@ -130,9 +130,9 @@ public class CompositingRenderer : IRendererWithCompositor
|
||||
if(v.CompositionVisual == null)
|
||||
return;
|
||||
var compositionChildren = v.CompositionVisual.Children;
|
||||
var visualChildren = (AvaloniaList<IVisual>)v.GetVisualChildren();
|
||||
var visualChildren = (AvaloniaList<Visual>)v.GetVisualChildren();
|
||||
|
||||
PooledList<(IVisual visual, int index)>? sortedChildren = null;
|
||||
PooledList<(Visual visual, int index)>? sortedChildren = null;
|
||||
if (v.HasNonUniformZIndexChildren && visualChildren.Count > 1)
|
||||
{
|
||||
sortedChildren = new (visualChildren.Count);
|
||||
|
||||
@@ -22,14 +22,14 @@ namespace Avalonia.Rendering
|
||||
{
|
||||
private readonly IDispatcher? _dispatcher;
|
||||
private readonly IRenderLoop? _renderLoop;
|
||||
private readonly IVisual _root;
|
||||
private readonly Visual _root;
|
||||
private readonly ISceneBuilder _sceneBuilder;
|
||||
|
||||
private bool _running;
|
||||
private bool _disposed;
|
||||
private volatile IRef<Scene>? _scene;
|
||||
private DirtyVisuals? _dirty;
|
||||
private HashSet<IVisual>? _recalculateChildren;
|
||||
private HashSet<Visual>? _recalculateChildren;
|
||||
private IRef<IRenderTargetBitmapImpl>? _overlay;
|
||||
private int _lastSceneId = -1;
|
||||
private DisplayDirtyRects _dirtyRectsDisplay = new DisplayDirtyRects();
|
||||
@@ -56,7 +56,7 @@ namespace Avalonia.Rendering
|
||||
IDeferredRendererLock? rendererLock = null) : base(true)
|
||||
{
|
||||
_dispatcher = dispatcher ?? Dispatcher.UIThread;
|
||||
_root = root ?? throw new ArgumentNullException(nameof(root));
|
||||
_root = root as Visual ?? throw new ArgumentNullException(nameof(root));
|
||||
_sceneBuilder = sceneBuilder ?? new SceneBuilder();
|
||||
Layers = new RenderLayers();
|
||||
_renderLoop = renderLoop;
|
||||
@@ -74,7 +74,7 @@ namespace Avalonia.Rendering
|
||||
/// This constructor is intended to be used for unit testing.
|
||||
/// </remarks>
|
||||
public DeferredRenderer(
|
||||
IVisual root,
|
||||
Visual root,
|
||||
IRenderTarget renderTarget,
|
||||
ISceneBuilder? sceneBuilder = null) : base(true)
|
||||
{
|
||||
@@ -116,7 +116,7 @@ namespace Avalonia.Rendering
|
||||
internal IRenderTarget? RenderTarget { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void AddDirty(IVisual visual)
|
||||
public void AddDirty(Visual visual)
|
||||
{
|
||||
_dirty?.Add(visual);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ namespace Avalonia.Rendering
|
||||
DisposeRenderTarget();
|
||||
}
|
||||
|
||||
public void RecalculateChildren(IVisual visual) => _recalculateChildren?.Add(visual);
|
||||
public void RecalculateChildren(Visual visual) => _recalculateChildren?.Add(visual);
|
||||
|
||||
void DisposeRenderTarget()
|
||||
{
|
||||
@@ -163,17 +163,17 @@ namespace Avalonia.Rendering
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool>? filter)
|
||||
public IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool>? filter)
|
||||
{
|
||||
EnsureCanHitTest();
|
||||
|
||||
//It's safe to access _scene here without a lock since
|
||||
//it's only changed from UI thread which we are currently on
|
||||
return _scene?.Item.HitTest(p, root, filter) ?? Enumerable.Empty<IVisual>();
|
||||
return _scene?.Item.HitTest(p, root, filter) ?? Enumerable.Empty<Visual>();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IVisual? HitTestFirst(Point p, IVisual root, Func<IVisual, bool>? filter)
|
||||
public Visual? HitTestFirst(Point p, Visual root, Func<Visual, bool>? filter)
|
||||
{
|
||||
EnsureCanHitTest();
|
||||
|
||||
@@ -414,7 +414,7 @@ namespace Avalonia.Rendering
|
||||
}
|
||||
|
||||
|
||||
private void Render(IDrawingContextImpl context, VisualNode node, IVisual? layer, Rect clipBounds)
|
||||
private void Render(IDrawingContextImpl context, VisualNode node, Visual? layer, Rect clipBounds)
|
||||
{
|
||||
if (layer == null || node.LayerRoot == layer)
|
||||
{
|
||||
@@ -643,7 +643,7 @@ namespace Avalonia.Rendering
|
||||
if (_dirty == null)
|
||||
{
|
||||
_dirty = new DirtyVisuals();
|
||||
_recalculateChildren = new HashSet<IVisual>();
|
||||
_recalculateChildren = new HashSet<Visual>();
|
||||
_sceneBuilder.UpdateAll(scene);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -13,10 +13,10 @@ namespace Avalonia.Rendering
|
||||
/// 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>
|
||||
internal class DirtyVisuals : IEnumerable<Visual>
|
||||
{
|
||||
private SortedDictionary<int, List<IVisual>> _inner = new SortedDictionary<int, List<IVisual>>();
|
||||
private Dictionary<IVisual, int> _index = new Dictionary<IVisual, int>();
|
||||
private SortedDictionary<int, List<Visual>> _inner = new SortedDictionary<int, List<Visual>>();
|
||||
private Dictionary<Visual, int> _index = new Dictionary<Visual, int>();
|
||||
private int _enumerating;
|
||||
|
||||
/// <summary>
|
||||
@@ -28,14 +28,14 @@ namespace Avalonia.Rendering
|
||||
/// Adds a visual to the dirty list.
|
||||
/// </summary>
|
||||
/// <param name="visual">The dirty visual.</param>
|
||||
public void Add(IVisual visual)
|
||||
public void Add(Visual visual)
|
||||
{
|
||||
if (_enumerating > 0)
|
||||
{
|
||||
throw new InvalidOperationException("Visual was invalidated during a render pass");
|
||||
}
|
||||
|
||||
var distance = visual.CalculateDistanceFromAncestor(visual.VisualRoot);
|
||||
var distance = visual.CalculateDistanceFromAncestor((Visual?)visual.GetVisualRoot());
|
||||
|
||||
if (_index.TryGetValue(visual, out var existingDistance))
|
||||
{
|
||||
@@ -50,7 +50,7 @@ namespace Avalonia.Rendering
|
||||
|
||||
if (!_inner.TryGetValue(distance, out var list))
|
||||
{
|
||||
list = new List<IVisual>();
|
||||
list = new List<Visual>();
|
||||
_inner.Add(distance, list);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Avalonia.Rendering
|
||||
/// Gets the dirty visuals, in ascending order of distance to their root.
|
||||
/// </summary>
|
||||
/// <returns>A collection of visuals.</returns>
|
||||
public IEnumerator<IVisual> GetEnumerator()
|
||||
public IEnumerator<Visual> GetEnumerator()
|
||||
{
|
||||
_enumerating++;
|
||||
try
|
||||
|
||||
@@ -24,10 +24,10 @@ namespace Avalonia.Rendering
|
||||
|
||||
public static class CustomSimpleHitTestExtensions
|
||||
{
|
||||
public static bool HitTestCustom(this IVisual visual, Point point)
|
||||
public static bool HitTestCustom(this Visual visual, Point point)
|
||||
=> (visual as ICustomSimpleHitTest)?.HitTest(point) ?? visual.TransformedBounds?.Contains(point) == true;
|
||||
|
||||
public static bool HitTestCustom(this IEnumerable<IVisual> children, Point point)
|
||||
public static bool HitTestCustom(this IEnumerable<Visual> children, Point point)
|
||||
=> children.Any(ctrl => ctrl.HitTestCustom(point));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Avalonia.Rendering
|
||||
/// Represents the root of a renderable tree.
|
||||
/// </summary>
|
||||
[NotClientImplementable]
|
||||
public interface IRenderRoot : IVisual
|
||||
public interface IRenderRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the client size of the window.
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Avalonia.Rendering
|
||||
/// Mark a visual as dirty and needing re-rendering.
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual.</param>
|
||||
void AddDirty(IVisual visual);
|
||||
void AddDirty(Visual visual);
|
||||
|
||||
/// <summary>
|
||||
/// Hit tests a location to find the visuals at the specified point.
|
||||
@@ -46,7 +46,7 @@ namespace Avalonia.Rendering
|
||||
/// children will be excluded from the results.
|
||||
/// </param>
|
||||
/// <returns>The visuals at the specified point, topmost first.</returns>
|
||||
IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter);
|
||||
IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool> filter);
|
||||
|
||||
/// <summary>
|
||||
/// Hit tests a location to find first visual at the specified point.
|
||||
@@ -58,13 +58,13 @@ namespace Avalonia.Rendering
|
||||
/// children will be excluded from the results.
|
||||
/// </param>
|
||||
/// <returns>The visual at the specified point, topmost first.</returns>
|
||||
IVisual? HitTestFirst(Point p, IVisual root, Func<IVisual, bool> filter);
|
||||
Visual? HitTestFirst(Point p, Visual root, Func<Visual, bool> filter);
|
||||
|
||||
/// <summary>
|
||||
/// Informs the renderer that the z-ordering of a visual's children has changed.
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual.</param>
|
||||
void RecalculateChildren(IVisual visual);
|
||||
void RecalculateChildren(Visual visual);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a resize notification is received by the control being rendered.
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Avalonia.Rendering
|
||||
/// </remarks>
|
||||
public class ImmediateRenderer : RendererBase, IRenderer, IVisualBrushRenderer
|
||||
{
|
||||
private readonly IVisual _root;
|
||||
private readonly Visual _root;
|
||||
private readonly IRenderRoot? _renderRoot;
|
||||
private bool _updateTransformedBounds = true;
|
||||
private IRenderTarget? _renderTarget;
|
||||
@@ -27,13 +27,13 @@ namespace Avalonia.Rendering
|
||||
/// Initializes a new instance of the <see cref="ImmediateRenderer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="root">The control to render.</param>
|
||||
public ImmediateRenderer(IVisual root)
|
||||
public ImmediateRenderer(Visual root)
|
||||
{
|
||||
_root = root ?? throw new ArgumentNullException(nameof(root));
|
||||
_renderRoot = root as IRenderRoot;
|
||||
}
|
||||
|
||||
private ImmediateRenderer(IVisual root, bool updateTransformedBounds)
|
||||
private ImmediateRenderer(Visual root, bool updateTransformedBounds)
|
||||
{
|
||||
_root = root ?? throw new ArgumentNullException(nameof(root));
|
||||
_renderRoot = root as IRenderRoot;
|
||||
@@ -102,7 +102,7 @@ namespace Avalonia.Rendering
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual.</param>
|
||||
/// <param name="target">The render target.</param>
|
||||
public static void Render(IVisual visual, IRenderTarget target)
|
||||
public static void Render(Visual visual, IRenderTarget target)
|
||||
{
|
||||
using (var renderer = new ImmediateRenderer(visual, updateTransformedBounds: false))
|
||||
using (var context = new DrawingContext(target.CreateDrawingContext(renderer)))
|
||||
@@ -116,7 +116,7 @@ namespace Avalonia.Rendering
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual.</param>
|
||||
/// <param name="context">The drawing context.</param>
|
||||
public static void Render(IVisual visual, DrawingContext context)
|
||||
public static void Render(Visual visual, DrawingContext context)
|
||||
{
|
||||
using (var renderer = new ImmediateRenderer(visual, updateTransformedBounds: false))
|
||||
{
|
||||
@@ -125,7 +125,7 @@ namespace Avalonia.Rendering
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void AddDirty(IVisual visual)
|
||||
public void AddDirty(Visual visual)
|
||||
{
|
||||
if (visual.Bounds != Rect.Empty)
|
||||
{
|
||||
@@ -162,18 +162,18 @@ namespace Avalonia.Rendering
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
|
||||
public IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool> filter)
|
||||
{
|
||||
return HitTest(root, p, filter);
|
||||
}
|
||||
|
||||
public IVisual? HitTestFirst(Point p, IVisual root, Func<IVisual, bool> filter)
|
||||
public Visual? HitTestFirst(Point p, Visual root, Func<Visual, bool> filter)
|
||||
{
|
||||
return HitTest(root, p, filter).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RecalculateChildren(IVisual visual) => AddDirty(visual);
|
||||
public void RecalculateChildren(Visual visual) => AddDirty(visual);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Start()
|
||||
@@ -199,21 +199,21 @@ namespace Avalonia.Rendering
|
||||
Render(new DrawingContext(context), visual, visual.Bounds);
|
||||
}
|
||||
|
||||
internal static void Render(IVisual visual, DrawingContext context, bool updateTransformedBounds)
|
||||
internal static void Render(Visual visual, DrawingContext context, bool updateTransformedBounds)
|
||||
{
|
||||
using var renderer = new ImmediateRenderer(visual, updateTransformedBounds);
|
||||
renderer.Render(context, visual, visual.Bounds);
|
||||
}
|
||||
|
||||
private static void ClearTransformedBounds(IVisual visual)
|
||||
private static void ClearTransformedBounds(Visual visual)
|
||||
{
|
||||
foreach (var e in visual.GetSelfAndVisualDescendants())
|
||||
{
|
||||
visual.TransformedBounds = null;
|
||||
visual.SetTransformedBounds(null);
|
||||
}
|
||||
}
|
||||
|
||||
private static Rect GetTransformedBounds(IVisual visual)
|
||||
private static Rect GetTransformedBounds(Visual visual)
|
||||
{
|
||||
if (visual.RenderTransform == null)
|
||||
{
|
||||
@@ -228,10 +228,10 @@ namespace Avalonia.Rendering
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<IVisual> HitTest(
|
||||
IVisual visual,
|
||||
private static IEnumerable<Visual> HitTest(
|
||||
Visual visual,
|
||||
Point p,
|
||||
Func<IVisual, bool>? filter)
|
||||
Func<Visual, bool>? filter)
|
||||
{
|
||||
_ = visual ?? throw new ArgumentNullException(nameof(visual));
|
||||
|
||||
@@ -266,7 +266,7 @@ namespace Avalonia.Rendering
|
||||
}
|
||||
}
|
||||
|
||||
private void Render(DrawingContext context, IVisual visual, Rect clipRect)
|
||||
private void Render(DrawingContext context, Visual visual, Rect clipRect)
|
||||
{
|
||||
var opacity = visual.Opacity;
|
||||
var clipToBounds = visual.ClipToBounds;
|
||||
@@ -329,11 +329,11 @@ namespace Avalonia.Rendering
|
||||
#pragma warning restore 0618
|
||||
|
||||
if (_updateTransformedBounds)
|
||||
visual.TransformedBounds = transformed;
|
||||
visual.SetTransformedBounds(transformed);
|
||||
|
||||
var childrenEnumerable = visual.HasNonUniformZIndexChildren
|
||||
? visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)
|
||||
: (IEnumerable<IVisual>)visual.VisualChildren;
|
||||
: (IEnumerable<Visual>)visual.VisualChildren;
|
||||
|
||||
foreach (var child in childrenEnumerable)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Avalonia.Rendering
|
||||
IDrawingContextImpl drawingContext,
|
||||
Size size,
|
||||
double scaling,
|
||||
IVisual layerRoot)
|
||||
Visual layerRoot)
|
||||
{
|
||||
Bitmap = RefCountable.Create(drawingContext.CreateLayer(size));
|
||||
Size = size;
|
||||
@@ -24,7 +24,7 @@ namespace Avalonia.Rendering
|
||||
public bool IsEmpty { get; set; }
|
||||
public double Scaling { get; private set; }
|
||||
public Size Size { get; private set; }
|
||||
public IVisual LayerRoot { get; }
|
||||
public Visual LayerRoot { get; }
|
||||
|
||||
public void RecreateBitmap(IDrawingContextImpl drawingContext, Size size, double scaling)
|
||||
{
|
||||
|
||||
@@ -3,17 +3,16 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Avalonia.Rendering
|
||||
{
|
||||
public class RenderLayers : IEnumerable<RenderLayer>
|
||||
{
|
||||
private readonly List<RenderLayer> _inner = new List<RenderLayer>();
|
||||
private readonly Dictionary<IVisual, RenderLayer> _index = new Dictionary<IVisual, RenderLayer>();
|
||||
private readonly Dictionary<Visual, RenderLayer> _index = new Dictionary<Visual, RenderLayer>();
|
||||
|
||||
public int Count => _inner.Count;
|
||||
public RenderLayer this[IVisual layerRoot] => _index[layerRoot];
|
||||
public RenderLayer this[Visual layerRoot] => _index[layerRoot];
|
||||
|
||||
public void Update(Scene scene, IDrawingContextImpl context)
|
||||
{
|
||||
@@ -59,7 +58,7 @@ namespace Avalonia.Rendering
|
||||
_inner.Clear();
|
||||
}
|
||||
|
||||
public bool TryGetValue(IVisual layerRoot, [NotNullWhen(true)] out RenderLayer? value)
|
||||
public bool TryGetValue(Visual layerRoot, [NotNullWhen(true)] out RenderLayer? value)
|
||||
{
|
||||
return _index.TryGetValue(layerRoot, out value);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <param name="scene">The scene.</param>
|
||||
/// <param name="visual">The visual to update.</param>
|
||||
/// <returns>True if changes were made, otherwise false.</returns>
|
||||
bool Update(Scene scene, IVisual visual);
|
||||
bool Update(Scene scene, Visual visual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Utilities;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Avalonia.Rendering.SceneGraph
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a node in the low-level scene graph representing an <see cref="IVisual"/>.
|
||||
/// Represents a node in the low-level scene graph representing a <see cref="Visual"/>.
|
||||
/// </summary>
|
||||
public interface IVisualNode : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the visual to which the node relates.
|
||||
/// </summary>
|
||||
IVisual Visual { get; }
|
||||
Visual Visual { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent scene graph node.
|
||||
|
||||
@@ -13,24 +13,24 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
public class Scene : IDisposable
|
||||
{
|
||||
private readonly Dictionary<IVisual, IVisualNode> _index;
|
||||
private readonly Dictionary<Visual, IVisualNode> _index;
|
||||
private readonly TaskCompletionSource<bool> _rendered = new TaskCompletionSource<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scene"/> class.
|
||||
/// </summary>
|
||||
/// <param name="rootVisual">The root visual to draw.</param>
|
||||
public Scene(IVisual rootVisual)
|
||||
public Scene(Visual rootVisual)
|
||||
: this(
|
||||
new VisualNode(rootVisual, null),
|
||||
new Dictionary<IVisual, IVisualNode>(),
|
||||
new Dictionary<Visual, IVisualNode>(),
|
||||
new SceneLayers(rootVisual),
|
||||
0)
|
||||
{
|
||||
_index.Add(rootVisual, Root);
|
||||
}
|
||||
|
||||
private Scene(VisualNode root, Dictionary<IVisual, IVisualNode> index, SceneLayers layers, int generation)
|
||||
private Scene(VisualNode root, Dictionary<Visual, IVisualNode> index, SceneLayers layers, int generation)
|
||||
{
|
||||
_ = root ?? throw new ArgumentNullException(nameof(root));
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <returns>The cloned scene.</returns>
|
||||
public Scene CloneScene()
|
||||
{
|
||||
var index = new Dictionary<IVisual, IVisualNode>(_index.Count);
|
||||
var index = new Dictionary<Visual, IVisualNode>(_index.Count);
|
||||
var root = Clone((VisualNode)Root, null, index);
|
||||
|
||||
var result = new Scene(root, index, Layers.Clone(), Generation + 1)
|
||||
@@ -115,7 +115,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <returns>
|
||||
/// The node representing the visual or null if it could not be found.
|
||||
/// </returns>
|
||||
public IVisualNode? FindNode(IVisual visual)
|
||||
public IVisualNode? FindNode(Visual visual)
|
||||
{
|
||||
_index.TryGetValue(visual, out var node);
|
||||
return node;
|
||||
@@ -128,10 +128,10 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <param name="root">The root of the subtree to search.</param>
|
||||
/// <param name="filter">A filter. May be null.</param>
|
||||
/// <returns>The visuals at the specified point.</returns>
|
||||
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool>? filter)
|
||||
public IEnumerable<Visual> HitTest(Point p, Visual root, Func<Visual, bool>? filter)
|
||||
{
|
||||
var node = FindNode(root);
|
||||
return (node != null) ? new HitTestEnumerable(node, filter, p, Root) : Enumerable.Empty<IVisual>();
|
||||
return (node != null) ? new HitTestEnumerable(node, filter, p, Root) : Enumerable.Empty<Visual>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,7 +141,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <param name="root">The root of the subtree to search.</param>
|
||||
/// <param name="filter">A filter. May be null.</param>
|
||||
/// <returns>The visual at the specified point.</returns>
|
||||
public IVisual? HitTestFirst(Point p, IVisual root, Func<IVisual, bool>? filter)
|
||||
public Visual? HitTestFirst(Point p, Visual root, Func<Visual, bool>? filter)
|
||||
{
|
||||
var node = FindNode(root);
|
||||
return (node != null) ? HitTestFirst(node, p, filter) : null;
|
||||
@@ -160,7 +160,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
node.Dispose();
|
||||
}
|
||||
|
||||
private VisualNode Clone(VisualNode source, IVisualNode? parent, Dictionary<IVisual, IVisualNode> index)
|
||||
private VisualNode Clone(VisualNode source, IVisualNode? parent, Dictionary<Visual, IVisualNode> index)
|
||||
{
|
||||
var result = source.Clone(parent);
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
return result;
|
||||
}
|
||||
|
||||
private IVisual HitTestFirst(IVisualNode root, Point p, Func<IVisual, bool>? filter)
|
||||
private Visual HitTestFirst(IVisualNode root, Point p, Func<Visual, bool>? filter)
|
||||
{
|
||||
using var enumerator = new HitTestEnumerator(root, filter, p, Root);
|
||||
|
||||
@@ -193,14 +193,14 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
return enumerator.Current;
|
||||
}
|
||||
|
||||
private class HitTestEnumerable : IEnumerable<IVisual>
|
||||
private class HitTestEnumerable : IEnumerable<Visual>
|
||||
{
|
||||
private readonly IVisualNode _root;
|
||||
private readonly Func<IVisual, bool>? _filter;
|
||||
private readonly Func<Visual, bool>? _filter;
|
||||
private readonly IVisualNode _sceneRoot;
|
||||
private readonly Point _point;
|
||||
|
||||
public HitTestEnumerable(IVisualNode root, Func<IVisual, bool>? filter, Point point, IVisualNode sceneRoot)
|
||||
public HitTestEnumerable(IVisualNode root, Func<Visual, bool>? filter, Point point, IVisualNode sceneRoot)
|
||||
{
|
||||
_root = root;
|
||||
_filter = filter;
|
||||
@@ -208,7 +208,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
_sceneRoot = sceneRoot;
|
||||
}
|
||||
|
||||
public IEnumerator<IVisual> GetEnumerator()
|
||||
public IEnumerator<Visual> GetEnumerator()
|
||||
{
|
||||
return new HitTestEnumerator(_root, _filter, _point, _sceneRoot);
|
||||
}
|
||||
@@ -219,15 +219,15 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
}
|
||||
}
|
||||
|
||||
private struct HitTestEnumerator : IEnumerator<IVisual>
|
||||
private struct HitTestEnumerator : IEnumerator<Visual>
|
||||
{
|
||||
private readonly PooledStack<Entry> _nodeStack;
|
||||
private readonly Func<IVisual, bool>? _filter;
|
||||
private readonly Func<Visual, bool>? _filter;
|
||||
private readonly IVisualNode _sceneRoot;
|
||||
private IVisual? _current;
|
||||
private Visual? _current;
|
||||
private readonly Point _point;
|
||||
|
||||
public HitTestEnumerator(IVisualNode root, Func<IVisual, bool>? filter, Point point, IVisualNode sceneRoot)
|
||||
public HitTestEnumerator(IVisualNode root, Func<Visual, bool>? filter, Point point, IVisualNode sceneRoot)
|
||||
{
|
||||
_nodeStack = new PooledStack<Entry>();
|
||||
_nodeStack.Push(new Entry(root, false, null, true));
|
||||
@@ -282,7 +282,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public IVisual Current => _current!;
|
||||
public Visual Current => _current!;
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Update(Scene scene, IVisual visual)
|
||||
public bool Update(Scene scene, Visual visual)
|
||||
{
|
||||
_ = scene ?? throw new ArgumentNullException(nameof(scene));
|
||||
_ = visual ?? throw new ArgumentNullException(nameof(visual));
|
||||
@@ -120,7 +120,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
return false;
|
||||
}
|
||||
|
||||
private static VisualNode? FindExistingAncestor(Scene scene, IVisual visual)
|
||||
private static VisualNode? FindExistingAncestor(Scene scene, Visual visual)
|
||||
{
|
||||
var node = scene.FindNode(visual);
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
return (VisualNode)node;
|
||||
}
|
||||
|
||||
private static object GetOrCreateChildNode(Scene scene, IVisual child, VisualNode parent)
|
||||
private static object GetOrCreateChildNode(Scene scene, Visual child, VisualNode parent)
|
||||
{
|
||||
var result = (VisualNode?)scene.FindNode(child);
|
||||
|
||||
@@ -259,11 +259,11 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
catch { }
|
||||
|
||||
var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform);
|
||||
visual.TransformedBounds = transformed;
|
||||
visual.SetTransformedBounds(transformed);
|
||||
|
||||
if (forceRecurse)
|
||||
{
|
||||
var visualChildren = (IList<IVisual>) visual.VisualChildren;
|
||||
var visualChildren = (IList<Visual>) visual.VisualChildren;
|
||||
|
||||
node.TryPreallocateChildren(visualChildren.Count);
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
|
||||
if (visual.HasNonUniformZIndexChildren)
|
||||
{
|
||||
var sortedChildren = new (IVisual visual, int index)[count];
|
||||
var sortedChildren = new (Visual visual, int index)[count];
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
@@ -352,7 +352,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
}
|
||||
}
|
||||
|
||||
private static VisualNode CreateNode(Scene scene, IVisual visual, VisualNode parent)
|
||||
private static VisualNode CreateNode(Scene scene, Visual visual, VisualNode parent)
|
||||
{
|
||||
var node = new VisualNode(visual, parent);
|
||||
node.LayerRoot = parent.LayerRoot;
|
||||
@@ -379,7 +379,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
|
||||
scene.Layers[node.LayerRoot!].Dirty.Add(node.Bounds);
|
||||
|
||||
node.Visual.TransformedBounds = null;
|
||||
node.Visual.SetTransformedBounds(null);
|
||||
|
||||
if (node.LayerRoot == node.Visual && node.Visual != scene.Root.Visual)
|
||||
{
|
||||
@@ -455,7 +455,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
}
|
||||
|
||||
// HACK: Disabled layers because they're broken in current renderer. See #2244.
|
||||
private static bool ShouldStartLayer(IVisual visual) => false;
|
||||
private static bool ShouldStartLayer(Visual visual) => false;
|
||||
|
||||
private static IGeometryImpl? CreateLayerGeometryClip(VisualNode node)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Avalonia.Rendering.SceneGraph
|
||||
{
|
||||
@@ -14,7 +13,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="layerRoot">The visual at the root of the layer.</param>
|
||||
/// <param name="distanceFromRoot">The distance from the scene root.</param>
|
||||
public SceneLayer(IVisual layerRoot, int distanceFromRoot)
|
||||
public SceneLayer(Visual layerRoot, int distanceFromRoot)
|
||||
{
|
||||
LayerRoot = layerRoot;
|
||||
Dirty = new DirtyRects();
|
||||
@@ -39,7 +38,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <summary>
|
||||
/// Gets the visual at the root of the layer.
|
||||
/// </summary>
|
||||
public IVisual LayerRoot { get; }
|
||||
public Visual LayerRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the distance of the layer root from the root of the scene.
|
||||
|
||||
@@ -10,15 +10,15 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
public class SceneLayers : IEnumerable<SceneLayer>
|
||||
{
|
||||
private readonly IVisual _root;
|
||||
private readonly Visual _root;
|
||||
private readonly List<SceneLayer> _inner;
|
||||
private readonly Dictionary<IVisual, SceneLayer> _index;
|
||||
private readonly Dictionary<Visual, SceneLayer> _index;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SceneLayers"/> class.
|
||||
/// </summary>
|
||||
/// <param name="root">The scene's root visual.</param>
|
||||
public SceneLayers(IVisual root) : this(root, 0)
|
||||
public SceneLayers(Visual root) : this(root, 0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="root">The scene's root visual.</param>
|
||||
/// <param name="capacity">Initial layer capacity.</param>
|
||||
public SceneLayers(IVisual root, int capacity)
|
||||
public SceneLayers(Visual root, int capacity)
|
||||
{
|
||||
_root = root;
|
||||
|
||||
_inner = new List<SceneLayer>(capacity);
|
||||
_index = new Dictionary<IVisual, SceneLayer>(capacity);
|
||||
_index = new Dictionary<Visual, SceneLayer>(capacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -71,14 +71,14 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="visual">The layer's root visual.</param>
|
||||
/// <returns>The layer.</returns>
|
||||
public SceneLayer this[IVisual visual] => _index[visual];
|
||||
public SceneLayer this[Visual visual] => _index[visual];
|
||||
|
||||
/// <summary>
|
||||
/// Adds a layer to the scene.
|
||||
/// </summary>
|
||||
/// <param name="layerRoot">The root visual of the layer.</param>
|
||||
/// <returns>The created layer.</returns>
|
||||
public SceneLayer Add(IVisual layerRoot)
|
||||
public SceneLayer Add(Visual layerRoot)
|
||||
{
|
||||
_ = layerRoot ?? throw new ArgumentNullException(nameof(layerRoot));
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// <returns>
|
||||
/// True if a layer exists with the specified root visual, otherwise false.
|
||||
/// </returns>
|
||||
public bool Exists(IVisual layerRoot)
|
||||
public bool Exists(Visual layerRoot)
|
||||
{
|
||||
_ = layerRoot ?? throw new ArgumentNullException(nameof(layerRoot));
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="layerRoot">The root visual.</param>
|
||||
/// <returns>The layer if found, otherwise null.</returns>
|
||||
public SceneLayer? Find(IVisual layerRoot)
|
||||
public SceneLayer? Find(Visual layerRoot)
|
||||
{
|
||||
_index.TryGetValue(layerRoot, out var result);
|
||||
return result;
|
||||
@@ -138,7 +138,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="layerRoot">The root visual.</param>
|
||||
/// <returns>The layer.</returns>
|
||||
public SceneLayer GetOrAdd(IVisual layerRoot)
|
||||
public SceneLayer GetOrAdd(Visual layerRoot)
|
||||
{
|
||||
_ = layerRoot ?? throw new ArgumentNullException(nameof(layerRoot));
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="layerRoot">The root visual.</param>
|
||||
/// <returns>True if a matching layer was removed, otherwise false.</returns>
|
||||
public bool Remove(IVisual layerRoot)
|
||||
public bool Remove(Visual layerRoot)
|
||||
{
|
||||
_ = layerRoot ?? throw new ArgumentNullException(nameof(layerRoot));
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
/// <param name="visual">The visual that this node represents.</param>
|
||||
/// <param name="parent">The parent scene graph node, if any.</param>
|
||||
public VisualNode(IVisual visual, IVisualNode? parent)
|
||||
public VisualNode(Visual visual, IVisualNode? parent)
|
||||
{
|
||||
Visual = visual ?? throw new ArgumentNullException(nameof(visual));
|
||||
Parent = parent;
|
||||
@@ -39,7 +39,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IVisual Visual { get; }
|
||||
public Visual Visual { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IVisualNode? Parent { get; }
|
||||
@@ -98,7 +98,7 @@ namespace Avalonia.Rendering.SceneGraph
|
||||
/// </summary>
|
||||
public bool OpacityChanged { get; private set; }
|
||||
|
||||
public IVisual? LayerRoot { get; set; }
|
||||
public Visual? LayerRoot { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<IVisualNode> Children => _children ?? EmptyChildren;
|
||||
|
||||
@@ -4,11 +4,11 @@ using Avalonia.VisualTree;
|
||||
|
||||
namespace Avalonia.Rendering
|
||||
{
|
||||
public class ZIndexComparer : IComparer<IVisual>
|
||||
public class ZIndexComparer : IComparer<Visual>
|
||||
{
|
||||
public static readonly ZIndexComparer Instance = new ZIndexComparer();
|
||||
public static readonly Comparison<IVisual> ComparisonInstance = Instance.Compare;
|
||||
public static readonly Comparison<Visual> ComparisonInstance = Instance.Compare;
|
||||
|
||||
public int Compare(IVisual? x, IVisual? y) => (x?.ZIndex ?? 0).CompareTo(y?.ZIndex ?? 0);
|
||||
public int Compare(Visual? x, Visual? y) => (x?.ZIndex ?? 0).CompareTo(y?.ZIndex ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user