Exemplo n.º 1
0
        /// <summary>
        /// Arrange a sequence of elements in a single line.
        /// </summary>
        /// <param name="lineStart">
        /// Index of the first element in the sequence to arrange.
        /// </param>
        /// <param name="lineEnd">
        /// Index of the last element in the sequence to arrange.
        /// </param>
        /// <param name="directDelta">
        /// Optional fixed growth in the primary direction.
        /// </param>
        /// <param name="indirectOffset">
        /// Offset of the line in the indirect direction.
        /// </param>
        /// <param name="indirectGrowth">
        /// Shared indirect growth of the elements on this line.
        /// </param>
        private void ArrangeLine(View[] children, int lineStart, int lineEnd, double?directDelta, double indirectOffset, double indirectGrowth)
        {
            double directOffset = 0.0f;

            Orientation o            = Orientation;
            bool        isHorizontal = o == Orientation.Horizontal;

            for (int index = lineStart; index < lineEnd; index++)
            {
                // Get the size of the element
                View element = children[index];

                var desiredSize = GetElementDesiredSize(element);

                OrientedSize elementSize = new OrientedSize(o, desiredSize.Width, desiredSize.Height);

                // Determine if we should use the element's desired size or the
                // fixed item width or height
                double directGrowth = directDelta != null ?
                                      directDelta.Value :
                                      elementSize.Direct;

                // Arrange the element
                Foundation.Rect bounds = isHorizontal ?
                                         new Foundation.Rect(directOffset, indirectOffset, directGrowth, indirectGrowth) :
                                         new Foundation.Rect(indirectOffset, directOffset, indirectGrowth, directGrowth);

                ArrangeElement(element, bounds);

                directOffset += directGrowth;
            }
        }
