Example #1
0
        public void Should_Track_Bounds()
        {
            var target  = new BoundsTracker();
            var control = default(Rectangle);
            var tree    = new Decorator
            {
                Padding = new Thickness(10),
                Child   = new Decorator
                {
                    Padding = new Thickness(5),
                    Child   = control = new Rectangle
                    {
                        Width  = 15,
                        Height = 15,
                    },
                }
            };

            tree.Measure(Size.Infinity);
            tree.Arrange(new Rect(0, 0, 100, 100));

            var track   = target.Track(control, tree);
            var results = new List <TransformedBounds>();

            track.Subscribe(results.Add);

            Assert.Equal(new Rect(15, 15, 15, 15), results.Last().Bounds);

            tree.Padding = new Thickness(15);
            tree.Measure(Size.Infinity);
            tree.Arrange(new Rect(0, 0, 100, 100), true);

            Assert.Equal(new Rect(20, 20, 15, 15), results.Last().Bounds);
        }
Example #2
0
 private static void ClearTransformedBounds(IVisual visual)
 {
     foreach (var e in visual.GetSelfAndVisualDescendents())
     {
         BoundsTracker.SetTransformedBounds((Visual)visual, null);
     }
 }
Example #3
0
        static IEnumerable <IVisual> HitTest(
            IVisual visual,
            Point p,
            Func <IVisual, bool> filter)
        {
            Contract.Requires <ArgumentNullException>(visual != null);

            if (filter?.Invoke(visual) != false)
            {
                bool containsPoint = BoundsTracker.GetTransformedBounds((Visual)visual)?.Contains(p) == true;

                if ((containsPoint || !visual.ClipToBounds) && visual.VisualChildren.Count > 0)
                {
                    foreach (var child in visual.VisualChildren.SortByZIndex())
                    {
                        foreach (var result in HitTest(child, p, filter))
                        {
                            yield return(result);
                        }
                    }
                }

                if (containsPoint)
                {
                    yield return(visual);
                }
            }
        }
Example #4
0
        private static void Deindex(Scene scene, VisualNode node)
        {
            scene.Remove(node);
            node.SubTreeUpdated = true;

            scene.Layers[node.LayerRoot].Dirty.Add(node.Bounds);

            if (node.Visual is Visual v)
            {
                BoundsTracker.SetTransformedBounds(v, null);
            }

            foreach (VisualNode child in node.Children)
            {
                var geometry = child as IDrawOperation;

                if (child is VisualNode visual)
                {
                    Deindex(scene, visual);
                }
            }

            if (node.LayerRoot == node.Visual && node.Visual != scene.Root.Visual)
            {
                scene.Layers.Remove(node.LayerRoot);
            }
        }
Example #5
0
        public void Should_Track_Bounds()
        {
            using (UnitTestApplication.Start(TestServices.StyledWindow))
            {
                var target  = new BoundsTracker();
                var control = default(Rectangle);
                var tree    = new Decorator
                {
                    Padding = new Thickness(10),
                    Child   = new Decorator
                    {
                        Padding = new Thickness(5),
                        Child   = control = new Rectangle
                        {
                            Width  = 15,
                            Height = 15,
                        },
                    }
                };

                var context = new DrawingContext(Mock.Of <IDrawingContextImpl>());

                tree.Measure(Size.Infinity);
                tree.Arrange(new Rect(0, 0, 100, 100));
                ImmediateRenderer.Render(tree, context);

                var track   = target.Track(control);
                var results = new List <TransformedBounds?>();
                track.Subscribe(results.Add);

                Assert.Equal(new Rect(0, 0, 15, 15), results[0].Value.Bounds);
                Assert.Equal(Matrix.CreateTranslation(42, 42), results[0].Value.Transform);
            }
        }
Example #6
0
 private void rdoWindow_MouseUp(object sender, MouseEventArgs e)
 {
     if (this.windowFinder.IsFinding)
     {
         this.Cursor = Cursors.Default;
         IntPtr hWnd = this.windowFinder.EndFind();
         if (e.Button == MouseButtons.Left)
         {
             if (hWnd != IntPtr.Zero)
             {
                 this.BoundsTracker = new BoundsTracker(hWnd);
             }
             else
             {
                 this.BoundsTracker     = this.prevBoundsTracker;
                 this.prevBoundsTracker = null;
             }
         }
         else
         {
             this.BoundsTracker     = this.prevBoundsTracker;
             this.prevBoundsTracker = null;
         }
     }
 }
