예제 #1
0
        /// <summary>
        /// The default implementation of the control's measure pass.
        /// </summary>
        /// <param name="availableSize">The size available to the control.</param>
        /// <returns>The desired size for the control.</returns>
        /// <remarks>
        /// This method calls <see cref="MeasureOverride(Size)"/> which is probably the method you
        /// want to override in order to modify a control's arrangement.
        /// </remarks>
        protected virtual Size MeasureCore(Size availableSize)
        {
            if (IsVisible)
            {
                var margin = Margin;

                ApplyTemplate();

                var constrained = LayoutHelper.ApplyLayoutConstraints(
                    this,
                    availableSize.Deflate(margin));
                var measured = MeasureOverride(constrained);

                var width  = measured.Width;
                var height = measured.Height;

                if (!double.IsNaN(Width))
                {
                    width = Width;
                }

                width = Math.Min(width, MaxWidth);
                width = Math.Max(width, MinWidth);

                if (!double.IsNaN(Height))
                {
                    height = Height;
                }

                height = Math.Min(height, MaxHeight);
                height = Math.Max(height, MinHeight);

                width  = Math.Min(width, availableSize.Width);
                height = Math.Min(height, availableSize.Height);

                if (UseLayoutRounding)
                {
                    var scale = GetLayoutScale();
                    width  = Math.Ceiling(width * scale) / scale;
                    height = Math.Ceiling(height * scale) / scale;
                }

                return(NonNegative(new Size(width, height).Inflate(margin)));
            }
            else
            {
                return(new Size());
            }
        }
예제 #2
0
        /// <summary>
        /// The default implementation of the control's arrange pass.
        /// </summary>
        /// <param name="finalRect">The control's new bounds.</param>
        /// <remarks>
        /// This method calls <see cref="ArrangeOverride(Size)"/> which is probably the method you
        /// want to override in order to modify a control's arrangement.
        /// </remarks>
        protected virtual void ArrangeCore(Rect finalRect)
        {
            if (IsVisible)
            {
                var margin  = Margin;
                var originX = finalRect.X + margin.Left;
                var originY = finalRect.Y + margin.Top;
                var availableSizeMinusMargins = new Size(
                    Math.Max(0, finalRect.Width - margin.Left - margin.Right),
                    Math.Max(0, finalRect.Height - margin.Top - margin.Bottom));
                var horizontalAlignment = HorizontalAlignment;
                var verticalAlignment   = VerticalAlignment;
                var size  = availableSizeMinusMargins;
                var scale = GetLayoutScale();

                if (horizontalAlignment != HorizontalAlignment.Stretch)
                {
                    size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - margin.Left - margin.Right));
                }

                if (verticalAlignment != VerticalAlignment.Stretch)
                {
                    size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - margin.Top - margin.Bottom));
                }

                size = LayoutHelper.ApplyLayoutConstraints(this, size);

                if (UseLayoutRounding)
                {
                    size = new Size(
                        Math.Ceiling(size.Width * scale) / scale,
                        Math.Ceiling(size.Height * scale) / scale);
                    availableSizeMinusMargins = new Size(
                        Math.Ceiling(availableSizeMinusMargins.Width * scale) / scale,
                        Math.Ceiling(availableSizeMinusMargins.Height * scale) / scale);
                }

                size = ArrangeOverride(size).Constrain(size);

                switch (horizontalAlignment)
                {
                case HorizontalAlignment.Center:
                case HorizontalAlignment.Stretch:
                    originX += (availableSizeMinusMargins.Width - size.Width) / 2;
                    break;

                case HorizontalAlignment.Right:
                    originX += availableSizeMinusMargins.Width - size.Width;
                    break;
                }

                switch (verticalAlignment)
                {
                case VerticalAlignment.Center:
                case VerticalAlignment.Stretch:
                    originY += (availableSizeMinusMargins.Height - size.Height) / 2;
                    break;

                case VerticalAlignment.Bottom:
                    originY += availableSizeMinusMargins.Height - size.Height;
                    break;
                }

                if (UseLayoutRounding)
                {
                    originX = Math.Floor(originX * scale) / scale;
                    originY = Math.Floor(originY * scale) / scale;
                }

                Bounds = new Rect(originX, originY, size.Width, size.Height);
            }
        }
