/// <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; } }