Example #7
0
        /// <summary>
        /// Returns the active input elements at a point on an <see cref="IInputElement"/>.
        /// </summary>
        /// <param name="element">The element to test.</param>
        /// <param name="p">The point on <paramref name="element"/>.</param>
        /// <returns>
        /// The active input elements found at the point, ordered topmost first.
        /// </returns>
        public static IEnumerable <IInputElement> GetInputElementsAt(this IInputElement element, Point p)
        {
            Contract.Requires <ArgumentNullException>(element != null);

            if (element.IsVisible &&
                element.IsHitTestVisible &&
                element.IsEnabledCore)
            {
                bool containsPoint = BoundsTracker.GetTransformedBounds((Visual)element).Contains(p);

                if ((containsPoint || !element.ClipToBounds) && element.VisualChildren.Any())
                {
                    foreach (var child in ZSort(element.VisualChildren.OfType <IInputElement>()))
                    {
                        foreach (var result in child.GetInputElementsAt(p))
                        {
                            yield return(result);
                        }
                    }
                }

                if (containsPoint)
                {
                    yield return(element);
                }
            }
        }
Example #8
0
        /// <summary>
        /// Renders the specified visual.
        /// </summary>
        /// <param name="visual">The visual to render.</param>
        /// <param name="context">The drawing context.</param>
        /// <param name="clipRect">
        /// The current clip rect, in coordinates relative to <paramref name="visual"/>.
        /// </param>
        private static void Render(this DrawingContext context, IVisual visual, Rect clipRect)
        {
            var opacity      = visual.Opacity;
            var clipToBounds = visual.ClipToBounds;
            var bounds       = new Rect(visual.Bounds.Size);

            if (visual.IsVisible && opacity > 0)
            {
                var m = Matrix.CreateTranslation(visual.Bounds.Position);

                var renderTransform = Matrix.Identity;

                if (visual.RenderTransform != null)
                {
                    var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
                    var offset = Matrix.CreateTranslation(origin);
                    renderTransform = (-offset) * visual.RenderTransform.Value * (offset);
                }

                m = renderTransform * m;

                if (clipToBounds)
                {
                    clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size));
                }

                using (context.PushPostTransform(m))
                    using (context.PushOpacity(opacity))
                        using (clipToBounds ? context.PushClip(bounds) : default(DrawingContext.PushedState))
                            using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default(DrawingContext.PushedState))
                                using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default(DrawingContext.PushedState))
                                    using (context.PushTransformContainer())
                                    {
                                        visual.Render(context);
                                        var transformed =
                                            new TransformedBounds(bounds, new Rect(), context.CurrentContainerTransform);
                                        if (visual is Visual)
                                        {
                                            BoundsTracker.SetTransformedBounds((Visual)visual, transformed);
                                        }

                                        var lst = GetSortedVisualList(visual.VisualChildren);

                                        foreach (var child in lst)
                                        {
                                            var childBounds = GetTransformedBounds(child);

                                            if (!child.ClipToBounds || clipRect.Intersects(childBounds))
                                            {
                                                var childClipRect = clipRect.Translate(-childBounds.Position);
                                                context.Render(child, childClipRect);
                                            }
                                        }

                                        ReturnListToPool(lst);
                                    }
            }
        }
Example #9
0
 private void rdoWindow_MouseDown(object sender, MouseEventArgs e)
 {
     if (!this.windowFinder.IsFinding && e.Button == MouseButtons.Left)
     {
         this.windowFinder.BeginFind();
         // Keep current tracker in case of cancellation.
         this.prevBoundsTracker = this.boundsTracker;
         // Update radio buttons state
         this.BoundsTracker = new BoundsTracker(IntPtr.Zero);
         // Change cursor
         this.Cursor = Cursors.Cross;
     }
 }
Example #10
0
        /// <summary>
        ///     Initialize host.
        /// </summary>
        private void Initialize()
        {
            this.Built += (sender, e) =>
            {
                var root = VisualRoot as TopLevel;
                if (root == null)
                {
                    throw new NotSupportedException("The visual root is not a toplevel.");
                }

                // Track change in bounds.
                var disposable = new BoundsTracker()
                                 .Track(this)
                                 .Subscribe(UpdateLayout);
                _disposables.Add(disposable);
            };
        }