Exemplo n.º 2
0
        internal void SetCoreBounds(UIKit.UIWindow keyWindow, Foundation.Rect windowBounds)
        {
            var statusBarHeight = UIApplication.SharedApplication.StatusBarFrame.Size.Height;

            UIEdgeInsets inset = new UIEdgeInsets(statusBarHeight, 0, 0, 0);

            // Not respecting its own documentation. https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
            // iOS returns all zeros for SafeAreaInsets on non-iPhoneX phones. (ignoring nav bars or status bars)
            // For that reason, we will set the window's visible bounds to the SafeAreaInsets only for iPhones with notches,
            // other phones will have insets that consider the status bar
            if (UseSafeAreaInsets)
            {
                if (keyWindow.SafeAreaInsets != UIEdgeInsets.Zero)                 // if we have a notch
                {
                    inset = keyWindow.SafeAreaInsets;
                }
            }

            VisibleBounds = new Foundation.Rect(
                x: windowBounds.Left + inset.Left,
                y: windowBounds.Top + inset.Top,
                width: windowBounds.Width - inset.Right - inset.Left,
                height: windowBounds.Height - inset.Top - inset.Bottom
                );

            if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
            {
                this.Log().Debug($"Updated visible bounds {VisibleBounds}, SafeAreaInsets: {inset}");
            }

            VisibleBoundsChanged?.Invoke(this, null);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Arranges the children knowing the grid is 1x1
        /// </summary>
        private void ArrangeSuperpositionPanel(Size finalSize, Column column, Row row)
        {
            if (column.Width.IsPixelSize)
            {
                finalSize.Width = column.Width.PixelSize.Value;
            }
            if (row.Height.IsPixelSize)
            {
                finalSize.Height = row.Height.PixelSize.Value;
            }

            var isMeasureRequired = column.Width.IsAuto || row.Height.IsAuto;

            if (isMeasureRequired)
            {
                finalSize = MeasureChildren(finalSize, column.Width.IsAuto, row.Height.IsAuto);
            }

            var offset = GetChildrenOffset();

            foreach (var child in Children)
            {
                var childFrame = new Foundation.Rect(
                    offset.X,
                    offset.Y,
                    finalSize.Width,
                    finalSize.Height
                    );
                ArrangeElement(child, childFrame);
            }
        }
Exemplo n.º 4
0
        internal void SetVisibleBounds(UIKit.UIWindow keyWindow, Foundation.Rect windowBounds)
        {
            var inset = UseSafeAreaInsets
                                        ? keyWindow.SafeAreaInsets
                                        : UIEdgeInsets.Zero;

            // Not respecting its own documentation. https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
            // iOS returns all zeros for SafeAreaInsets on non-iPhones and iOS11. (ignoring nav bars or status bars)
            // So we need to update the top inset depending of the status bar visibilty on other devices
            var statusBarHeight = UIApplication.SharedApplication.StatusBarHidden
                                        ? 0
                                        : UIApplication.SharedApplication.StatusBarFrame.Size.Height;

            inset.Top = (nfloat)Math.Max(inset.Top, statusBarHeight);

            var newVisibleBounds = new Foundation.Rect(
                x: windowBounds.Left + inset.Left,
                y: windowBounds.Top + inset.Top,
                width: windowBounds.Width - inset.Right - inset.Left,
                height: windowBounds.Height - inset.Top - inset.Bottom
                );

            if (VisibleBounds != newVisibleBounds)
            {
                VisibleBounds = newVisibleBounds;

                if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                {
                    this.Log().Debug($"Updated visible bounds {VisibleBounds}, SafeAreaInsets: {inset}");
                }

                VisibleBoundsChanged?.Invoke(this, null);
            }
        }
Exemplo n.º 5
0
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            arrangeSize.Width  -= GetHorizontalOffset();
            arrangeSize.Height -= GetVerticalOffset();

            var childRectangle = new Foundation.Rect(BorderThickness.Left + Padding.Left, BorderThickness.Top + Padding.Top, arrangeSize.Width, arrangeSize.Height);


            var isHorizontal      = Orientation == Windows.UI.Xaml.Controls.Orientation.Horizontal;
            var previousChildSize = 0.0;

            this.Log().Debug($"StackPanel/{Name}: Arranging {Children.Count} children.");

            // Shadow variables for evaluation performance
            var spacing = Spacing;
            var count   = Children.Count;

            for (int i = 0; i < count; i++)
            {
                var view             = Children[i];
                var desiredChildSize = GetElementDesiredSize(view);
                var addSpacing       = i != 0;

                if (isHorizontal)
                {
                    childRectangle.X += previousChildSize;

                    if (addSpacing)
                    {
                        childRectangle.X += spacing;
                    }

                    previousChildSize     = desiredChildSize.Width;
                    childRectangle.Width  = desiredChildSize.Width;
                    childRectangle.Height = Math.Max(arrangeSize.Height, desiredChildSize.Height);
                }
                else
                {
                    childRectangle.Y += previousChildSize;

                    if (addSpacing)
                    {
                        childRectangle.Y += spacing;
                    }

                    previousChildSize     = desiredChildSize.Height;
                    childRectangle.Height = desiredChildSize.Height;
                    childRectangle.Width  = Math.Max(arrangeSize.Width, desiredChildSize.Width);
                }

                var adjustedRectangle = childRectangle;

                ArrangeElement(view, adjustedRectangle);
            }

            arrangeSize.Width  += GetHorizontalOffset();
            arrangeSize.Height += GetVerticalOffset();

            return(arrangeSize);
        }
