Exemple #1
0
        /// <summary>
        /// Adds an element to the queue.
        /// </summary>
        /// <param name="element">The element to add to the queue.</param>
        public void Enqueue(UIElement element)
        {
            Contract.Require(element, nameof(element));

            var current = element;
            var parent  = element;

            while (current != null)
            {
                invalidate(current);

                parent = VisualTreeHelper.GetParent(current) as UIElement;
                if (parent == null || !bubble)
                {
                    var entry = new Entry(current.LayoutDepth, current);
                    if (queue.ContainsKey(entry))
                        return;

                    queue.Add(entry, current);
                }
                else
                {
                    var entry = new Entry(current.LayoutDepth, current);
                    queue.Remove(entry);
                }

                if (!bubble)
                    break;

                current = parent;
            }
        }
        /// <summary>
        /// Removes the specified element from the queue.
        /// </summary>
        /// <param name="element">The element to remove from the queue.</param>
        public void Remove(UIElement element)
        {
            Contract.Require(element, "element");

            var entry = new Entry(element.LayoutDepth, element);
            queue.Remove(entry);
        }
        /// <summary>
        /// Gets a value indicating whether the specified element is rendered out-of-band.
        /// </summary>
        /// <param name="element">The element to evaluate.</param>
        /// <returns><c>true</c> if the specified element is rendered out-of-band; otherwise, <c>false</c>.</returns>
        public Boolean IsRenderedOutOfBand(UIElement element)
        {
            Contract.Require(element, "element");
            Contract.EnsureNotDisposed(this, Disposed);

            return element.OutOfBandRenderTarget != null;
        }
        /// <summary>
        /// Gets a value indicating whether the specified element's texture is ready to be used.
        /// </summary>
        /// <param name="element">The element to evaluate.</param>
        /// <returns><c>true</c> if the specified element's texture is ready; otherwise, <c>false</c>.</returns>
        public Boolean IsTextureReady(UIElement element)
        {
            Contract.Require(element, "element");
            Contract.EnsureNotDisposed(this, Disposed);

            var rtarget = element.OutOfBandRenderTarget;
            return rtarget != null && rtarget.Value.IsReady;
        }
Exemple #5
0
        /// <summary>
        /// Deactivates the specified command stream's activated link, if it has one.
        /// </summary>
        /// <param name="stream">The command stream to update.</param>
        /// <param name="element">The element that owns the command stream.</param>
        /// <returns><see langword="true"/> if the command stream's link was deactivated; otherwise, <see langword="false"/>.</returns>
        public static Boolean DeactivateTextLink(TextLayoutCommandStream stream, UIElement element)
        {
            Contract.Require(element, nameof(element));

            if (stream == null || element.View == null)
                return false;

            return element.View.Resources.TextRenderer.DeactivateLink(stream);
        }
        /// <summary>
        /// Gets a value indicating whether the specified element is currently being drawn.
        /// </summary>
        /// <param name="element">The element to evaluate.</param>
        /// <returns><c>true</c> if the specified element is being drawn; otherwise, false.</returns>
        public static Boolean IsDrawn(UIElement element)
        {
            Contract.Require(element, "element");

            if (element.Visibility != Visibility.Visible)
                return false;

            if (element is Popup || element is Adorner)
                return true;

            return (element.RenderSize.Width > 0 && element.RenderSize.Height > 0);
        }
Exemple #7
0
        /// <summary>
        /// Activates any link at the current cursor position within the specified command stream.
        /// </summary>
        /// <param name="stream">The command stream to update.</param>
        /// <param name="element">The element that owns the command stream.</param>
        /// <param name="data">The event metadata for the routed event which prompted the link activation.</param>
        /// <returns><see langword="true"/> if the command stream's link was deactivated; otherwise, <see langword="false"/>.</returns>
        public static Boolean ActivateTextLink(TextLayoutCommandStream stream, UIElement element, RoutedEventData data)
        {
            Contract.Require(element, nameof(element));

            if (stream == null || element.View == null || !element.View.Resources.TextRenderer.ActivateLinkAtCursor(stream))
                return false;

            element.Focus();
            element.CaptureMouse();

            data.Handled = true;
            return true;
        }