Example #11
0
        private static void Update(DrawingContext context, Scene scene, VisualNode node, Rect clip, bool forceRecurse)
        {
            var visual       = node.Visual;
            var opacity      = visual.Opacity;
            var clipToBounds = visual.ClipToBounds;
            var bounds       = new Rect(visual.Bounds.Size);
            var contextImpl  = (DeferredDrawingContextImpl)context.PlatformImpl;

            contextImpl.Layers.Find(node.LayerRoot)?.Dirty.Add(node.Bounds);

            if (visual.IsVisible)
            {
                var m = Matrix.CreateTranslation(visual.Bounds.Position);

                var renderTransform = Matrix.Identity;

                if (visual.RenderTransform != null)
                {
                    var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
                    var offset = Matrix.CreateTranslation(origin);
                    renderTransform = (-offset) * visual.RenderTransform.Value * (offset);
                }

                m = renderTransform * m;

                using (contextImpl.BeginUpdate(node))
                    using (context.PushPostTransform(m))
                        using (context.PushTransformContainer())
                        {
                            var clipBounds = bounds.TransformToAABB(contextImpl.Transform).Intersect(clip);

                            forceRecurse = forceRecurse ||
                                           node.Transform != contextImpl.Transform ||
                                           node.ClipBounds != clipBounds;

                            node.Transform    = contextImpl.Transform;
                            node.ClipBounds   = clipBounds;
                            node.ClipToBounds = clipToBounds;
                            node.GeometryClip = visual.Clip?.PlatformImpl;
                            node.Opacity      = opacity;

                            // TODO: Check equality between node.OpacityMask and visual.OpacityMask before assigning.
                            node.OpacityMask = visual.OpacityMask?.ToImmutable();

                            if (ShouldStartLayer(visual))
                            {
                                if (node.LayerRoot != visual)
                                {
                                    MakeLayer(scene, node);
                                }
                                else
                                {
                                    UpdateLayer(node, scene.Layers[node.LayerRoot]);
                                }
                            }
                            else if (node.LayerRoot == node.Visual && node.Parent != null)
                            {
                                ClearLayer(scene, node);
                            }

                            if (node.ClipToBounds)
                            {
                                clip = clip.Intersect(node.ClipBounds);
                            }

                            try
                            {
                                visual.Render(context);
                            }
                            catch { }

                            if (visual is Visual)
                            {
                                var transformed = new TransformedBounds(new Rect(visual.Bounds.Size), clip, node.Transform);
                                BoundsTracker.SetTransformedBounds((Visual)visual, transformed);
                            }

                            if (forceRecurse)
                            {
                                foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
                                {
                                    var childNode = scene.FindNode(child) ?? CreateNode(scene, child, node);
                                    Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
                                }

                                node.SubTreeUpdated = true;
                                contextImpl.TrimChildren();
                            }
                        }
            }
        }
Example #12
0
        private void Render(DrawingContext context, IVisual visual, Rect clipRect)
        {
            var opacity      = visual.Opacity;
            var clipToBounds = visual.ClipToBounds;
            var bounds       = new Rect(visual.Bounds.Size);

            if (visual.IsVisible && opacity > 0)
            {
                var m = Matrix.CreateTranslation(visual.Bounds.Position);

                var renderTransform = Matrix.Identity;

                if (visual.RenderTransform != null)
                {
                    var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
                    var offset = Matrix.CreateTranslation(origin);
                    renderTransform = (-offset) * visual.RenderTransform.Value * (offset);
                }

                m = renderTransform * m;

                if (clipToBounds)
                {
                    clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size));
                }

                using (context.PushPostTransform(m))
                    using (context.PushOpacity(opacity))
                        using (clipToBounds ? context.PushClip(bounds) : default(DrawingContext.PushedState))
                            using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default(DrawingContext.PushedState))
                                using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default(DrawingContext.PushedState))
                                    using (context.PushTransformContainer())
                                    {
                                        visual.Render(context);

#pragma warning disable 0618
                                        var transformed =
                                            new TransformedBounds(bounds, new Rect(), context.CurrentContainerTransform);
#pragma warning restore 0618

                                        if (visual is Visual)
                                        {
                                            BoundsTracker.SetTransformedBounds((Visual)visual, transformed);
                                        }

                                        foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
                                        {
                                            var childBounds = GetTransformedBounds(child);

                                            if (!child.ClipToBounds || clipRect.Intersects(childBounds))
                                            {
                                                var childClipRect = clipRect.Translate(-childBounds.Position);
                                                Render(context, child, childClipRect);
                                            }
                                            else
                                            {
                                                ClearTransformedBounds(child);
                                            }
                                        }
                                    }
            }

            if (!visual.IsVisible)
            {
                ClearTransformedBounds(visual);
            }
        }
Example #13
0
 /// <summary>
 /// Determines whether the specified element is currently visible to the user.
 /// </summary>
 /// <param name="element">The element.</param>
 /// <returns><c>true</c> if if the specified element is currently visible to the user; otherwise, <c>false</c>.</returns>
 private static bool IsUserVisible(Control element)
 {
     return(element.IsEffectivelyVisible && BoundsTracker.GetTransformedBounds(element).HasValue);
 }