Browse Source

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

Allow for disabling clipping of adorners. Cleanup AdornerLayer class.
pull/6258/head
Jumar Macato 5 years ago
committed by GitHub
parent
commit
b57e984327
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 67
      src/Avalonia.Controls/Primitives/AdornerLayer.cs

67
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.
/// <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 static readonly AttachedProperty<Visual> AdornedElementProperty =
AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, Visual>("AdornedElement");
/// <summary>
/// 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 =
AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, AdornedElementInfo>("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<VisualLayerManager>()?.AdornerLayer;
}
public static bool GetIsClipEnabled(Visual adorner)
{
return visual.GetVisualAncestors()
.OfType<VisualLayerManager>()
.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<Visual?> e)
{
var adorner = (Visual)e.Sender;
var adorned = (Visual)e.NewValue;
var adorned = e.NewValue.GetValueOrDefault();
var layer = adorner.GetVisualParent<AdornerLayer>();
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; }
}

Loading…
Cancel
Save