示例#1
0
        //public static OrientedSize ArrangeStackLine(this Panel panel, Orientation orientation, Range<int> line, double lineOffset, double itemOffset, double? fixedLineSize, double? fixedItemSize)
        //{
        //  return ArrangeStackLine(panel.Children.Cast<UIElement>().Skip(line.Minimum).Take(line.Maximum - line.Minimum), orientation, lineOffset, itemOffset, fixedLineSize, fixedItemSize);
        //}

        public static OrientedSize ArrangeStackLine(IEnumerable <UIElement> elements, Orientation orientation, double lineOffset, double itemOffset, double?fixedLineSize, double?fixedItemSize)
        {
            var isHorizontal = orientation.IsHorizontal();

            var orientedSize = new OrientedSize(orientation);

            foreach (var element in elements)
            {
                var elementSize = element.DesiredSize.AsOriented(orientation);

                var itemSize = fixedItemSize ?? elementSize.Direct;
                var lineSize = fixedLineSize ?? elementSize.Indirect;

                var bounds = isHorizontal
          ? new Rect(itemOffset, lineOffset, itemSize, lineSize)
          : new Rect(lineOffset, itemOffset, lineSize, itemSize);

                //bounds = bounds.LayoutRoundToEven();

                element.Arrange(bounds);
                itemOffset += itemSize;
                //itemOffset = itemOffset.LayoutRoundMidPointFromZero(orientation);

                orientedSize = orientedSize.StackSize(elementSize);
            }

            return(orientedSize);
        }
示例#2
0
        //public static OrientedSize MeasureStackLine(this Panel panel, Orientation orientation, Range<int> line, double lineOffset, double itemOffset, double? fixedLineSize, double? fixedItemSize)
        //{
        //  return MeasureStackLine(panel.Children.Cast<UIElement>().Skip(line.Minimum).Take(line.Length()), orientation, null, null, fixedLineSize, fixedItemSize);
        //}

        public static OrientedSize MeasureStackLine(IEnumerable <UIElement> elements, OrientedSize availableSize, OrientedSize minimumSize, double?fixedLineSize, double?fixedItemSize)
        {
            var orientation  = availableSize.Orientation;
            var orientedSize = new OrientedSize(orientation);

            foreach (var element in elements)
            {
                var currentConstraint = new OrientedSize(orientation)
                {
                    Direct   = (availableSize.Direct - orientedSize.Direct).Clamp(minimumSize.Direct, double.PositiveInfinity),
                    Indirect = availableSize.Indirect.Clamp(minimumSize.Indirect, double.PositiveInfinity)
                };

                var measureSize = new OrientedSize(orientation)
                {
                    Direct   = Math.Min(currentConstraint.Direct, fixedItemSize ?? double.PositiveInfinity),
                    Indirect = Math.Min(currentConstraint.Indirect, fixedLineSize ?? double.PositiveInfinity)
                };

                element.Measure(measureSize.Size);

                var desired = element.DesiredSize.AsOriented(orientation);

                orientedSize = orientedSize.StackSize(desired);
            }

            return(orientedSize);
        }
            private void EnsureSizePart(TGridLineModel model, Size availableSize, Orientation orientation, bool expandCross)
            {
                var horizontal          = orientation.IsHorizontal();
                var orientedSize        = new OrientedSize(orientation, availableSize);
                var currentOrientedSize = new OrientedSize(orientation, _size);
                var gridLines           = model.GridLines;
                var sortedDefinitions   = gridLines.SortedLines;
                var fillSize            = orientedSize.Direct + MaxGridStep;
                var lineSize            = orientedSize.Indirect + (expandCross ? MaxGridStep : 0);
                var lineCount           = horizontal ? _lineCountX : _lineCountY;

                if (lineSize.IsGreaterThan(currentOrientedSize.Indirect))
                {
                    for (var i = 0; i < sortedDefinitions.Count; i++)
                    {
                        var pathFigureCollection = _pathFigures[i].Figures;
                        var iLine = 0;

                        foreach (var figure in pathFigureCollection)
                        {
                            var line            = (LineSegment)figure.Segments[0];
                            var lineOrientation = figure.StartPoint.X.Equals(line.Point.X) ? Orientation.Horizontal : Orientation.Vertical;

                            if (orientation != lineOrientation)
                            {
                                continue;
                            }

                            var orientedPoint  = new OrientedPoint(orientation, figure.StartPoint);
                            var iStep          = gridLines.GetSortedDefinitionIndex(iLine);
                            var lineDefinition = sortedDefinitions[iStep];

                            UpdateLineFigure(figure, lineDefinition, orientation, orientedPoint.Direct, orientedPoint.Indirect, lineSize);

                            iLine++;
                        }
                    }
                }

                for (var offset = lineCount * GridStep; offset < fillSize; offset += GridStep)
                {
                    var snapOffset           = offset.LayoutRound(orientation, RoundingMode.MidPointFromZero) + 0.5;
                    var iStep                = gridLines.GetSortedDefinitionIndex(lineCount);
                    var lineDefinition       = sortedDefinitions[iStep];
                    var pathFigureCollection = _pathFigures[iStep].Figures;

                    pathFigureCollection.Add(CreateLineFigure(lineDefinition, orientation, snapOffset, 0, lineSize));

                    lineCount++;
                }

                if (horizontal)
                {
                    _lineCountX = lineCount;
                }
                else
                {
                    _lineCountY = lineCount;
                }
            }
示例#4
0
文件: SizeUtils.cs 项目: Egaros/lib
        public static OrientedSize ExpandTo(OrientedSize size, OrientedSize another)
        {
            var clone = size;

            clone.Size = clone.Size.ExpandTo(another.Size);

            return(clone);
        }
示例#5
0
        internal static OrientedSize ConstraintSize(this OrientedSize desiredSize, OrientedSize availableSize)
        {
            if (desiredSize.Orientation != availableSize.Orientation)
            {
                throw new InvalidOperationException();
            }

            return(new OrientedSize(desiredSize.Orientation, desiredSize.Size.ConstraintSize(availableSize.Size)));
        }
