Browse Source

Merge pull request #6235 from MarchingCube/adorner-layer-clipping

Allow for disabling clipping of adorners. Cleanup AdornerLayer class.
release/0.10.7
Jumar Macato 5 years ago
committed by Dan Walmsley
parent
commit
3393a7564f
  1. 67
      src/Avalonia.Controls/Primitives/AdornerLayer.cs

67
src/Avalonia.Controls/Primitives/AdornerLayer.cs

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

Loading…
Cancel
Save