Exemplo n.º 6
0
        internal void SetCoreBounds(NSWindow keyWindow, Foundation.Rect windowBounds)
        {
            VisibleBounds = windowBounds;

            if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
            {
                this.Log().Debug($"Updated visible bounds {VisibleBounds}");
            }

            VisibleBoundsChanged?.Invoke(this, null);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Create matrix to transform image based on relative dimensions of bitmap and drawRect, Stretch mode, and RelativeTransform
        /// </summary>
        /// <param name="drawRect"></param>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        private Android.Graphics.Matrix GenerateMatrix(Foundation.Rect drawRect, Bitmap bitmap)
        {
            var matrix = new Android.Graphics.Matrix();

            // Note that bitmap.Width and bitmap.Height (in physical pixels) are automatically scaled up when loaded from local resources, but aren't when acquired externally.
            // This means that bitmaps acquired externally might not render the same way on devices with different densities when using Stretch.None.

            var sourceRect      = new Foundation.Rect(0, 0, bitmap.Width, bitmap.Height);
            var destinationRect = GetArrangedImageRect(sourceRect.Size, drawRect);

            matrix.SetRectToRect(sourceRect.ToRectF(), destinationRect.ToRectF(), Android.Graphics.Matrix.ScaleToFit.Fill);

            RelativeTransform?.ToNativeTransform(matrix, new Size(drawRect.Width, drawRect.Height), isBrush: true);
            return(matrix);
        }
Exemplo n.º 8
0
        protected override Size ArrangeOverride(Size finalSize)
        {
            var child = this.FindFirstChild();

            if (child != null)
            {
                var padding         = Padding;
                var borderThickness = BorderThickness;

                var finalRect = new Foundation.Rect(
                    padding.Left + borderThickness.Left,
                    padding.Top + borderThickness.Top,
                    finalSize.Width - padding.Left - padding.Right - borderThickness.Left - borderThickness.Right,
                    finalSize.Height - padding.Top - padding.Bottom - borderThickness.Top - borderThickness.Bottom
                    );

                base.ArrangeElement(child, finalRect);
            }

            return(finalSize);
        }
Exemplo n.º 9
0
        internal void SetVisibleBounds(UIKit.UIWindow keyWindow, Foundation.Rect windowBounds)
        {
            var inset = UseSafeAreaInsets
                                        ? keyWindow.SafeAreaInsets
                                        : UIEdgeInsets.Zero;

            // Not respecting its own documentation. https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
            // iOS returns all zeros for SafeAreaInsets on non-iPhones and iOS11. (ignoring nav bars or status bars)
            // So we need to update the top inset depending of the status bar visibility on other devices
            var statusBarHeight = UIApplication.SharedApplication.StatusBarHidden
                                        ? 0
                                        : UIApplication.SharedApplication.StatusBarFrame.Size.Height;

            inset.Top = (nfloat)Math.Max(inset.Top, statusBarHeight);

            var newVisibleBounds = new Foundation.Rect(
                x: windowBounds.Left + inset.Left,
                y: windowBounds.Top + inset.Top,
                width: windowBounds.Width - inset.Right - inset.Left,
                height: windowBounds.Height - inset.Top - inset.Bottom
                );

            SetVisibleBounds(newVisibleBounds);
        }
Exemplo n.º 10
0
        private IDisposable BuildDrawableLayer()
        {
            if (_controlHeight == 0 || _controlWidth == 0)
            {
                return(Disposable.Empty);
            }

            var drawables = new List <Drawable>();

            var path = GetPath();

            if (path == null)
            {
                return(Disposable.Empty);
            }

            // Scale the path using its Stretch
            Android.Graphics.Matrix matrix = new Android.Graphics.Matrix();
            switch (this.Stretch)
            {
            case Media.Stretch.Fill:
            case Media.Stretch.None:
                matrix.SetScale((float)_scaleX, (float)_scaleY);
                break;

            case Media.Stretch.Uniform:
                var scale = Math.Min(_scaleX, _scaleY);
                matrix.SetScale((float)scale, (float)scale);
                break;

            case Media.Stretch.UniformToFill:
                scale = Math.Max(_scaleX, _scaleY);
                matrix.SetScale((float)scale, (float)scale);
                break;
            }
            path.Transform(matrix);

            // Move the path using its alignements
            var translation = new Android.Graphics.Matrix();

            var pathBounds = new RectF();

            // Compute the bounds. This is needed for stretched shapes and stroke thickness translation calculations.
            path.ComputeBounds(pathBounds, true);

            if (Stretch == Stretch.None)
            {
                // Since we are not stretching, ensure we are using (0, 0) as origin.
                pathBounds.Left = 0;
                pathBounds.Top  = 0;
            }

            if (!ShouldPreserveOrigin)
            {
                //We need to translate the shape to take in account the stroke thickness
                translation.SetTranslate((float)(-pathBounds.Left + PhysicalStrokeThickness * 0.5f), (float)(-pathBounds.Top + PhysicalStrokeThickness * 0.5f));
            }

            path.Transform(translation);

            // Draw the fill
            var drawArea = new Foundation.Rect(0, 0, _controlWidth, _controlHeight);

            var imageBrushFill = Fill as ImageBrush;

            if (imageBrushFill != null)
            {
                var bitmapDrawable = new BitmapDrawable(Context.Resources, imageBrushFill.TryGetBitmap(drawArea, () => RefreshShape(forceRefresh: true), path));
                drawables.Add(bitmapDrawable);
            }
            else
            {
                var fill      = Fill ?? SolidColorBrushHelper.Transparent;
                var fillPaint = fill.GetFillPaint(drawArea);

                var lineDrawable = new PaintDrawable();
                lineDrawable.Shape       = new PathShape(path, (float)_controlWidth, (float)_controlHeight);
                lineDrawable.Paint.Color = fillPaint.Color;
                lineDrawable.Paint.SetShader(fillPaint.Shader);
                lineDrawable.Paint.SetStyle(Paint.Style.Fill);
                lineDrawable.Paint.Alpha = fillPaint.Alpha;

                this.SetStrokeDashEffect(lineDrawable.Paint);

                drawables.Add(lineDrawable);
            }

            // Draw the contour
            if (Stroke != null)
            {
                using (var strokeBrush = new Paint(Stroke.GetStrokePaint(drawArea)))
                {
                    var lineDrawable = new PaintDrawable();
                    lineDrawable.Shape       = new PathShape(path, (float)_controlWidth, (float)_controlHeight);
                    lineDrawable.Paint.Color = strokeBrush.Color;
                    lineDrawable.Paint.SetShader(strokeBrush.Shader);
                    lineDrawable.Paint.StrokeWidth = (float)PhysicalStrokeThickness;
                    lineDrawable.Paint.SetStyle(Paint.Style.Stroke);
                    lineDrawable.Paint.Alpha = strokeBrush.Alpha;

                    this.SetStrokeDashEffect(lineDrawable.Paint);

                    drawables.Add(lineDrawable);
                }
            }

            var layerDrawable = new LayerDrawable(drawables.ToArray());

            // Set bounds must always be called, otherwise the android layout engine can't determine
            // the rendering size. See Drawable documentation for details.
            layerDrawable.SetBounds(0, 0, (int)_controlWidth, (int)_controlHeight);

            return(SetOverlay(this, layerDrawable));
        }
Exemplo n.º 11
0
        /// <summary>
        /// Synchronously tries to return a bitmap for this ImageBrush. If the backing image is not available,
        /// a fetch will be scheduled and the onImageLoaded callback will be called once the backing image is ready.
        /// </summary>
        /// <param name="drawRect">The destination bounds</param>
        /// <param name="onImageLoaded">A callback that will be called when the backing image changes (eg, to redraw your view)</param>
        /// <param name="maskingPath">An optional path to clip the bitmap by (eg an ellipse)</param>
        /// <returns>A bitmap transformed based on target bounds and shape, Stretch mode, and RelativeTransform</returns>
        internal Bitmap TryGetBitmap(Foundation.Rect drawRect, Action onImageLoaded, Path maskingPath = null)
        {
            ScheduleRefreshIfNeeded(drawRect, onImageLoaded);

            return(GetTransformedBitmap(drawRect, maskingPath));
        }
Exemplo n.º 12
0
		internal InputPaneVisibilityEventArgs(Foundation.Rect occludedRect)
		{
			OccludedRect = occludedRect;
		}
Exemplo n.º 13
0
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            var borderAndPaddingSize = BorderAndPaddingSize;

            arrangeSize = arrangeSize.Subtract(borderAndPaddingSize);

            var childRectangle = new Foundation.Rect(BorderThickness.Left + Padding.Left, BorderThickness.Top + Padding.Top, arrangeSize.Width, arrangeSize.Height);

            var isHorizontal      = Orientation == Windows.UI.Xaml.Controls.Orientation.Horizontal;
            var previousChildSize = 0.0;

            if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
            {
                this.Log().Debug($"StackPanel/{Name}: Arranging {Children.Count} children.");
            }

            // Shadow variables for evaluation performance
            var spacing = Spacing;
            var count   = Children.Count;

            for (var i = 0; i < count; i++)
            {
                var view             = Children[i];
                var desiredChildSize = GetElementDesiredSize(view);
                var addSpacing       = i != 0;

                if (isHorizontal)
                {
                    childRectangle.X += previousChildSize;

                    if (addSpacing)
                    {
                        childRectangle.X += spacing;
                    }

                    previousChildSize     = desiredChildSize.Width;
                    childRectangle.Width  = desiredChildSize.Width;
                    childRectangle.Height = Math.Max(arrangeSize.Height, desiredChildSize.Height);
                }
                else
                {
                    childRectangle.Y += previousChildSize;

                    if (addSpacing)
                    {
                        childRectangle.Y += spacing;
                    }

                    previousChildSize     = desiredChildSize.Height;
                    childRectangle.Height = desiredChildSize.Height;
                    childRectangle.Width  = Math.Max(arrangeSize.Width, desiredChildSize.Width);
                }

                var adjustedRectangle = childRectangle;

                ArrangeElement(view, adjustedRectangle);
            }

            var finalSizeWithBorderAndPadding = arrangeSize.Add(borderAndPaddingSize);

            return(finalSizeWithBorderAndPadding);
        }