Exemplo n.º 1
0
        /// <summary>
        /// Updates or creates a sublayer to render a border-like shape.
        /// </summary>
        /// <param name="owner">The parent layer to apply the shape</param>
        /// <param name="area">The rendering area</param>
        /// <param name="background">The background brush</param>
        /// <param name="borderThickness">The border thickness</param>
        /// <param name="borderBrush">The border brush</param>
        /// <param name="cornerRadius">The corner radius</param>
        /// <param name="backgroundImage">The background image in case of a ImageBrush background</param>
        public void UpdateLayer(
            FrameworkElement owner,
            Brush background,
            Thickness borderThickness,
            Brush borderBrush,
            CornerRadius cornerRadius,
            object backgroundImage
            )
        {
            // Bounds is captured to avoid calling twice calls below.
            var area = new Rect(0, 0, owner.ActualWidth, owner.ActualHeight);

            var newState            = new LayoutState(area, background, borderThickness, borderBrush, cornerRadius, backgroundImage);
            var previousLayoutState = _currentState;

            if (!newState.Equals(previousLayoutState))
            {
                if (
                    background != null ||
                    cornerRadius != CornerRadius.None ||
                    (borderThickness != Thickness.Empty && borderBrush != null)
                    )
                {
                    _layerDisposable.Disposable = null;
                    _layerDisposable.Disposable = InnerCreateLayer(owner, newState);
                }
                else
                {
                    _layerDisposable.Disposable = null;
                }

                _currentState = newState;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Updates or creates a sublayer to render a border-like shape.
        /// </summary>
        /// <param name="view">The view to which we should add the layers</param>
        /// <param name="background">The background brush of the border</param>
        /// <param name="borderThickness">The border thickness</param>
        /// <param name="borderBrush">The border brush</param>
        /// <param name="cornerRadius">The corner radius</param>
        /// <param name="padding">The padding to apply on the content</param>
        public void UpdateLayer(
            FrameworkElement view,
            Brush background,
            Thickness borderThickness,
            Brush borderBrush,
            CornerRadius cornerRadius,
            Thickness padding,
            bool willUpdateMeasures = false
            )
        {
            // This is required because android Height and Width are hidden by Control.
            var baseView = view as View;

            var logicalDrawArea = view.LayoutSlot;

            // Set origin to 0, because drawArea should be in the coordinates of the view itself
            logicalDrawArea.X = 0;
            logicalDrawArea.Y = 0;
            var drawArea            = logicalDrawArea.LogicalToPhysicalPixels();
            var newState            = new LayoutState(drawArea, background, borderThickness, borderBrush, cornerRadius, padding);
            var previousLayoutState = _currentState;

            if (!newState.Equals(previousLayoutState))
            {
                bool imageHasChanged      = newState.BackgroundImageSource != previousLayoutState?.BackgroundImageSource;
                bool shouldDisposeEagerly = imageHasChanged || newState.BackgroundImageSource == null;
                if (shouldDisposeEagerly)
                {
                    // Clear previous value anyway in order to make sure the previous values are unset before the new ones.
                    // This prevents the case where a second update would set a new background and then set the background to null when disposing the previous.
                    _layerDisposable.Disposable = null;
                }

                Action onImageSet = null;
                var    disposable = InnerCreateLayers(view, drawArea, background, borderThickness, borderBrush, cornerRadius, () => onImageSet?.Invoke());

                // Most of the time we immediately dispose the previous layer. In the case where we're using an ImageBrush,
                // and the backing image hasn't changed, we dispose the previous layer at the moment the new background is applied,
                // to prevent a visible flicker.
                if (shouldDisposeEagerly)
                {
                    _layerDisposable.Disposable = disposable;
                }
                else
                {
                    onImageSet = () => _layerDisposable.Disposable = disposable;
                }

                if (willUpdateMeasures)
                {
                    view.RequestLayout();
                }
                else
                {
                    view.Invalidate();
                }

                _currentState = newState;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Updates or creates a sublayer to render a border-like shape.
        /// </summary>
        /// <param name="owner">The parent layer to apply the shape</param>
        /// <param name="area">The rendering area</param>
        /// <param name="background">The background brush</param>
        /// <param name="borderThickness">The border thickness</param>
        /// <param name="borderBrush">The border brush</param>
        /// <param name="cornerRadius">The corner radius</param>
        /// <param name="backgroundImage">The background image in case of a ImageBrush background</param>
        public void UpdateLayer(
            UIView owner,
            Brush background,
            Thickness borderThickness,
            Brush borderBrush,
            CornerRadius cornerRadius,
            UIImage backgroundImage
            )
        {
            // Frame is captured to avoid calling twice calls below.
            var frame = owner.Frame;
            var area  = new CGRect(0, 0, frame.Width, frame.Height);

            var newState            = new LayoutState(area, background, borderThickness, borderBrush, cornerRadius, backgroundImage);
            var previousLayoutState = _currentState;

            if (!newState.Equals(previousLayoutState))
            {
                if (
                    background != null ||
                    (borderThickness != Thickness.Empty && borderBrush != null)
                    )
                {
                    _layerDisposable.Disposable = null;
                    _layerDisposable.Disposable = InnerCreateLayer(owner.Layer, area, background, borderThickness, borderBrush, cornerRadius);
                }
                else
                {
                    _layerDisposable.Disposable = null;
                }

                _currentState = newState;
            }
        }
        /// <summary>
        /// Updates or creates a sublayer to render a border-like shape.
        /// </summary>
        /// <param name="owner">The parent layer to apply the shape</param>
        /// <param name="area">The rendering area</param>
        /// <param name="background">The background brush</param>
        /// <param name="borderThickness">The border thickness</param>
        /// <param name="borderBrush">The border brush</param>
        /// <param name="cornerRadius">The corner radius</param>
        /// <param name="backgroundImage">The background image in case of a ImageBrush background</param>
        /// <returns>An updated BoundsPath if the layer has been created or updated; null if there is no change.</returns>
        public CGPath UpdateLayer(
            _View owner,
            Brush background,
            BackgroundSizing backgroundSizing,
            Thickness borderThickness,
            Brush borderBrush,
            CornerRadius cornerRadius,
            _Image backgroundImage)
        {
            // Bounds is captured to avoid calling twice calls below.
            var bounds = owner.Bounds;
            var area   = new CGRect(0, 0, bounds.Width, bounds.Height);

            var newState            = new LayoutState(area, background, backgroundSizing, borderThickness, borderBrush, cornerRadius, backgroundImage);
            var previousLayoutState = _currentState;

            if (!newState.Equals(previousLayoutState))
            {
#if __MACOS__
                owner.WantsLayer = true;
#endif

                _layerDisposable.Disposable = null;
                _layerDisposable.Disposable = InnerCreateLayer(owner as UIElement, owner.Layer, newState);

                _currentState = newState;
            }

            return(newState.BoundsPath);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Updates or creates a sublayer to render a border-like shape.
        /// </summary>
        /// <param name="view">The view to which we should add the layers</param>
        /// <param name="background">The background brush of the border</param>
        /// <param name="borderThickness">The border thickness</param>
        /// <param name="borderBrush">The border brush</param>
        /// <param name="cornerRadius">The corner radius</param>
        /// <param name="padding">The padding to apply on the content</param>
        public void UpdateLayers(
            FrameworkElement view,
            Brush background,
            Thickness borderThickness,
            Brush borderBrush,
            CornerRadius cornerRadius,
            Thickness padding
            )
        {
            // This is required because android Height and Width are hidden by Control.
            var baseView = view as View;

            Size targetSize          = new Size(baseView.Width, baseView.Height);
            var  drawArea            = new Windows.Foundation.Rect(0, 0, targetSize.Width, targetSize.Height);
            var  newState            = new LayoutState(drawArea, background, borderThickness, borderBrush, cornerRadius, padding);
            var  previousLayoutState = _currentState;

            if (!newState.Equals(previousLayoutState))
            {
                bool imageHasChanged      = newState.BackgroundImageSource != previousLayoutState?.BackgroundImageSource;
                bool shouldDisposeEagerly = imageHasChanged || newState.BackgroundImageSource == null;
                if (shouldDisposeEagerly)
                {
                    // Clear previous value anyway in order to make sure the previous values are unset before the new ones.
                    // This prevents the case where a second update would set a new background and then set the background to null when disposing the previous.
                    _layerDisposable.Disposable = null;
                }

                if (
                    background != null ||
                    (borderThickness != Thickness.Empty && borderBrush != null)
                    )
                {
                    Action onImageSet = null;
                    var    disposable = InnerCreateLayers(view, drawArea, background, borderThickness, borderBrush, cornerRadius, () => onImageSet?.Invoke());

                    // Most of the time we immediately dispose the previous layer. In the case where we're using an ImageBrush,
                    // and the backing image hasn't changed, we dispose the previous layer at the moment the new background is applied,
                    // to prevent a visible flicker.
                    if (shouldDisposeEagerly)
                    {
                        _layerDisposable.Disposable = disposable;
                    }
                    else
                    {
                        onImageSet = () => _layerDisposable.Disposable = disposable;
                    }
                }

                view.Invalidate();

                _currentState = newState;
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Updates or creates a sublayer to render a border-like shape.
        /// </summary>
        /// <param name="owner">The parent layer to apply the shape</param>
        /// <param name="area">The rendering area</param>
        /// <param name="background">The background brush</param>
        /// <param name="borderThickness">The border thickness</param>
        /// <param name="borderBrush">The border brush</param>
        /// <param name="cornerRadius">The corner radius</param>
        /// <param name="backgroundImage">The background image in case of a ImageBrush background</param>
        public void UpdateLayer(
            _View owner,
            Brush background,
            Thickness borderThickness,
            Brush borderBrush,
            CornerRadius cornerRadius,
            _Image backgroundImage
            )
        {
            // Bounds is captured to avoid calling twice calls below.
            var bounds = owner.Bounds;
            var area   = new CGRect(0, 0, bounds.Width, bounds.Height);

            var newState            = new LayoutState(area, background, borderThickness, borderBrush, cornerRadius, backgroundImage);
            var previousLayoutState = _currentState;

            if (!newState.Equals(previousLayoutState))
            {
                if (
                    background != null ||
                    (borderThickness != Thickness.Empty && borderBrush != null)
                    )
                {
#if __MACOS__
                    owner.WantsLayer = true;
#endif

                    _layerDisposable.Disposable = null;
                    _layerDisposable.Disposable = InnerCreateLayer(owner.Layer, area, background, borderThickness, borderBrush, cornerRadius);
                }
                else
                {
                    _layerDisposable.Disposable = null;
                }

                _currentState = newState;
            }
        }