diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
index a397608aba..52c8273b6c 100644
--- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs
+++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
@@ -1,19 +1,33 @@
using System;
using System.Collections.Specialized;
-using System.Linq;
-using System.Resources;
using Avalonia.Media;
using Avalonia.Rendering;
-using Avalonia.Utilities;
using Avalonia.VisualTree;
+#nullable enable
+
namespace Avalonia.Controls.Primitives
{
- // TODO: Need to track position of adorned elements and move the adorner if they move.
+ ///
+ /// Represents a surface for showing adorners.
+ /// Adorners are always on top of the adorned element and are positioned to stay relative to the adorned element.
+ ///
+ ///
+ /// TODO: Need to track position of adorned elements and move the adorner if they move.
+ ///
public class AdornerLayer : Canvas, ICustomSimpleHitTest
{
- public static readonly AttachedProperty AdornedElementProperty =
- AvaloniaProperty.RegisterAttached("AdornedElement");
+ ///
+ /// Allows for getting and setting of the adorned element.
+ ///
+ public static readonly AttachedProperty AdornedElementProperty =
+ AvaloniaProperty.RegisterAttached("AdornedElement");
+
+ ///
+ /// Allows for controlling clipping of the adorner.
+ ///
+ public static readonly AttachedProperty IsClipEnabledProperty =
+ AvaloniaProperty.RegisterAttached("IsClipEnabled", true);
private static readonly AttachedProperty s_adornedElementInfoProperty =
AvaloniaProperty.RegisterAttached("AdornedElementInfo");
@@ -28,7 +42,7 @@ namespace Avalonia.Controls.Primitives
Children.CollectionChanged += ChildrenCollectionChanged;
}
- public static Visual GetAdornedElement(Visual adorner)
+ public static Visual? GetAdornedElement(Visual adorner)
{
return adorner.GetValue(AdornedElementProperty);
}
@@ -38,12 +52,19 @@ namespace Avalonia.Controls.Primitives
adorner.SetValue(AdornedElementProperty, adorned);
}
- public static AdornerLayer GetAdornerLayer(IVisual visual)
+ public static AdornerLayer? GetAdornerLayer(IVisual visual)
+ {
+ return visual.FindAncestorOfType()?.AdornerLayer;
+ }
+
+ public static bool GetIsClipEnabled(Visual adorner)
{
- return visual.GetVisualAncestors()
- .OfType()
- .FirstOrDefault()
- ?.AdornerLayer;
+ return adorner.GetValue(IsClipEnabledProperty);
+ }
+
+ public static void SetIsClipEnabled(Visual adorner, bool isClipEnabled)
+ {
+ adorner.SetValue(IsClipEnabledProperty, isClipEnabled);
}
protected override Size MeasureOverride(Size availableSize)
@@ -70,12 +91,13 @@ namespace Avalonia.Controls.Primitives
foreach (var child in Children)
{
var info = child.GetValue(s_adornedElementInfoProperty);
+ var isClipEnabled = child.GetValue(IsClipEnabledProperty);
if (info != null && info.Bounds.HasValue)
{
child.RenderTransform = new MatrixTransform(info.Bounds.Value.Transform);
child.RenderTransformOrigin = new RelativePoint(new Point(0,0), RelativeUnit.Absolute);
- UpdateClip(child, info.Bounds.Value);
+ UpdateClip(child, info.Bounds.Value, isClipEnabled);
child.Arrange(info.Bounds.Value.Bounds);
}
else
@@ -87,16 +109,23 @@ namespace Avalonia.Controls.Primitives
return finalSize;
}
- private static void AdornedElementChanged(AvaloniaPropertyChangedEventArgs e)
+ private static void AdornedElementChanged(AvaloniaPropertyChangedEventArgs e)
{
var adorner = (Visual)e.Sender;
- var adorned = (Visual)e.NewValue;
+ var adorned = e.NewValue.GetValueOrDefault();
var layer = adorner.GetVisualParent();
layer?.UpdateAdornedElement(adorner, adorned);
}
- private void UpdateClip(IControl control, TransformedBounds bounds)
+ private void UpdateClip(IControl control, TransformedBounds bounds, bool isEnabled)
{
+ if (!isEnabled)
+ {
+ control.Clip = null;
+
+ return;
+ }
+
if (!(control.Clip is RectangleGeometry clip))
{
clip = new RectangleGeometry();
@@ -129,13 +158,13 @@ namespace Avalonia.Controls.Primitives
InvalidateArrange();
}
- private void UpdateAdornedElement(Visual adorner, Visual adorned)
+ private void UpdateAdornedElement(Visual adorner, Visual? adorned)
{
var info = adorner.GetValue(s_adornedElementInfoProperty);
if (info != null)
{
- info.Subscription.Dispose();
+ info.Subscription!.Dispose();
if (adorned == null)
{
@@ -163,7 +192,7 @@ namespace Avalonia.Controls.Primitives
private class AdornedElementInfo
{
- public IDisposable Subscription { get; set; }
+ public IDisposable? Subscription { get; set; }
public TransformedBounds? Bounds { get; set; }
}