Browse Source

Change TransformedBounds to a direct property on Visual (exposed on IVisual) instead of using an attached property in BoundsTracker.

Jeremy Koritzinsky 8 years ago
parent
commit
f65ae1918f

+ 1 - 3
src/Avalonia.Controls/Primitives/AdornerLayer.cs

@@ -18,8 +18,6 @@ namespace Avalonia.Controls.Primitives
         private static readonly AttachedProperty<AdornedElementInfo> s_adornedElementInfoProperty =
             AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, AdornedElementInfo>("AdornedElementInfo");
 
-        private readonly BoundsTracker _tracker = new BoundsTracker();
-
         static AdornerLayer()
         {
             AdornedElementProperty.Changed.Subscribe(AdornedElementChanged);
@@ -118,7 +116,7 @@ namespace Avalonia.Controls.Primitives
                     adorner.SetValue(s_adornedElementInfoProperty, info);
                 }
 
-                info.Subscription = _tracker.Track(adorned).Subscribe(x =>
+                info.Subscription = adorned.GetObservable(TransformedBoundsProperty).Subscribe(x =>
                 {
                     info.Bounds = x;
                     InvalidateArrange();

+ 3 - 6
src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs

@@ -169,7 +169,7 @@ namespace Avalonia.Rendering
         {
             foreach (var e in visual.GetSelfAndVisualDescendants())
             {
-                BoundsTracker.SetTransformedBounds((Visual)visual, null);
+                visual.TransformedBounds = null;
             }
         }
 
@@ -197,7 +197,7 @@ namespace Avalonia.Rendering
 
             if (filter?.Invoke(visual) != false)
             {
-                bool containsPoint = BoundsTracker.GetTransformedBounds((Visual)visual)?.Contains(p) == true;
+                bool containsPoint = visual.TransformedBounds?.Contains(p) == true;
 
                 if ((containsPoint || !visual.ClipToBounds) && visual.VisualChildren.Count > 0)
                 {
@@ -257,10 +257,7 @@ namespace Avalonia.Rendering
                         new TransformedBounds(bounds, new Rect(), context.CurrentContainerTransform);
 #pragma warning restore 0618
 
-                    if (visual is Visual)
-                    {
-                        BoundsTracker.SetTransformedBounds((Visual)visual, transformed);
-                    }
+                    visual.TransformedBounds = transformed;
 
                     foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
                     {

+ 3 - 9
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@@ -209,11 +209,8 @@ namespace Avalonia.Rendering.SceneGraph
                     }
                     catch { }
 
-                    if (visual is Visual)
-                    {
-                        var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform);
-                        BoundsTracker.SetTransformedBounds((Visual)visual, transformed);
-                    }
+                    var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform);
+                    visual.TransformedBounds = transformed;
 
                     if (forceRecurse)
                     {
@@ -279,10 +276,7 @@ namespace Avalonia.Rendering.SceneGraph
 
             scene.Layers[node.LayerRoot].Dirty.Add(node.Bounds);
 
-            if (node.Visual is Visual v)
-            {
-                BoundsTracker.SetTransformedBounds(v, null);
-            }
+            node.Visual.TransformedBounds = null;
 
             foreach (VisualNode child in node.Children)
             {

+ 17 - 0
src/Avalonia.Visuals/Visual.cs

@@ -32,6 +32,11 @@ namespace Avalonia
         public static readonly DirectProperty<Visual, Rect> BoundsProperty =
             AvaloniaProperty.RegisterDirect<Visual, Rect>(nameof(Bounds), o => o.Bounds);
 
+        public static readonly DirectProperty<Visual, TransformedBounds?> TransformedBoundsProperty =
+            AvaloniaProperty.RegisterDirect<Visual, TransformedBounds?>(
+                nameof(TransformedBounds),
+                o => o.TransformedBounds);
+
         /// <summary>
         /// Defines the <see cref="ClipToBounds"/> property.
         /// </summary>
@@ -87,6 +92,7 @@ namespace Avalonia
             AvaloniaProperty.Register<Visual, int>(nameof(ZIndex));
 
         private Rect _bounds;
+        private TransformedBounds? _transformedBounds;
         private IRenderRoot _visualRoot;
         private IVisual _visualParent;
 
@@ -135,6 +141,11 @@ namespace Avalonia
             protected set { SetAndRaise(BoundsProperty, ref _bounds, value); }
         }
 
+        /// <summary>
+        /// Gets the bounds of the control relative to the window, accounting for rendering transforms.
+        /// </summary>
+        public TransformedBounds? TransformedBounds => _transformedBounds;
+
         /// <summary>
         /// Gets a value indicating whether the control should be clipped to its bounds.
         /// </summary>
@@ -253,6 +264,12 @@ namespace Avalonia
         /// Gets the root of the visual tree, if the control is attached to a visual tree.
         /// </summary>
         IRenderRoot IVisual.VisualRoot => VisualRoot;
+        
+        TransformedBounds? IVisual.TransformedBounds
+        {
+            get { return _transformedBounds; }
+            set { SetAndRaise(TransformedBoundsProperty, ref _transformedBounds, value); }
+        }
 
         /// <summary>
         /// Invalidates the visual and queues a repaint.

+ 0 - 51
src/Avalonia.Visuals/VisualTree/BoundsTracker.cs

@@ -1,51 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System;
-
-namespace Avalonia.VisualTree
-{
-    /// <summary>
-    /// Tracks the bounds of a control.
-    /// </summary>
-    /// <remarks>
-    /// This class is used to track a controls's bounds for hit testing.
-    /// TODO: This shouldn't be implemented as an attached property: it would be more performant
-    /// to just store bounds in some sort of central repository.
-    /// </remarks>
-    public class BoundsTracker
-    {
-        /// <summary>
-        /// Defines the TransformedBounds attached property.
-        /// </summary>
-        private static AttachedProperty<TransformedBounds?> TransformedBoundsProperty =
-            AvaloniaProperty.RegisterAttached<BoundsTracker, Visual, TransformedBounds?>("TransformedBounds");
-
-        /// <summary>
-        /// Starts tracking the specified visual.
-        /// </summary>
-        /// <param name="visual">The visual.</param>
-        /// <returns>An observable that returns the tracked bounds.</returns>
-        public IObservable<TransformedBounds?> Track(Visual visual)
-        {
-            return visual.GetObservable(TransformedBoundsProperty);
-        }
-
-        /// <summary>
-        /// Sets the transformed bounds of the visual.
-        /// </summary>
-        /// <param name="visual">The visual.</param>
-        /// <param name="value">The transformed bounds.</param>
-        internal static void SetTransformedBounds(Visual visual, TransformedBounds? value)
-        {
-            visual.SetValue(TransformedBoundsProperty, value);
-        }
-
-        /// <summary>
-        /// Gets the transformed bounds of the visual.
-        /// </summary>
-        /// <param name="visual">The visual.</param>
-        /// <returns>The transformed bounds or null if the visual is not visible.</returns>
-        public static TransformedBounds? GetTransformedBounds(Visual visual) => visual.GetValue(TransformedBoundsProperty);
-    }
-}

+ 5 - 0
src/Avalonia.Visuals/VisualTree/IVisual.cs

@@ -36,6 +36,11 @@ namespace Avalonia.VisualTree
         /// </summary>
         Rect Bounds { get; }
 
+        /// <summary>
+        /// Gets the bounds of the control relative to the window, accounting for rendering transforms.
+        /// </summary>
+        TransformedBounds? TransformedBounds { get; set; }
+
         /// <summary>
         /// Gets a value indicating whether the control should be clipped to its bounds.
         /// </summary>

+ 2 - 2
tests/Avalonia.Visuals.UnitTests/VisualTree/BoundsTrackerTests.cs → tests/Avalonia.Visuals.UnitTests/VisualTree/TransformedBoundsTests.cs

@@ -17,7 +17,7 @@ using Avalonia.Platform;
 
 namespace Avalonia.Visuals.UnitTests.VisualTree
 {
-    public class BoundsTrackerTests
+    public class TransformedBoundsTests
     {
         [Fact]
         public void Should_Track_Bounds()
@@ -46,7 +46,7 @@ namespace Avalonia.Visuals.UnitTests.VisualTree
                 tree.Arrange(new Rect(0, 0, 100, 100));
                 ImmediateRenderer.Render(tree, context);
 
-                var track = target.Track(control);
+                var track = control.GetObservable(Visual.TransformedBoundsProperty);
                 var results = new List<TransformedBounds?>();
                 track.Subscribe(results.Add);