Exemple #8
0
        /// <summary>
        /// Executes any link at the current cursor position within the specified command stream.
        /// </summary>
        /// <param name="stream">The command stream to update.</param>
        /// <param name="element">The element that owns the command stream.</param>
        /// <param name="data">The event metadata for the routed event which prompted the link execution.</param>
        public static Boolean ExecuteTextLink(TextLayoutCommandStream stream, UIElement element, RoutedEventData data)
        {
            Contract.Require(element, nameof(element));

            if (stream == null || element.View == null)
                return false;

            if (stream.ActiveLinkIndex.HasValue)
                element.ReleaseMouseCapture();

            if (!element.View.Resources.TextRenderer.ExecuteActivatedLink(stream))
                return false;

            data.Handled = true;
            return true;
        }
Exemple #9
0
        /// <summary>
        /// Updates the position of the cursor within the specified command stream.
        /// </summary>
        /// <param name="stream">The command stream to update.</param>
        /// <param name="element">The element that owns the command stream.</param>
        /// <param name="position">The position of the input device.</param>
        public static void UpdateLinkCursor(TextLayoutCommandStream stream, UIElement element, Point2D? position)
        {
            Contract.Require(element, nameof(element));

            if (stream == null || element.View == null)
                return;

            var positionDips = position;
            var positionPixs = positionDips.HasValue ? (Point2)element.View.Display.DipsToPixels(positionDips.Value) : (Point2?)null;

            if (positionDips.HasValue && (element.IsMouseOver || element.IsMouseCaptured))
            {
                element.View.Resources
                    .TextRenderer.UpdateCursor(stream, positionPixs);
            }
            else
            {
                element.View.Resources
                    .TextRenderer.UpdateCursor(stream, null);
            }
        }
        /// <summary>
        /// Gets a value indicating whether the renderer is currently drawing the out-of-band render targets for
        /// the specified element.
        /// </summary>
        /// <param name="element">The element to evaluate.</param>
        /// <returns><see langword="true"/> if the render targets for the specified element are currently being drawn; otherwise, <see langword="false"/>.</returns>
        public Boolean IsDrawingRenderTargetFor(UIElement element)
        {
            Contract.Require(element, nameof(element));

            return element == currentElementDrawingRenderTarget;
        }
        /// <summary>
        /// Resizes the render target to match the specified element.
        /// </summary>
        /// <param name="element">The element for which to resize the render target.</param>
        /// <param name="bounds">The visual bounds of the element in absolute screen coordinates.</param>
        /// <returns><see langword="true"/> if the element was resized; otherwise, <see langword="false"/>.</returns>
        public Boolean ResizeForElement(UIElement element, out RectangleD bounds)
        {
            Contract.Require(element, nameof(element));

            if (element.View == null)
            {
                bounds = RectangleD.Empty;
                return false;
            }

            bounds = element.TransformedVisualBounds;

            var effect = element.Effect;
            if (effect != null)
            {
                effect.ModifyVisualBounds(ref bounds);
            }

            var display = element.View.Display;
            var width   = Math.Max(1, (Int32)Math.Ceiling(display.DipsToPixels(bounds.Width)));
            var height  = Math.Max(1, (Int32)Math.Ceiling(display.DipsToPixels(bounds.Height)));

            if (width == renderTarget.Width && height == renderTarget.Height)
                return false;

            if (width < 1 || height < 1)
            {
                Resize(1, 1);
                bounds = RectangleD.Empty;
            }
            else
            {
                Resize(width, height);
            }

            return true;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Entry"/> structure.
 /// </summary>
 /// <param name="priority">The entry's priority within the queue.</param>
 /// <param name="element">The element pending a layout operation.</param>
 public Entry(Int32 priority, UIElement element)
 {
     this.priority = priority;
     this.element  = element;
 }
Exemple #13
0
        /// <summary>
        /// Gets a value indicating whether the specified element is currently filling space in the layout.
        /// </summary>
        /// <param name="element">The element to evaluate.</param>
        /// <returns><see langword="true"/> if the specified element is filling space; otherwise, <see langword="false"/>.</returns>
        public static Boolean IsSpaceFilling(UIElement element)
        {
            Contract.Require(element, nameof(element));

            return element.Visibility != Visibility.Collapsed;
        }
Exemple #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UvmlObject"/> class.
 /// </summary>
 /// <param name="xml">The XML element that corresponds to this node.</param>
 /// <param name="instance">The <see cref="UIElement"/> instance that was created for this object.</param>
 /// <param name="instanceFlags">The set of <see cref="UIElementInstanceFlags"/> to attach to this object's instance.</param>
 public UvmlObject(XElement xml, UIElement instance, UIElementInstanceFlags instanceFlags)
 {
     this.xml = xml;
     this.instance  = instance;
     this.instanceFlags = instanceFlags;
 }
        /// <summary>
        /// Sets the visibility of the specified element.
        /// </summary>
        private void SetElementVisibility(UIElement element, Boolean visible)
        {
            if (element == null)
                return;

            element.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ExampleBoxesAdorner"/> class.
 /// </summary>
 /// <param name="adornedElement">The element being adorned.</param>
 public ExampleBoxesAdorner(UIElement adornedElement)
     : base(adornedElement)
 {
 }
        /// <summary>
        /// Gets a value indicating whether the specified element has become disconnected from the view's layout root through the visual tree.
        /// </summary>
        /// <param name="element">The element to evaluate.</param>
        /// <returns><see langword="true"/> if the specified element is visually disconnected; otherwise, <see langword="false"/>.</returns>
        private static Boolean IsVisuallyDisconnectedFromRoot(UIElement element)
        {
            var current = element;

            while (current != null)
            {
                if (current == element.View.LayoutRoot)
                    return false;

                if (current is PopupRoot)
                {
                    var popup = current.Parent as Popup;
                    if (popup == null || !popup.IsOpen)
                        return true;

                    current = popup;
                }
                else
                {
                    current = VisualTreeHelper.GetParent(current) as UIElement;
                }
            }

            return true;
        }
        /// <summary>
        /// Unregisters an element from the out-of-band renderer.
        /// </summary>
        /// <param name="element">The element to unregister.</param>
        public void Unregister(UIElement element)
        {
            Contract.Require(element, nameof(element));
            Contract.EnsureNotDisposed(this, Disposed);

            foreach (var registeredElement in registeredElements)
            {
                var weakRefTarget = (UIElement)registeredElement.Target;
                if (weakRefTarget != element)
                    continue;

                for (UpfPool<OutOfBandRenderTarget>.PooledObject current = element.OutOfBandRenderTarget, next = null; current != null; current = next)
                {
                    next = current.Value.NextInternal;
                    current.Value.Resize(1, 1);
                    current.Value.NextInternal = null;
                    renderTargetPool.Release(current);
                }

                registeredElements.Remove(registeredElement);
                element.OutOfBandRenderTarget = null;

                registeredElement.Target = null;
                WeakReferencePool.Instance.Release(registeredElement);

                break;
            }
        }
        /// <summary>
        /// Registers an element with the out-of-band renderer.
        /// </summary>
        /// <param name="element">The element to register.</param>
        /// <param name="additional">The number of additional render targets to reserve.</param>
        public void Register(UIElement element, Int32 additional)
        {
            Contract.Require(element, nameof(element));
            Contract.EnsureRange(additional >= 0, nameof(additional));
            Contract.EnsureNotDisposed(this, Disposed);

            if (IsRenderedOutOfBand(element))
                return;

            InitializePools();

            var weakRef = WeakReferencePool.Instance.Retrieve();
            weakRef.Target = element;

            var target = renderTargetPool.Retrieve(element);
            var targetObject = target.Value;

            var bounds = default(RectangleD);
            targetObject.ResizeForElement(element, out bounds);

            var currentTarget = targetObject;
            currentTarget.NextInternal = null;

            for (int i = 0; i < additional; i++)
            {
                var additionalTarget = renderTargetPool.Retrieve(element);
                var additionalTargetObject = additionalTarget.Value;

                additionalTargetObject.NextInternal = null;
                additionalTargetObject.Resize(targetObject.Width, targetObject.Height);

                currentTarget.NextInternal = additionalTarget;
                currentTarget = additionalTarget.Value;
            }

            registeredElements.Add(weakRef);
            element.OutOfBandRenderTarget = target;
        }
        /// <summary>
        /// Draws out-of-band elements to their render buffers.
        /// </summary>
        /// <param name="time">Time elapsed since the last call to <see cref="UltravioletContext.Draw(UltravioletTime)"/>.</param>
        public void DrawRenderTargets(UltravioletTime time)
        {
            Contract.EnsureNotDisposed(this, Disposed);

            if (registeredElements.Count == 0)
                return;

            var graphics = Ultraviolet.GetGraphics();

            var upf = Ultraviolet.GetUI().GetPresentationFoundation();
            upf.PerformanceStats.BeginDraw();

            try
            {
                isDrawingRenderTargets = true;

                foreach (var registeredElement in registeredElements)
                {
                    var element = (UIElement)registeredElement.Target;
                    if (element != null && element.OutOfBandRenderTarget != null)
                    {
                        element.OutOfBandRenderTarget.Value.IsReady = false;
                    }

                    if (element.View != null && !element.View.LayoutRoot.IsLoaded)
                        viewsNeedingLoading.Add(element.View);
                }

                foreach (var view in viewsNeedingLoading)
                {
                    view.EnsureIsLoaded();
                }
                viewsNeedingLoading.Clear();

                registeredElements.Sort(uiElementComparer);
                foreach (var registeredElement in registeredElements)
                {
                    var element = (UIElement)registeredElement.Target;
                    if (element == null)
                    {
                        deadReferences.Add(registeredElement);
                        continue;
                    }

                    if (element.View == null)
                        continue;

                    var bounds = default(RectangleD);
                    var effect = element.Effect;

                    var rtarget = element.OutOfBandRenderTarget.Value;
                    if (rtarget.ResizeForElement(element, out bounds))
                    {
                        for (var current = rtarget.Next; current != null; current = current.Next)
                            current.Resize(rtarget.Width, rtarget.Height);
                    }

                    graphics.SetRenderTarget(rtarget.RenderTarget);
                    graphics.Clear(Color.Transparent);

                    var popup = element as Popup;
                    if (popup != null)
                    {
                        if (!popup.IsOpen)
                            continue;

                        element = popup.Root;
                    }

                    if (!element.TransformedVisualBounds.IsEmpty && !IsVisuallyDisconnectedFromRoot(element))
                    {
                        drawingContext.Reset(element.View.Display);

                        var visualParent = VisualTreeHelper.GetParent(element) as UIElement;
                        var visualTransformOfParent = (visualParent == null) ? popup.PopupTransformToView : visualParent.GetVisualTransformMatrix();
                        var visualTransformOfElement = element.GetVisualTransformMatrix(ref visualTransformOfParent);

                        rtarget.VisualTransform = visualTransformOfElement;
                        rtarget.VisualBounds = bounds;

                        currentElementDrawingRenderTarget = element;

                        element.DrawToRenderTarget(time, drawingContext, rtarget.RenderTarget,
                            (popup != null) ? popup.PopupTransformToViewInDevicePixels : visualTransformOfParent);

                        if (rtarget.Next != null)
                        {
                            if (effect != null)
                            {
                                effect.DrawRenderTargets(drawingContext, element, rtarget);
                            }
                        }

                        currentElementDrawingRenderTarget = null;

                        rtarget.IsReady = true;
                    }
                }

                foreach (var deadReference in deadReferences)
                    registeredElements.Remove(deadReference);
            }
            finally
            {
                isDrawingRenderTargets = false;
                currentElementDrawingRenderTarget = null;
            }
            deadReferences.Clear();

            graphics.SetRenderTarget(null);
            graphics.Clear(Color.Transparent);

            upf.PerformanceStats.EndDraw();
        }
        /// <summary>
        /// Gets the render target that represents the specified element.
        /// </summary>
        /// <param name="element">The element for which to retrieve a render target.</param>
        /// <returns>The render target associated with the specified out-of-band element, or <c>null if the element is
        /// not registered for out-of-band rendering.</c></returns>
        public OutOfBandRenderTarget GetElementRenderTarget(UIElement element)
        {
            Contract.Require(element, nameof(element));
            Contract.EnsureNotDisposed(this, Disposed);

            var pooledObject = element.OutOfBandRenderTarget;
            return (pooledObject == null) ? null : pooledObject.Value;
        }