示例#6
0
        private static OrientedSize GetFinalMeasureSize(OrientedSize availableSize, OrientedSize desiredSize, OrientedSize visibleSize)
        {
            var finalSize = availableSize;

            // Indirect
            finalSize.Indirect = finalSize.Indirect.IsInfinity() ? desiredSize.Indirect : visibleSize.Indirect;

            // Direct
            finalSize.Direct = finalSize.Direct.IsInfinity() ? desiredSize.Direct : visibleSize.Direct;

            return(finalSize.ConstraintSize(availableSize));
        }
示例#7
0
        public static Size Arrange(IWrapPanel panel, Size finalSize)
        {
            var orientation = panel.Orientation;
            var lineSize    = new OrientedSize(orientation);
            var maximumSize = new OrientedSize(orientation, finalSize);

            var itemWidth  = panel.ItemWidth.IsNaN() ? (double?)null : panel.ItemWidth;
            var itemHeight = panel.ItemHeight.IsNaN() ? (double?)null : panel.ItemHeight;

            var lineOffset    = 0.0;
            var fixedItemSize = orientation.IsHorizontal() ? itemWidth : itemHeight;

            var children  = panel.Elements;
            var count     = children.Count;
            var lineStart = 0;

            for (var lineEnd = 0; lineEnd < count; lineEnd++)
            {
                var element     = children[lineEnd];
                var elementSize = element.GetDesiredOrientedSize(orientation, itemWidth, itemHeight);

                if (maximumSize.Direct.IsLessThan(lineSize.Direct + elementSize.Direct, XamlConstants.LayoutComparisonPrecision))
                {
                    panel.ArrangeStackLine(orientation, Zaaml.Core.Range.Create(lineStart, lineEnd), lineOffset, 0, lineSize.Indirect, fixedItemSize);

                    lineOffset += lineSize.Indirect;
                    lineSize    = elementSize;

                    if (maximumSize.Direct.IsLessThan(elementSize.Direct, XamlConstants.LayoutComparisonPrecision))
                    {
                        panel.ArrangeStackLine(orientation, Zaaml.Core.Range.Create(lineStart, ++lineEnd), lineOffset, 0, lineSize.Indirect, fixedItemSize);

                        lineOffset += lineSize.Indirect;
                        lineSize    = new OrientedSize(orientation);
                    }

                    lineStart = lineEnd;
                }
                else
                {
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            if (lineStart < count)
            {
                panel.ArrangeStackLine(orientation, Zaaml.Core.Range.Create(lineStart, count), lineOffset, 0, lineSize.Indirect, fixedItemSize);
            }

            return(finalSize);
        }
示例#8
0
        internal static OrientedSize Clamp(this OrientedSize self, OrientedSize min, OrientedSize max)
        {
            if (self.Orientation != min.Orientation || min.Orientation != max.Orientation)
            {
                throw new InvalidOperationException();
            }

            return(new OrientedSize(self.Orientation)
            {
                Direct = self.Direct.Clamp(min.Direct, max.Direct),
                Indirect = self.Indirect.Clamp(min.Indirect, max.Indirect),
            });
        }
示例#9
0
        protected override Size ArrangeOverride(Size finalSize)
        {
            Orientation  o              = Orientation;
            OrientedSize lineSize       = new OrientedSize(o);
            OrientedSize maximumSize    = new OrientedSize(o, finalSize.Width, finalSize.Height);
            double       itemWidth      = ItemWidth;
            double       itemHeight     = ItemHeight;
            bool         hasFixedWidth  = !double.IsNaN(itemWidth);
            bool         hasFixedHeight = !double.IsNaN(itemHeight);
            double       indirectOffset = 0;
            double?      directDelta    = (o == Orientation.Horizontal) ?
                                          (hasFixedWidth ? (double?)itemWidth : null) :
                                          (hasFixedHeight ? (double?)itemHeight : null);
            UIElementCollection children = Children;
            int count     = children.Count;
            int lineStart = 0;

            for (int lineEnd = 0; lineEnd < count; lineEnd++)
            {
                UIElement    element     = children[lineEnd];
                OrientedSize elementSize = new OrientedSize(o,
                                                            hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                                                            hasFixedHeight ? itemHeight : element.DesiredSize.Height);
                if (IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    ArrangeLine(lineStart, lineEnd, directDelta, indirectOffset, lineSize.Indirect);
                    indirectOffset += lineSize.Indirect;
                    lineSize        = elementSize;
                    if (IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        ArrangeLine(lineEnd, ++lineEnd, directDelta, indirectOffset, elementSize.Indirect);
                        indirectOffset += lineSize.Indirect;
                        lineSize        = new OrientedSize(o);
                    }
                    lineStart = lineEnd;
                }
                else
                {
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }
            if (lineStart < count)
            {
                ArrangeLine(lineStart, count, directDelta, indirectOffset, lineSize.Indirect);
            }
            return(finalSize);
        }
示例#10
0
        private static OrientedSize GetChildConstraint(FlexElement flexElement, OrientedSize autoConstraint, OrientedSize starConstraint)
        {
            var flexLength = flexElement.Length;

            if (flexLength.IsStar)
            {
                starConstraint.Direct *= flexLength.Value;

                return(starConstraint);
            }

            if (flexLength.IsAbsolute)
            {
                autoConstraint.Direct = flexLength.Value;

                return(autoConstraint);
            }

            return(autoConstraint);
        }
示例#11
0
        private void ArrangeLine(int lineStart, int lineEnd,
                                 double?directDelta, double indirectOffset, double indirectGrowth)
        {
            double              directOffset = 0.0;
            Orientation         o            = Orientation;
            bool                isHorizontal = o == Orientation.Horizontal;
            UIElementCollection children     = Children;

            for (int index = lineStart; index < lineEnd; index++)
            {
                UIElement    element      = children[index];
                OrientedSize elementSize  = new OrientedSize(o, element.DesiredSize.Width, element.DesiredSize.Height);
                double       directGrowth = directDelta != null ? directDelta.Value : elementSize.Direct;
                Rect         bounds       = isHorizontal ?
                                            new Rect(directOffset, indirectOffset, directGrowth, indirectGrowth) :
                                            new Rect(indirectOffset, directOffset, indirectGrowth, directGrowth);
                element.Arrange(bounds);
                directOffset += directGrowth;
            }
        }
示例#12
0
        protected override Size MeasureOverride(Size constraint)
        {
            Orientation  o              = Orientation;
            OrientedSize lineSize       = new OrientedSize(o);
            OrientedSize totalSize      = new OrientedSize(o);
            OrientedSize maximumSize    = new OrientedSize(o, constraint.Width, constraint.Height);
            double       itemWidth      = ItemWidth;
            double       itemHeight     = ItemHeight;
            bool         hasFixedWidth  = !double.IsNaN(itemWidth);
            bool         hasFixedHeight = !double.IsNaN(itemHeight);
            Size         itemSize       = new Size(hasFixedWidth ? itemWidth : constraint.Width,
                                                   hasFixedHeight ? itemHeight : constraint.Height);

            foreach (UIElement element in Children)
            {
                element.Measure(itemSize);
                OrientedSize elementSize = new OrientedSize(o,
                                                            hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                                                            hasFixedHeight ? itemHeight : element.DesiredSize.Height);
                if (IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    totalSize.Direct    = Math.Max(lineSize.Direct, totalSize.Direct);
                    totalSize.Indirect += lineSize.Indirect;
                    lineSize            = elementSize;
                    if (IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        totalSize.Direct    = Math.Max(elementSize.Direct, totalSize.Direct);
                        totalSize.Indirect += elementSize.Indirect;
                        lineSize            = new OrientedSize(o);
                    }
                }
                else
                {
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }
            totalSize.Direct    = Math.Max(lineSize.Direct, totalSize.Direct);
            totalSize.Indirect += lineSize.Indirect;
            return(new Size(totalSize.Width, totalSize.Height));
        }
示例#13
0
        public static Size Measure(IWrapPanel panel, Size availableSize)
        {
            var orientation        = panel.Orientation;
            var result             = new OrientedSize(orientation);
            var lineSize           = new OrientedSize(orientation);
            var orientedConstraint = new OrientedSize(orientation, availableSize);

            var itemWidth  = panel.ItemWidth.IsNaN() ? (double?)null : panel.ItemWidth;
            var itemHeight = panel.ItemHeight.IsNaN() ? (double?)null : panel.ItemHeight;

            var itemConstraintSize = new Size(itemWidth ?? availableSize.Width, itemHeight ?? availableSize.Height);

            foreach (var element in panel.Elements)
            {
                element.Measure(itemConstraintSize);
                var elementSize = element.GetDesiredOrientedSize(orientation, itemWidth, itemHeight);

                if (orientedConstraint.Direct.IsLessThan(lineSize.Direct + elementSize.Direct, XamlConstants.LayoutComparisonPrecision))
                {
                    result   = result.WrapSize(lineSize);
                    lineSize = elementSize;

                    if (!orientedConstraint.Direct.IsLessThan(elementSize.Direct, XamlConstants.LayoutComparisonPrecision))
                    {
                        continue;
                    }

                    result   = result.WrapSize(elementSize);
                    lineSize = new OrientedSize(orientation);
                }
                else
                {
                    lineSize = lineSize.StackSize(elementSize);
                }
            }

            return(result.WrapSize(lineSize).Size);
        }
示例#14
0
        protected override Size MeasureOverrideCore(Size availableSize)
        {
            Children.Add(_phantomGroup);

            _phantomGroup.BeginMeasurePass();
            _phantomGroup.Invalidate();
            _phantomGroup.Measure(new Size(0, double.PositiveInfinity));
            _phantomGroup.EndMeasurePass();

            var largeItemDesiredSize = _phantomGroup.DesiredSize;

            Children.Remove(_phantomGroup);

            if (Children.Count == 0)
            {
                return(new Size(0, largeItemDesiredSize.Height));
            }

            var reductionOrder = ActualGroupSizeReductionOrder.ToList();

            OddMeasure = false;

            try
            {
                foreach (var ribbonGroup in Groups)
                {
                    ribbonGroup.BeginMeasurePass();
                }

                var          nextReduceGroupIndex = 0;
                OrientedSize finalSize;

                var reductionLevel = 0;

                do
                {
                    finalSize = new OrientedSize(Orientation.Horizontal);

                    var measureItemSize = new Size(double.PositiveInfinity, largeItemDesiredSize.Height);

                    if (OddMeasure)
                    {
                        measureItemSize.Height += 1;
                    }

                    foreach (var ribbonGroup in Groups)
                    {
                        ribbonGroup.InvalidateInt(this);
                        finalSize = finalSize.StackSize(ribbonGroup.MeasureInt(measureItemSize, false));
                    }

                    OddMeasure = !OddMeasure;

                    if (finalSize.Direct.IsLessThanOrClose(availableSize.Width, XamlConstants.LayoutComparisonPrecision))
                    {
                        return(GetFinalSize(availableSize, new Size(finalSize.Width, largeItemDesiredSize.Height)));
                    }

                    foreach (var ribbonGroup in ActualGroupSizeReductionOrder)
                    {
                        var shrink = ribbonGroup.Shrink(finalSize.Direct - availableSize.Width);

                        if (shrink.IsZero(XamlConstants.LayoutComparisonPrecision))
                        {
                            continue;
                        }

                        finalSize.Direct -= shrink;

                        if (finalSize.Direct.IsLessThanOrClose(availableSize.Width, XamlConstants.LayoutComparisonPrecision))
                        {
                            return(GetFinalSize(availableSize, new Size(finalSize.Width, largeItemDesiredSize.Height)));
                        }
                    }

                    reductionLevel++;
                } while (ReduceNextGroup(reductionOrder, ref nextReduceGroupIndex));

                return(GetFinalSize(availableSize, new Size(finalSize.Width, largeItemDesiredSize.Height)));
            }
            finally
            {
                for (var i = 0; i < (OddMeasure ? 2 : 1); i++)
                {
                    var measureItemSize = new Size(double.PositiveInfinity, largeItemDesiredSize.Height);
                    if (OddMeasure)
                    {
                        measureItemSize.Height += 1;
                    }

                    OddMeasure = !OddMeasure;

                    foreach (var ribbonGroup in Groups)
                    {
                        ribbonGroup.InvalidateInt(this);
                        ribbonGroup.MeasureInt(measureItemSize, true);
                    }
                }

                foreach (var ribbonGroup in Groups)
                {
                    ribbonGroup.EndMeasurePass();
                }
            }
        }
示例#15
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+1 element in the sequence to arrange.
        /// </param>
        /// <param name="directDelta">
        /// Optional fixed growth in the primary direction.
        /// </param>
        /// <param name="directMaximum">
        /// Maximum length in the direct 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(int lineStart, int lineEnd, double?directDelta, double directMaximum, double indirectOffset, double indirectGrowth)
        {
            Orientation         o            = Orientation;
            bool                isHorizontal = o == Orientation.Horizontal;
            UIElementCollection children     = Children;
            double              directLength = 0.0;
            double              itemCount    = 0.0;
            double              itemLength   = isHorizontal ? ItemWidth : ItemHeight;

            if (AlignLastItems && !itemLength.IsNaN())
            {
                // Length is easy to calculate in this case
                itemCount    = Math.Floor(directMaximum / itemLength);
                directLength = itemCount * itemLength;
            }
            else
            {
                // Make first pass to calculate the slack space
                itemCount = lineEnd - lineStart;
                for (int index = lineStart; index < lineEnd; index++)
                {
                    // Get the size of the element
                    UIElement    element     = children[index];
                    OrientedSize elementSize = new OrientedSize(o, element.DesiredSize.Width, element.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;

                    // Update total length
                    directLength += directGrowth;
                }
            }

            // Determine slack
            double directSlack      = directMaximum - directLength;
            double directSlackSlice = directSlack / (itemCount + 1.0);
            double directOffset     = directSlackSlice;

            // Make second pass to arrange items
            for (int index = lineStart; index < lineEnd; index++)
            {
                // Get the size of the element
                UIElement    element     = children[index];
                OrientedSize elementSize = new OrientedSize(o, element.DesiredSize.Width, element.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
                Rect bounds = isHorizontal ?
                              new Rect(directOffset, indirectOffset, directGrowth, indirectGrowth) :
                              new Rect(indirectOffset, directOffset, indirectGrowth, directGrowth);
                element.Arrange(bounds);

                // Update offset for next time
                directOffset += directGrowth + directSlackSlice;
            }
        }
示例#16
0
 public static OrientedSize ExpandTo(this OrientedSize size, OrientedSize value)
 {
     return(SizeUtils.ExpandTo(size, value));
 }
示例#17
0
 public static double HalfIndirect(this OrientedSize orientedSize)
 {
     return(SizeUtils.HalfIndirect(orientedSize));
 }
示例#18
0
        protected override Size MeasureOverride(Size constraint)
        {
            // Variables tracking the size of the current line, the total size
            // measured so far, and the maximum size available to fill.  Note
            // that the line might represent a row or a column depending on the
            // orientation.
            Orientation  o           = Orientation;
            OrientedSize lineSize    = new OrientedSize(o);
            OrientedSize totalSize   = new OrientedSize(o);
            OrientedSize maximumSize = new OrientedSize(o, constraint.Width, constraint.Height);

            // Determine the constraints for individual items
            double itemWidth      = ItemWidth;
            double itemHeight     = ItemHeight;
            bool   hasFixedWidth  = !itemWidth.IsNaN();
            bool   hasFixedHeight = !itemHeight.IsNaN();
            Size   itemSize       = new Size(
                hasFixedWidth ? itemWidth : constraint.Width,
                hasFixedHeight ? itemHeight : constraint.Height);

            // Measure each of the Children
            foreach (UIElement element in Children)
            {
                // Determine the size of the element
                element.Measure(itemSize);
                OrientedSize elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (NumericExtensions.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Update the total size with the direct and indirect growth
                    // for the current line
                    totalSize.Direct    = Math.Max(lineSize.Direct, totalSize.Direct);
                    totalSize.Indirect += lineSize.Indirect;

                    // Move the element to a new line
                    lineSize = elementSize;

                    // If the current element is larger than the maximum size,
                    // place it on a line by itself
                    if (NumericExtensions.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Update the total size for the line occupied by this
                        // single element
                        totalSize.Direct    = Math.Max(elementSize.Direct, totalSize.Direct);
                        totalSize.Indirect += elementSize.Indirect;

                        // Move to a new line
                        lineSize = new OrientedSize(o);
                    }
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Update the total size with the elements on the last line
            totalSize.Direct    = Math.Max(lineSize.Direct, totalSize.Direct);
            totalSize.Indirect += lineSize.Indirect;

            // Return the total size required as an un-oriented quantity
            return(new Size(totalSize.Width, totalSize.Height));
        }
示例#19
0
        /// <summary>
        /// Arranges and sizes the
        /// <see cref="T:System.Windows.Controls.WrapPanel" /> control and its
        /// child elements.
        /// </summary>
        /// <param name="finalSize">
        /// The area within the parent that the
        /// <see cref="T:System.Windows.Controls.WrapPanel" /> should use
        /// arrange itself and its children.
        /// </param>
        /// <returns>
        /// The actual size used by the
        /// <see cref="T:System.Windows.Controls.WrapPanel" />.
        /// </returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            // Variables tracking the size of the current line, and the maximum
            // size available to fill.  Note that the line might represent a row
            // or a column depending on the orientation.
            Orientation  o           = Orientation;
            OrientedSize lineSize    = new OrientedSize(o);
            OrientedSize maximumSize = new OrientedSize(o, finalSize.Width, finalSize.Height);

            // Determine the constraints for individual items
            double itemWidth      = ItemWidth;
            double itemHeight     = ItemHeight;
            bool   hasFixedWidth  = !itemWidth.IsNaN();
            bool   hasFixedHeight = !itemHeight.IsNaN();
            double indirectOffset = 0;
            double?directDelta    = (o == Orientation.Horizontal) ?
                                    (hasFixedWidth ? (double?)itemWidth : null) :
                                    (hasFixedHeight ? (double?)itemHeight : null);

            // Measure each of the Children.  We will process the elements one
            // line at a time, just like during measure, but we will wait until
            // we've completed an entire line of elements before arranging them.
            // The lineStart and lineEnd variables track the size of the
            // currently arranged line.
            UIElementCollection children = Children;
            int count     = children.Count;
            int lineStart = 0;

            for (int lineEnd = 0; lineEnd < count; lineEnd++)
            {
                UIElement element = children[lineEnd];

                // Get the size of the element
                OrientedSize elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (NumericExtensions.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Then we just completed a line and we should arrange it
                    ArrangeLine(lineStart, lineEnd, directDelta, indirectOffset, lineSize.Indirect);

                    // Move the current element to a new line
                    indirectOffset += lineSize.Indirect;
                    lineSize        = elementSize;

                    // If the current element is larger than the maximum size
                    if (NumericExtensions.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Arrange the element as a single line
                        ArrangeLine(lineEnd, ++lineEnd, directDelta, indirectOffset, elementSize.Indirect);

                        // Move to a new line
                        indirectOffset += lineSize.Indirect;
                        lineSize        = new OrientedSize(o);
                    }

                    // Advance the start index to a new line after arranging
                    lineStart = lineEnd;
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Arrange any elements on the last line
            if (lineStart < count)
            {
                ArrangeLine(lineStart, count, directDelta, indirectOffset, lineSize.Indirect);
            }

            return(finalSize);
        }
示例#20
0
文件: SizeUtils.cs 项目: Egaros/lib
 public static double GetIndirect(Size size, Orientation orientation)
 {
     return(OrientedSize.GetIndirect(size, orientation));
 }
示例#21
0
文件: SizeUtils.cs 项目: Egaros/lib
 public static double HalfIndirect(OrientedSize orientedSize)
 {
     return(orientedSize.Indirect / 2.0);
 }
示例#22
0
        protected override Size MeasureOverride(Size constraint)
        {
            // Variables tracking the size of the current line, the total size
            // measured so far, and the maximum size available to fill.  Note
            // that the line might represent a row or a column depending on the
            // orientation.
            Orientation o = Orientation;
            OrientedSize lineSize = new OrientedSize(o);
            OrientedSize totalSize = new OrientedSize(o);
            OrientedSize maximumSize = new OrientedSize(o, constraint.Width, constraint.Height);

            // Determine the constraints for individual items
            double itemWidth = ItemWidth;
            double itemHeight = ItemHeight;
            bool hasFixedWidth = !itemWidth.IsNaN();
            bool hasFixedHeight = !itemHeight.IsNaN();
            Size itemSize = new Size(
                hasFixedWidth ? itemWidth : constraint.Width,
                hasFixedHeight ? itemHeight : constraint.Height);

            // Measure each of the Children
            foreach (UIElement element in Children)
            {
                // Determine the size of the element
                element.Measure(itemSize);
                OrientedSize elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (NumericExtensions.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Update the total size with the direct and indirect growth
                    // for the current line
                    totalSize.Direct = Math.Max(lineSize.Direct, totalSize.Direct);
                    totalSize.Indirect += lineSize.Indirect;

                    // Move the element to a new line
                    lineSize = elementSize;

                    // If the current element is larger than the maximum size,
                    // place it on a line by itself
                    if (NumericExtensions.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Update the total size for the line occupied by this
                        // single element
                        totalSize.Direct = Math.Max(elementSize.Direct, totalSize.Direct);
                        totalSize.Indirect += elementSize.Indirect;

                        // Move to a new line
                        lineSize = new OrientedSize(o);
                    }
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Update the total size with the elements on the last line
            totalSize.Direct = Math.Max(lineSize.Direct, totalSize.Direct);
            totalSize.Indirect += lineSize.Indirect;

            // Return the total size required as an un-oriented quantity
            return new Size(totalSize.Width, totalSize.Height);
        }
示例#23
0
        /// <summary>
        /// Arranges the child elements of the panel.
        /// </summary>
        /// <param name="finalSize">
        /// The final size.
        /// </param>
        /// <returns>
        /// Returns the size required by the panel.
        /// </returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            var o           = this.Orientation;
            var lineSize    = new OrientedSize(o);
            var maximumSize = new OrientedSize(o, finalSize.Width, finalSize.Height);

            // Determine the constraints for individual items
            double itemWidth      = this.ItemWidth;
            double itemHeight     = this.ItemHeight;
            bool   hasFixedWidth  = !itemWidth.IsNaN();
            bool   hasFixedHeight = !itemHeight.IsNaN();
            double indirectOffset = 0;
            var    directDelta    = (o == Orientation.Horizontal)
                                  ? (hasFixedWidth ? (double?)itemWidth : null)
                                  : (hasFixedHeight ? (double?)itemHeight : null);

            var children  = this.Children;
            int count     = children.Count;
            int lineStart = 0;

            for (var lineEnd = 0; lineEnd < count; lineEnd++)
            {
                var element = children[lineEnd];

                // Get the size of the element
                var elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (MathHelper.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Then we just completed a line and we should arrange it
                    this.ArrangeLine(lineStart, lineEnd, directDelta, indirectOffset, lineSize.Indirect);

                    // Move the current element to a new line
                    indirectOffset += lineSize.Indirect;
                    lineSize        = elementSize;

                    // If the current element is larger than the maximum size
                    if (MathHelper.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Arrange the element as a single line
                        this.ArrangeLine(lineEnd, ++lineEnd, directDelta, indirectOffset, elementSize.Indirect);

                        // Move to a new line
                        indirectOffset += lineSize.Indirect;
                        lineSize        = new OrientedSize(o);
                    }

                    // Advance the start index to a new line after arranging
                    lineStart = lineEnd;
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Arrange any elements on the last line
            if (lineStart < count)
            {
                this.ArrangeLine(lineStart, count, directDelta, indirectOffset, lineSize.Indirect);
            }

            return(finalSize);
        }
示例#24
0
        private static OrientedSize MeasureChild(UIElement child, OrientedSize childConstraint)
        {
            child.Measure(childConstraint.Size);

            return(child.DesiredSize.AsOriented(childConstraint.Orientation));
        }
示例#25
0
 public static OrientedSize WrapSize(this OrientedSize self, Size itemSize)
 {
     return(self.WrapSize(itemSize.AsOriented(self.Orientation)));
 }
示例#26
0
        private OrientedSize ProcessSpacingAndOverflow(double spacing, OrientedSize desiredOriented, OrientedSize availableOriented, out bool isHiddenChanged)
        {
            var childrenCount = Panel.Elements.Count;
            var orientation   = Panel.Orientation;

            var target = availableOriented.Direct;

            isHiddenChanged = false;

            // Current length is greater than available and we have no possibility to stretch down -> mark elements as hidden
            var current = 0.0;
            var visible = 0.0;

            var hasHiddenChildren    = false;
            var visibleChildrenCount = 0;

            if (desiredOriented.Direct.IsGreaterThan(availableOriented.Direct))
            {
                var stretchOverflow = FlexElementCollection.Mount(FlexElements.Capacity);

                try
                {
                    // Process Pinned Flexible
                    for (var index = 0; index < childrenCount; index++)
                    {
                        var flexElement = FlexElements[index];

                        if (CanPinStretch(flexElement) == false)
                        {
                            continue;
                        }

                        flexElement.StretchDirection = FlexStretchDirection.Shrink;

                        stretchOverflow.Add(flexElement);

                        Panel.SetIsHidden(Panel.Elements[index], false);
                    }

                    // Process Pinned
                    for (var index = 0; index < childrenCount; index++)
                    {
                        var child = Panel.Elements[index];

                        if (child.Visibility == Visibility.Collapsed)
                        {
                            continue;
                        }

                        var flexElement = FlexElements[index];

                        if (CanPin(flexElement) == false)
                        {
                            continue;
                        }

                        current += flexElement.ActualLength;
                        current += spacing;

                        visible = current;

                        Panel.SetIsHidden(Panel.Elements[index], false);
                    }

                    // Process Hide
                    for (var index = 0; index < childrenCount; index++)
                    {
                        var child = Panel.Elements[index];

                        if (child.Visibility == Visibility.Collapsed)
                        {
                            continue;
                        }

                        visibleChildrenCount++;

                        var flexElement = FlexElements[index];

                        if (CanPin(flexElement))
                        {
                            continue;
                        }

                        current += flexElement.ActualLength;

                        if (CanHide(flexElement) == false)
                        {
                            isHiddenChanged |= Panel.GetIsHidden(child);
                            Panel.SetIsHidden(child, false);

                            current += spacing;

                            visible = current;
                            continue;
                        }

                        var isOverflowed = current.IsGreaterThan(target, XamlConstants.LayoutComparisonPrecision);

                        current += spacing;

                        if (isOverflowed == false)
                        {
                            visible = current;
                        }

                        isHiddenChanged   |= Panel.GetIsHidden(child) != isOverflowed;
                        hasHiddenChildren |= isOverflowed;

                        Panel.SetIsHidden(child, isOverflowed);
                    }

                    if (visibleChildrenCount > 0)
                    {
                        visible = visible - spacing;
                    }

                    Panel.HasHiddenChildren = hasHiddenChildren;

                    // Stretch Pinned
                    if (visible.IsGreaterThan(availableOriented.Direct) && stretchOverflow.Count > 0)
                    {
                        var currentPinStretch = stretchOverflow.Actual;
                        var pinStretchTarget  = (currentPinStretch - (visible - availableOriented.Direct)).Clamp(0, availableOriented.Direct);
                        var pinStretchDesired = stretchOverflow.Stretch(FlexStretch.Fill, pinStretchTarget, FlexDistributor.Equalizer);

                        if (pinStretchDesired < currentPinStretch)
                        {
                            var pinStretchIndex = 0;

                            for (var index = 0; index < childrenCount; index++)
                            {
                                var flexElement = FlexElements[index];

                                if (CanPinStretch(flexElement))
                                {
                                    FlexElements[index] = stretchOverflow[pinStretchIndex++].WithStretchDirection(FlexStretchDirection.Shrink).WithMaxLength(flexElement.ActualLength);
                                }
                                else
                                {
                                    FlexElements[index] = FlexElements[index].WithStretchDirection(FlexStretchDirection.Shrink).WithShrinkPriority(short.MaxValue);
                                }
                            }

                            FinalMeasureItems(availableOriented, spacing, true);

                            return(OrientedSize.Create(orientation, availableOriented.Direct, desiredOriented.Indirect));
                        }
                    }
                }
                finally
                {
                    FlexElementCollection.Release(stretchOverflow);
                }

                return(OrientedSize.Create(orientation, visible.Clamp(0, availableOriented.Direct), desiredOriented.Indirect));
            }

            for (var index = 0; index < childrenCount; index++)
            {
                var flexElement = FlexElements[index];
                var child       = Panel.Elements[index];

                if (child.Visibility == Visibility.Collapsed)
                {
                    continue;
                }

                visibleChildrenCount++;

                current += flexElement.ActualLength;
                current += spacing;

                Panel.SetIsHidden(Panel.Elements[index], false);
            }

            Panel.HasHiddenChildren = false;
            visible = Math.Max(0, current);

            if (visibleChildrenCount > 0)
            {
                visible = visible - spacing;
            }

            return(OrientedSize.Create(orientation, visible.Clamp(0, availableOriented.Direct), desiredOriented.Indirect));
        }
示例#27
0
        private Size ArrangeCoreImpl(Size finalSize)
        {
            var flexPanel         = Panel;
            var flexPanelEx       = Panel as IFlexPanelEx;
            var allowMeasure      = flexPanelEx?.AllowMeasureInArrange ?? false;
            var orientation       = flexPanel.Orientation;
            var useLayoutRounding = flexPanel.UseLayoutRounding;
            var spacing           = GetRoundSpacing(flexPanel.Spacing, useLayoutRounding);

            for (var index = 0; index < flexPanel.Elements.Count; index++)
            {
                FlexElements[index] = FlexElements[index].WithUIElement(flexPanel.Elements[index], orientation);
            }

            var currentFlexElements = FlexElementCollection.Mount(FlexElements.Capacity);

            try
            {
                FlexElements.CopyTo(currentFlexElements);

                while (true)
                {
                    var nextArrangePass    = false;
                    var size               = new OrientedSize(orientation);
                    var spacingDelta       = 0.0;
                    var finalOriented      = finalSize.AsOriented(orientation);
                    var finalIndirect      = finalOriented.Indirect;
                    var currentPoint       = new OrientedPoint(orientation);
                    var childFinalOriented = new OrientedSize(orientation);

                    // Stretch
                    Stretch(currentFlexElements, spacing, finalOriented.Direct, true);

                    for (var index = 0; index < flexPanel.Elements.Count; index++)
                    {
                        var child       = flexPanel.Elements[index];
                        var flexElement = currentFlexElements[index];

                        if (child.Visibility == Visibility.Collapsed)
                        {
                            continue;
                        }

                        if (flexPanel.GetIsHidden(child))
                        {
                            child.Arrange(XamlConstants.ZeroRect);
                            flexElement.ActualLength   = 0.0;
                            currentFlexElements[index] = flexElement;

                            continue;
                        }

                        var desiredOriented = child.DesiredSize.AsOriented(orientation);

                        childFinalOriented.Direct   = flexElement.ActualLength;
                        childFinalOriented.Indirect = Math.Max(finalIndirect, desiredOriented.Indirect);

                        // Arrange Child
                        var rect = new Rect(XamlConstants.ZeroPoint, childFinalOriented.Size).Offset(currentPoint);

                        if (useLayoutRounding)
                        {
                            rect = rect.LayoutRound(RoundingMode.MidPointFromZero);
                        }

                        if (_measureInfinite && allowMeasure && desiredOriented.Direct.IsGreaterThan(childFinalOriented.Direct))
                        {
                            var remeasureOriented = desiredOriented;

                            remeasureOriented.ChangeDirect(childFinalOriented.Direct);

                            child.Measure(remeasureOriented.Size);
                        }

                        child.Arrange(rect);

                        var arrangeSize = GetActualArrangeSize(child);

                        if (arrangeSize.IsEmpty == false)
                        {
                            rect.Width  = arrangeSize.Width;
                            rect.Height = arrangeSize.Height;
                        }

                        var finalChildDirect = rect.Size().AsOriented(orientation).Direct;

                        if (IsArrangeFixed(flexElement) == false && finalChildDirect.IsLessThan(childFinalOriented.Direct))
                        {
                            var length = finalChildDirect;

                            flexElement.SetLengths(length, length, length, length);
                            currentFlexElements[index] = flexElement;
                            nextArrangePass            = true;

                            break;
                        }

                        if (useLayoutRounding)
                        {
                            var rectSize = rect.Size().AsOriented(orientation);

                            flexElement.ActualLength = rectSize.Direct;
                            currentPoint.Direct      = Math.Max(0, (currentPoint.Direct + rectSize.Direct + spacing).LayoutRound(orientation, RoundingMode.MidPointFromZero));
                        }
                        else
                        {
                            var rectSize = rect.Size().AsOriented(orientation);

                            flexElement.ActualLength = rectSize.Direct;
                            currentPoint.Direct      = Math.Max(0, currentPoint.Direct + rectSize.Direct + spacing);
                        }

                        currentFlexElements[index] = flexElement;

                        spacingDelta += spacing;

                        size = size.StackSize(childFinalOriented);
                    }

                    if (nextArrangePass)
                    {
                        continue;
                    }

                    if (spacingDelta.Equals(0.0) == false)
                    {
                        size.Direct = Math.Max(0, size.Direct + spacingDelta - spacing);
                    }

                    var result = finalSize;

                    if (orientation == Orientation.Horizontal)
                    {
                        result.Width = flexPanel.ShouldFill(Orientation.Horizontal) ? finalSize.Width : Math.Min(finalSize.Width, size.Width);
                    }
                    else
                    {
                        result.Height = flexPanel.ShouldFill(Orientation.Vertical) ? finalSize.Height : Math.Min(finalSize.Height, size.Height);
                    }

                    return(result);
                }
            }
            finally
            {
                FlexElementCollection.Release(currentFlexElements);
            }
        }
示例#28
0
        private OrientedSize MeasureItems(Size availableSize, out OrientedSize fixedSize, out OrientedSize flexibleSize)
        {
            var stretch              = Panel.Stretch;
            var orientation          = Panel.Orientation;
            var children             = Panel.Elements;
            var childrenCount        = children.Count;
            var oriented             = availableSize.AsOriented(orientation);
            var fixedChildConstraint = oriented.Clone.ChangeDirect(double.PositiveInfinity);
            var starChildConstraint  = oriented.Clone.ChangeDirect(0);
            var fixedResult          = new OrientedSize(orientation);
            var starValue            = 0.0;

            FlexElements.EnsureCount(childrenCount);

            for (var index = 0; index < childrenCount; index++)
            {
                var flexElement = Panel.GetFlexElement(children[index]).WithOrientation(orientation);

                if (flexElement.IsStar)
                {
                    starValue += flexElement.Length.Value;
                }

                FlexElements[index] = flexElement;
            }

            // None Stretch
            if (stretch == FlexStretch.None)
            {
                for (var index = 0; index < childrenCount; index++)
                {
                    var flexElement     = FlexElements[index];
                    var child           = children[index];
                    var childConstraint = GetChildConstraint(flexElement, fixedChildConstraint, starChildConstraint);

                    // Stack child size
                    var size = MeasureChild(child, childConstraint);

                    flexElement         = flexElement.WithUIElement(child, orientation);
                    size.Direct         = flexElement.DesiredLength;
                    fixedResult         = fixedResult.StackSize(size);
                    FlexElements[index] = flexElement;
                }

                fixedSize    = fixedResult;
                flexibleSize = new OrientedSize(orientation);

                return(fixedResult);
            }

            // Fixed size children
            for (var index = 0; index < childrenCount; index++)
            {
                var flexElement = FlexElements[index];

                if (flexElement.IsStar)
                {
                    continue;
                }

                var child           = children[index];
                var childConstraint = GetChildConstraint(flexElement, fixedChildConstraint, starChildConstraint);

                // Stack child size
                var size = MeasureChild(child, childConstraint);

                flexElement         = flexElement.WithUIElement(child, orientation);
                size.Direct         = flexElement.DesiredLength;
                fixedResult         = fixedResult.StackSize(size);
                FlexElements[index] = flexElement;
            }

            fixedSize    = fixedResult;
            flexibleSize = new OrientedSize(orientation);
            starChildConstraint.ChangeDirect(FlexUtils.CalcStarValue(oriented.Direct, fixedResult.Direct, starValue));

            // Star size children
            var flexibleResult = new OrientedSize(orientation);

            for (var index = 0; index < childrenCount; index++)
            {
                var flexElement = FlexElements[index];

                if (flexElement.IsFixed)
                {
                    continue;
                }

                var child           = children[index];
                var childConstraint = GetChildConstraint(flexElement, fixedChildConstraint, starChildConstraint);

                // Stack child size
                var size = MeasureChild(child, childConstraint);

                flexElement         = flexElement.WithUIElement(child, orientation);
                size.Direct         = flexElement.DesiredLength;
                flexibleResult      = flexibleResult.StackSize(size);
                FlexElements[index] = flexElement.WithUIElement(child, orientation);
            }

            flexibleSize = flexibleResult;

            return(fixedResult.StackSize(flexibleResult));
        }
示例#29
0
        /// <summary>
        /// Arranges the content of a WrapPanel element.
        /// </summary>
        /// <param name="finalSize">
        /// The Size that this element should use to arrange its child elements.
        /// </param>
        /// <returns>
        /// The arranged size of this WrapPanel element and its children.
        /// </returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            // Variables tracking the size of the current line, and the maximum
            // size available to fill.  Note that the line might represent a row
            // or a column depending on the orientation.
            Orientation o = Orientation;
            OrientedSize lineSize = new OrientedSize(o);
            OrientedSize maximumSize = new OrientedSize(o, finalSize.Width, finalSize.Height);

            // Determine the constraints for individual items
            double itemWidth = ItemWidth;
            double itemHeight = ItemHeight;
            bool hasFixedWidth = !itemWidth.IsNaN();
            bool hasFixedHeight = !itemHeight.IsNaN();
            double indirectOffset = 0;
            double? directDelta = (o == Orientation.Horizontal) ?
                (hasFixedWidth ? (double?) itemWidth : null) :
                (hasFixedHeight ? (double?) itemHeight : null);

            // Measure each of the Children.  We will process the elements one
            // line at a time, just like during measure, but we will wait until
            // we've completed an entire line of elements before arranging them.
            // The lineStart and lineEnd variables track the size of the
            // currently arranged line.
            UIElementCollection children = Children;
            int count = children.Count;
            int lineStart = 0;
            for (int lineEnd = 0; lineEnd < count; lineEnd++)
            {
                UIElement element = children[lineEnd];

                // Get the size of the element
                OrientedSize elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (NumericExtensions.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Then we just completed a line and we should arrange it
                    ArrangeLine(lineStart, lineEnd, directDelta, indirectOffset, lineSize.Indirect);

                    // Move the current element to a new line
                    indirectOffset += lineSize.Indirect;
                    lineSize = elementSize;

                    // If the current element is larger than the maximum size
                    if (NumericExtensions.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Arrange the element as a single line
                        ArrangeLine(lineEnd, ++lineEnd, directDelta, indirectOffset, elementSize.Indirect);

                        // Move to a new line
                        indirectOffset += lineSize.Indirect;
                        lineSize = new OrientedSize(o);
                    }

                    // Advance the start index to a new line after arranging
                    lineStart = lineEnd;
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Arrange any elements on the last line
            if (lineStart < count)
            {
                ArrangeLine(lineStart, count, directDelta, indirectOffset, lineSize.Indirect);
            }

            return finalSize;
        }
示例#30
0
 public static OrientedSize WrapSize(this OrientedSize self, OrientedSize itemSize)
 {
     self.Direct    = Math.Max(itemSize.Direct, self.Direct);
     self.Indirect += itemSize.Indirect;
     return(self);
 }
示例#31
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(int lineStart, int lineEnd, double? directDelta, double indirectOffset, double indirectGrowth)
        {
            double directOffset = 0.0;

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

            UIElementCollection children = Children;
            for (int index = lineStart; index < lineEnd; index++)
            {
                // Get the size of the element
                UIElement element = children[index];
                OrientedSize elementSize = new OrientedSize(o, element.DesiredSize.Width, element.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
                Rect bounds = isHorizontal ?
                    new Rect(directOffset, indirectOffset, directGrowth, indirectGrowth) :
                    new Rect(indirectOffset, directOffset, indirectGrowth, directGrowth);
                element.Arrange(bounds);

                directOffset += directGrowth;
            }
        }
示例#32
0
        /// <summary>
        /// Measures the child elements of the panel.
        /// </summary>
        /// <param name="constraint">
        /// The size available for child elements.
        /// </param>
        /// <returns>
        /// Returns the size required by the panel.
        /// </returns>
        protected override Size MeasureOverride(Size constraint)
        {
            var o           = this.Orientation;
            var lineSize    = new OrientedSize(o);
            var totalSize   = new OrientedSize(o);
            var maximumSize = new OrientedSize(o, constraint.Width, constraint.Height);

            // Determine the constraints for individual items
            double itemWidth      = this.ItemWidth;
            double itemHeight     = this.ItemHeight;
            bool   hasFixedWidth  = !double.IsNaN(itemWidth);
            bool   hasFixedHeight = !double.IsNaN(itemHeight);
            var    itemSize       = new Size(
                hasFixedWidth ? itemWidth : constraint.Width,
                hasFixedHeight ? itemHeight : constraint.Height);

            // Measure each of the children
            foreach (var element in this.Children)
            {
                // Determine the size of the element
                element.Measure(itemSize);
                var elementSize = new OrientedSize(
                    o,
                    hasFixedWidth ? itemWidth : element.DesiredSize.Width,
                    hasFixedHeight ? itemHeight : element.DesiredSize.Height);

                // If this element falls of the edge of the line
                if (MathHelper.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
                {
                    // Update the total size with the direct and indirect growth for the current line
                    totalSize.Direct    = Math.Max(lineSize.Direct, totalSize.Direct);
                    totalSize.Indirect += lineSize.Indirect;

                    // Move the element to a new line
                    lineSize = elementSize;

                    // If the current element is larger than the maximum size, place it on a line by itself
                    if (MathHelper.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
                    {
                        // Update the total size for the line occupied by this single element
                        totalSize.Direct    = Math.Max(elementSize.Direct, totalSize.Direct);
                        totalSize.Indirect += elementSize.Indirect;

                        // Move to a new line
                        lineSize = new OrientedSize(o);
                    }
                }
                else
                {
                    // Otherwise just add the element to the end of the line
                    lineSize.Direct  += elementSize.Direct;
                    lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
                }
            }

            // Update the total size with the elements on the last line
            totalSize.Direct    = Math.Max(lineSize.Direct, totalSize.Direct);
            totalSize.Indirect += lineSize.Indirect;

            // Return the total size required as an un-oriented quantity
            return(new Size(totalSize.Width, totalSize.Height));
        }