Return to Snippet

Revision: 18763
at October 7, 2009 19:16 by ingebretsen


Updated Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace JustifyingWrapPanelTest
{
    public class StretchWrapPanel : Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
            double lineWidth = 0;
            double lineHeight = 0;
            double totalWidth = 0;
            double totalHeight = 0;

            Size asBigAsYouWant = new Size(double.PositiveInfinity, double.PositiveInfinity);

            foreach (UIElement element in this.Children)
            {
                element.Measure(asBigAsYouWant);
                Size itemSize = GetItemDesiredSize(element);

                // reset the line if we run out of room
                if ((this.Children[this.Children.Count - 1].Equals(element)) || (lineWidth + GetItemDesiredSize(this.Children[this.Children.IndexOf(element) + 1]).Width > availableSize.Width))
                {
                    if (lineWidth > totalWidth) totalWidth = lineWidth;
                    lineWidth = 0;

                    totalHeight += lineHeight;
                    lineHeight = 0;
                }

                lineWidth += itemSize.Width;

                // take the tallest item in the line as our lineHeight
                if (itemSize.Height > lineHeight) lineHeight = itemSize.Height;
            }


            return new Size(availableSize.Width, totalHeight);
        }


        protected override Size ArrangeOverride(Size finalSize)
        {
            int lineCount = 0;
            double lineWidth = 0;
            double lineHeight = 0;

            double top = 0;
            double left = 0;
            double width = 0;
            double height = 0;
            double gap = 0;

            for (int u = 0; u <= this.Children.Count - 1; u++)
            {
                UIElement curr = this.Children[u];
                Size currSize = GetItemDesiredSize(curr);
                lineCount++;

                lineWidth = lineWidth + currSize.Width;
                lineHeight = Math.Max(lineHeight, currSize.Height);

                bool isLast = this.Children[this.Children.Count - 1].Equals(curr);

                if (isLast || (lineWidth + GetItemDesiredSize(this.Children[u + 1]).Width) >= finalSize.Width)
                {
                    gap = isLast ? gap : lineCount <= 1 ? 0 : (finalSize.Width - lineWidth) / (lineCount - 1);
                    for (int i = (u - lineCount) + 1; i <= u; i++)
                    {
                        UIElement element = this.Children[i];
                        width = GetItemDesiredSize(element).Width;
                        height = GetItemDesiredSize(element).Height;

                        element.Arrange(new Rect(left, top, width, height));

                        left += (width + gap);
                    }

                    top += lineHeight;
                    left = 0;

                    // reset our line markers
                    lineWidth = 0;
                    lineHeight = 0;
                    lineCount = 0;
                }
            }

            return finalSize;
        }

        private Size GetItemDesiredSize(UIElement element)
        {
            Size itemSize = new Size();
            itemSize.Width = double.IsInfinity(element.DesiredSize.Width) ? 0 : element.DesiredSize.Width;
            itemSize.Height = double.IsInfinity(element.DesiredSize.Height) ? 0 : element.DesiredSize.Height;
            return itemSize;
        }

    }
}

Revision: 18762
at October 7, 2009 19:15 by ingebretsen


Initial Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace JustifyingWrapPanelTest
{
    public class StretchWrapPanel : Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
            double lineWidth = 0;
            double lineHeight = 0;
            double totalWidth = 0;
            double totalHeight = 0;

            Size asBigAsYouWant = new Size(double.PositiveInfinity, double.PositiveInfinity);

            foreach (UIElement element in this.Children)
            {
                element.Measure(asBigAsYouWant);
                Size itemSize = GetItemDesiredSize(element);

                // reset the line if we run out of room
                if ((this.Children[this.Children.Count - 1].Equals(element)) || (lineWidth + GetItemDesiredSize(this.Children[this.Children.IndexOf(element) + 1]).Width > availableSize.Width))
                {
                    if (lineWidth > totalWidth) totalWidth = lineWidth;
                    lineWidth = 0;

                    totalHeight += lineHeight;
                    lineHeight = 0;
                }

                lineWidth += itemSize.Width;

                // take the tallest item in the line as our lineHeight
                if (itemSize.Height > lineHeight) lineHeight = itemSize.Height;
            }


            return new Size(availableSize.Width, totalHeight);
        }


        protected override Size ArrangeOverride(Size finalSize)
        {
            int lineCount = 0;
            double lineWidth = 0;
            double lineHeight = 0;

            double top = 0;
            double left = 0;
            double width = 0;
            double height = 0;
            double gap = 0;

            for (int u = 0; u <= this.Children.Count - 1; u++)
            {
                UIElement curr = this.Children[u];
                Size currSize = GetItemDesiredSize(curr);
                lineCount++;

                lineWidth = lineWidth + currSize.Width;
                lineHeight = Math.Max(lineHeight, currSize.Height);

                bool isLast = this.Children[this.Children.Count - 1].Equals(curr);

                if (isLast || (lineWidth + GetItemDesiredSize(this.Children[u + 1]).Width) >= finalSize.Width)
                {
                    gap = isLast ? gap : lineCount <= 1 ? 0 : (finalSize.Width - lineWidth) / (lineCount - 1);
                    for (int i = (u - lineCount) + 1; i <= u; i++)
                    {
                        UIElement element = this.Children[i];
                        width = GetItemDesiredSize(element).Width;
                        height = GetItemDesiredSize(element).Height;

                        element.Arrange(new Rect(left, top, width, height));

                        left += (width + gap);
                    }

                    top += lineHeight;
                    left = 0;


                    // reset our line markers
                    lineWidth = 0;
                    lineHeight = 0;
                    lineCount = 0;

                }





                //Size itemSize = GetItemDesiredSize(element);
                //lineWidth += itemSize.Width;
                //lineHeight = Math.Max(lineHeight, itemSize.Height);

                //if (this.Children[this.Children.Count- 1].Equals(element) || (lineWidth + this.Children[u+1].DesiredSize.Width) >= finalSize.Width) 
                //{
                //    // process the line
                //    left = 0;

                //    //if (lineCount > 1)
                //    {
                //        double gap = (finalSize.Width - lineWidth) / (lineCount);
                //        for (int i = startIndex; i < startIndex + lineCount; i++)
                //        {
                //            UIElement next = this.Children[i];
                //            width = next.DesiredSize.Width;
                //            height = lineHeight;

                //            next.Arrange(new Rect(left, top, width, height));

                //            left += (width + gap);
                //        }

                //    }
                //    //else
                //    //{
                //    //    width = element.DesiredSize.Width;
                //    //    height = lineHeight;
                //    //    element.Arrange(new Rect(left, top, width, height));
                //    //}

                //    // reset the line counts
                //    top += lineHeight;
                //    lineWidth = 0;
                //    lineHeight = 0;
                //    startIndex = startIndex + lineCount;
                //    lineCount = 0;

                //}
                //else
                //{
                //    // TODO update line height

                //    // TODO update the lineWidth
                //}

                //lineCount++;

            }

            return finalSize;
        }

        private Size GetItemDesiredSize(UIElement element)
        {
            Size itemSize = new Size();
            itemSize.Width = double.IsInfinity(element.DesiredSize.Width) ? 0 : element.DesiredSize.Width;
            itemSize.Height = double.IsInfinity(element.DesiredSize.Height) ? 0 : element.DesiredSize.Height;
            return itemSize;
        }

    }
}

Initial URL


Initial Description
This is a flowpanel that automatically justifies it's lines so that the elements are justified.

Initial Title
StrechFlowPanel

Initial Tags


Initial Language
C#