示例#1
0
        /// <summary>
        ///     Defines the template for core-level arrange layout definition.
        /// </summary>
        /// <remarks>
        ///     In WPF this method is defined on UIElement as protected virtual and has a base implementation.
        ///     FrameworkElement (which derrives from UIElement) creates a sealed implemention, similar to the below,
        ///     which discards UIElement's base implementation.
        /// </remarks>
        /// <param name = "finalRect">The final area within the parent that element should use to arrange itself and its child elements.</param>
        private void ArrangeCore(Rect finalRect)
        {
            this.isClippingRequired = false;
            Size finalSize = finalRect != Rect.Empty ? new Size(finalRect.Width, finalRect.Height) : new Size();

            Thickness margin = this.Margin;

            finalSize = finalSize.Deflate(margin);

            Size unclippedDesiredSize = this.unclippedSize.IsEmpty
                                            ? this.DesiredSize.Deflate(margin)
                                            : this.unclippedSize;

            if (finalSize.Width.IsLessThan(unclippedDesiredSize.Width))
            {
                this.isClippingRequired = true;
                finalSize.Width = unclippedDesiredSize.Width;
            }

            if (finalSize.Height.IsLessThan(unclippedDesiredSize.Height))
            {
                this.isClippingRequired = true;
                finalSize.Height = unclippedDesiredSize.Height;
            }

            if (this.HorizontalAlignment != HorizontalAlignment.Stretch)
            {
                finalSize.Width = unclippedDesiredSize.Width;
            }

            if (this.VerticalAlignment != VerticalAlignment.Stretch)
            {
                finalSize.Height = unclippedDesiredSize.Height;
            }

            var minMax = new MinMax(this);

            double largestWidth = Math.Max(unclippedDesiredSize.Width, minMax.MaxWidth);
            if (largestWidth.IsLessThan(finalSize.Width))
            {
                finalSize.Width = largestWidth;
            }

            double largestHeight = Math.Max(unclippedDesiredSize.Height, minMax.MaxHeight);
            if (largestHeight.IsLessThan(finalSize.Height))
            {
                finalSize.Height = largestHeight;
            }

            Size renderSize = this.ArrangeOverride(finalSize);
            this.RenderSize = renderSize;

            var inkSize = new Size(
                Math.Min(renderSize.Width, minMax.MaxWidth), Math.Min(renderSize.Height, minMax.MaxHeight));

            this.isClippingRequired |= inkSize.Width.IsLessThan(renderSize.Width) ||
                                       inkSize.Height.IsLessThan(renderSize.Height);

            Size clientSize = finalRect.Size.Deflate(margin);

            this.isClippingRequired |= clientSize.Width.IsLessThan(inkSize.Width) ||
                                       clientSize.Height.IsLessThan(inkSize.Height);

            Vector offset = this.ComputeAlignmentOffset(clientSize, inkSize);
            offset.X += finalRect.X + margin.Left;
            offset.Y += finalRect.Y + margin.Top;

            this.visualOffset = offset;
        }
示例#2
0
        /// <summary>
        ///     Implements basic measure-pass layout system behavior.
        /// </summary>
        /// <remarks>
        ///     In WPF this method is definded on UIElement as protected virtual and returns an empty Size.
        ///     FrameworkElement (which derrives from UIElement) then creates a sealed implementation similar to the below.
        ///     In XPF UIElement and FrameworkElement have been collapsed into a single class.
        /// </remarks>
        /// <param name = "availableSize">The available size that the parent element can give to the child elements.</param>
        /// <returns>The desired size of this element in layout.</returns>
        private Size MeasureCore(Size availableSize)
        {
            this.ResolveDeferredBindings(this.GetNearestDataContext());
            this.OnApplyTemplate();

            Thickness margin = this.Margin;
            Size availableSizeWithoutMargins = availableSize.Deflate(margin);

            var minMax = new MinMax(this);

            availableSizeWithoutMargins.Width = availableSizeWithoutMargins.Width.Coerce(
                minMax.MinWidth, minMax.MaxWidth);
            availableSizeWithoutMargins.Height = availableSizeWithoutMargins.Height.Coerce(
                minMax.MinHeight, minMax.MaxHeight);

            Size size = this.MeasureOverride(availableSizeWithoutMargins);

            size = new Size(Math.Max(size.Width, minMax.MinWidth), Math.Max(size.Height, minMax.MinHeight));
            Size unclippedSize = size;

            bool isClippingRequired = false;
            if (size.Width > minMax.MaxWidth)
            {
                size.Width = minMax.MaxWidth;
                isClippingRequired = true;
            }

            if (size.Height > minMax.MaxHeight)
            {
                size.Height = minMax.MaxHeight;
                isClippingRequired = true;
            }

            Size desiredSizeWithMargins = size.Inflate(margin);

            if (desiredSizeWithMargins.Width > availableSize.Width)
            {
                desiredSizeWithMargins.Width = availableSize.Width;
                isClippingRequired = true;
            }

            if (desiredSizeWithMargins.Height > availableSize.Height)
            {
                desiredSizeWithMargins.Height = availableSize.Height;
                isClippingRequired = true;
            }

            this.unclippedSize = isClippingRequired ? unclippedSize : Size.Empty;

            return desiredSizeWithMargins;
        }
示例#3
0
        protected virtual Rect GetClippingRect(Size finalSize)
        {
            if (!this.isClippingRequired)
            {
                return Rect.Empty;
            }

            var max = new MinMax(this);
            Size renderSize = this.RenderSize;

            double maxWidth = double.IsPositiveInfinity(max.MaxWidth) ? renderSize.Width : max.MaxWidth;
            double maxHeight = double.IsPositiveInfinity(max.MaxHeight) ? renderSize.Height : max.MaxHeight;

            bool isClippingRequiredDueToMaxSize = maxWidth.IsLessThan(renderSize.Width) ||
                                                  maxHeight.IsLessThan(renderSize.Height);

            renderSize.Width = Math.Min(renderSize.Width, max.MaxWidth);
            renderSize.Height = Math.Min(renderSize.Height, max.MaxHeight);

            Thickness margin = this.Margin;
            double horizontalMargins = margin.Left + margin.Right;
            double verticalMargins = margin.Top + margin.Bottom;

            var clientSize = new Size(
                (finalSize.Width - horizontalMargins).EnsurePositive(), 
                (finalSize.Height - verticalMargins).EnsurePositive());

            bool isClippingRequiredDueToClientSize = clientSize.Width.IsLessThan(renderSize.Width) ||
                                                     clientSize.Height.IsLessThan(renderSize.Height);

            if (isClippingRequiredDueToMaxSize && !isClippingRequiredDueToClientSize)
            {
                return new Rect(0d, 0d, maxWidth, maxHeight);
            }

            if (!isClippingRequiredDueToClientSize)
            {
                return Rect.Empty;
            }

            Vector offset = this.ComputeAlignmentOffset(clientSize, renderSize);

            var clipRect = new Rect(-offset.X, -offset.Y, clientSize.Width, clientSize.Height);

            if (isClippingRequiredDueToMaxSize)
            {
                clipRect.Intersect(new Rect(0d, 0d, maxWidth, maxHeight));
            }

            return clipRect;
        }