/// <summary>
        /// Gets the constraints from the given placement or an automatic constraints in case
        /// the placement has not table constraints.
        /// </summary>
        /// <param name="placement"></param>
        /// <param name="lastConstraints"></param>
        /// <returns></returns>
        private TableLayoutConstraints GetConstrains(VCItemPlacement placement, TableLayoutConstraints lastConstraints)
        {
            TableLayoutConstraints constraints = placement.Constraints as TableLayoutConstraints;

            if (constraints != null)
            {
                return(constraints);
            }

            // Auto generate constraints
            if (lastConstraints == null)
            {
                return(new TableLayoutConstraints(0, 0));
            }
            else
            {
                int col = lastConstraints.ColumnIndex + lastConstraints.ColumnSpan;

                // Next col ok?
                if (col < colFills.Length)
                {
                    return(new TableLayoutConstraints(col, lastConstraints.RowIndex));
                }

                // Next row ok?
                int row = lastConstraints.RowIndex + lastConstraints.RowSpan;
                if (row < rowsFills.Length)
                {
                    return(new TableLayoutConstraints(0, row));
                }

                // Overflow, restart
                return(new TableLayoutConstraints(0, 0));
            }
        }
        /// <summary>
        /// Set the locations of the given placements.
        /// </summary>
        /// <param name="placements">All placements that must be layed out.</param>
        /// <param name="controlSize">The size of the control (in virtual units)</param>
        public virtual void Layout(ICollection <VCItemPlacement> placements, SizeF controlSize)
        {
            if (placements.Count > 0)
            {
                // Calculate maximum width and total height
                int[] maxColWidth  = new int[colFills.Length];
                int[] maxRowHeight = new int[rowsFills.Length];

                TableLayoutConstraints lastConstraints = null;
                foreach (VCItemPlacement placement in placements)
                {
                    TableLayoutConstraints constraints = GetConstrains(placement, lastConstraints);
                    lastConstraints = constraints;

                    Size itemSz = placement.Item.PreferredSize + constraints.CellPadding.Size;
                    DistributeSize(itemSz.Width, constraints.ColumnIndex, constraints.ColumnSpan, colFills, maxColWidth);
                    DistributeSize(itemSz.Height, constraints.RowIndex, constraints.RowSpan, rowsFills, maxRowHeight);
                }

                // Calculate preferred size
                this.preferredSize = this.size = new Size(MathUtil.Sum(maxColWidth) + padding.Horizontal, MathUtil.Sum(maxRowHeight) + padding.Vertical);

                // Calculate full size (expand applicable columns and rows)
                if (size.Width < controlSize.Width)
                {
                    float extra = controlSize.Width - size.Width;
                    for (int i = 0; i < maxColWidth.Length; i++)
                    {
                        maxColWidth[i] += (int)(colFills[i] * extra);
                    }
                }
                if (size.Height < controlSize.Height)
                {
                    float extra = controlSize.Height - size.Height;
                    for (int i = 0; i < maxRowHeight.Length; i++)
                    {
                        maxRowHeight[i] += (int)(rowsFills[i] * extra);
                    }
                }
                this.size = new Size(MathUtil.Sum(maxColWidth) + padding.Horizontal, MathUtil.Sum(maxRowHeight) + padding.Vertical);

                // Calculate distance for dealing with table alignment (not cell alignment!)
                int dx = padding.Left;
                switch (hAlignment)
                {
                case HorizontalAlignment.Center:
                    dx += (controlSize.Width > size.Width) ? (int)((controlSize.Width - size.Width) / 2) : 0;
                    break;

                case HorizontalAlignment.Right:
                    dx += (controlSize.Width > size.Width) ? (int)(controlSize.Width - size.Width) : 0;
                    break;
                }

                int dy = padding.Top;
                switch (vAlignment)
                {
                case VerticalAlignment.Middle:
                    dy += (controlSize.Height > size.Height) ? (int)((controlSize.Height - size.Height) / 2) : 0;
                    break;

                case VerticalAlignment.Bottom:
                    dy += (controlSize.Height > size.Height) ? (int)(controlSize.Height - size.Height) : 0;
                    break;
                }


                // Calculate item bounds
                lastConstraints = null;
                foreach (VCItemPlacement placement in placements)
                {
                    TableLayoutConstraints constraints = GetConstrains(placement, lastConstraints);
                    lastConstraints = constraints;
                    Padding cellPadding = constraints.CellPadding;
                    Size    maxItemSize = new Size(
                        MathUtil.Sum(maxColWidth, constraints.ColumnIndex, constraints.ColumnSpan) - cellPadding.Horizontal,
                        MathUtil.Sum(maxRowHeight, constraints.RowIndex, constraints.RowSpan) - cellPadding.Vertical);

                    Size itemSize = placement.Item.PreferredSize;
                    if ((constraints.Fill & FillDirection.Horizontal) != 0)
                    {
                        itemSize.Width = maxItemSize.Width;
                    }
                    if ((constraints.Fill & FillDirection.Vertical) != 0)
                    {
                        itemSize.Height = maxItemSize.Height;
                    }

                    int x = dx + MathUtil.Sum(maxColWidth, 0, constraints.ColumnIndex) + cellPadding.Left;
                    int y = dy + MathUtil.Sum(maxRowHeight, 0, constraints.RowIndex) + cellPadding.Top;
                    switch (constraints.ItemAlignment)
                    {
                    case ContentAlignment.TopCenter:
                    case ContentAlignment.MiddleCenter:
                    case ContentAlignment.BottomCenter:
                        x += (maxItemSize.Width - itemSize.Width) / 2;
                        break;

                    case ContentAlignment.TopRight:
                    case ContentAlignment.MiddleRight:
                    case ContentAlignment.BottomRight:
                        x += maxItemSize.Width - itemSize.Width;
                        break;
                    }
                    switch (constraints.ItemAlignment)
                    {
                    case ContentAlignment.MiddleLeft:
                    case ContentAlignment.MiddleCenter:
                    case ContentAlignment.MiddleRight:
                        y += (maxItemSize.Height - itemSize.Height) / 2;
                        break;

                    case ContentAlignment.BottomLeft:
                    case ContentAlignment.BottomCenter:
                    case ContentAlignment.BottomRight:
                        y += maxItemSize.Height - itemSize.Height;
                        break;
                    }

                    Rectangle bounds = new Rectangle(new Point(x, y), itemSize);
                    placement.Bounds = bounds;
                }
            }
            else
            {
                this.preferredSize = Size.Empty;
                this.size          = Size.Empty;
            }
        }