예제 #3
0
        protected virtual void ArrangeCore(Rect finalRect)
        {
            if (IsVisible)
            {
                var useLayoutRounding = UseLayoutRounding;
                var scale             = LayoutHelper.GetLayoutScale(this);

                var margin  = Margin;
                var originX = finalRect.X + margin.Left;
                var originY = finalRect.Y + margin.Top;

                // Margin has to be treated separately because the layout rounding function is not linear
                // f(a + b) != f(a) + f(b)
                // If the margin isn't pre-rounded some sizes will be offset by 1 pixel in certain scales.
                if (useLayoutRounding)
                {
                    margin = LayoutHelper.RoundLayoutThickness(margin, scale, scale);
                }

                var availableSizeMinusMargins = new Size(
                    Math.Max(0, finalRect.Width - margin.Left - margin.Right),
                    Math.Max(0, finalRect.Height - margin.Top - margin.Bottom));
                var horizontalAlignment = HorizontalAlignment;
                var verticalAlignment   = VerticalAlignment;
                var size = availableSizeMinusMargins;

                if (horizontalAlignment != HorizontalAlignment.Stretch)
                {
                    size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - margin.Left - margin.Right));
                }

                if (verticalAlignment != VerticalAlignment.Stretch)
                {
                    size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - margin.Top - margin.Bottom));
                }

                size = LayoutHelper.ApplyLayoutConstraints(this, size);

                if (useLayoutRounding)
                {
                    size = LayoutHelper.RoundLayoutSize(size, scale, scale);
                    availableSizeMinusMargins = LayoutHelper.RoundLayoutSize(availableSizeMinusMargins, scale, scale);
                }

                size = ArrangeOverride(size).Constrain(size);

                switch (horizontalAlignment)
                {
                case HorizontalAlignment.Center:
                case HorizontalAlignment.Stretch:
                    originX += (availableSizeMinusMargins.Width - size.Width) / 2;
                    break;

                case HorizontalAlignment.Right:
                    originX += availableSizeMinusMargins.Width - size.Width;
                    break;
                }

                switch (verticalAlignment)
                {
                case VerticalAlignment.Center:
                case VerticalAlignment.Stretch:
                    originY += (availableSizeMinusMargins.Height - size.Height) / 2;
                    break;

                case VerticalAlignment.Bottom:
                    originY += availableSizeMinusMargins.Height - size.Height;
                    break;
                }

                if (useLayoutRounding)
                {
                    originX = LayoutHelper.RoundLayoutValue(originX, scale);
                    originY = LayoutHelper.RoundLayoutValue(originY, scale);
                }

                Bounds = new Rect(originX, originY, size.Width, size.Height);
            }
        }
예제 #4
0
        /// <inheritdoc/>
        protected sealed override void OnVisualParentChanged(IVisual oldParent, IVisual newParent)
        {
            LayoutHelper.InvalidateSelfAndChildrenMeasure(this);

            base.OnVisualParentChanged(oldParent, newParent);
        }
예제 #5
0
        protected virtual Size MeasureCore(Size availableSize)
        {
            if (IsVisible)
            {
                var margin            = Margin;
                var useLayoutRounding = UseLayoutRounding;
                var scale             = 1.0;

                if (useLayoutRounding)
                {
                    scale  = LayoutHelper.GetLayoutScale(this);
                    margin = LayoutHelper.RoundLayoutThickness(margin, scale, scale);
                }

                ApplyStyling();
                ApplyTemplate();

                var constrained = LayoutHelper.ApplyLayoutConstraints(
                    this,
                    availableSize.Deflate(margin));
                var measured = MeasureOverride(constrained);

                var width  = measured.Width;
                var height = measured.Height;

                {
                    double widthCache = Width;

                    if (!double.IsNaN(widthCache))
                    {
                        width = widthCache;
                    }
                }

                width = Math.Min(width, MaxWidth);
                width = Math.Max(width, MinWidth);

                {
                    double heightCache = Height;

                    if (!double.IsNaN(heightCache))
                    {
                        height = heightCache;
                    }
                }

                height = Math.Min(height, MaxHeight);
                height = Math.Max(height, MinHeight);

                if (useLayoutRounding)
                {
                    (width, height) = LayoutHelper.RoundLayoutSizeUp(new Size(width, height), scale, scale);
                }

                width  = Math.Min(width, availableSize.Width);
                height = Math.Min(height, availableSize.Height);

                return(NonNegative(new Size(width, height).Inflate(margin)));
            }
            else
            {
                return(new Size());
            }
        }