void computeSize()
{
_sizeInvalid = false;
var cellCount = _cells.Count;
// Implicitly End the row for layout purposes.
if( cellCount > 0 && !_cells.Last().endRow )
{
endRow();
_implicitEndRow = true;
}
else
{
_implicitEndRow = false;
}
int columns = _columns, rows = _rows;
_columnWidth = ensureSize( _columnWidth, columns );
_rowHeight = ensureSize( _rowHeight, rows );
_columnMinWidth = ensureSize( _columnMinWidth, columns );
_rowMinHeight = ensureSize( _rowMinHeight, rows );
_columnPrefWidth = ensureSize( _columnPrefWidth, columns );
_rowPrefHeight = ensureSize( _rowPrefHeight, rows );
_expandWidth = ensureSize( _expandWidth, columns );
_expandHeight = ensureSize( _expandHeight, rows );
var spaceRightLast = 0f;
for( var i = 0; i < cellCount; i++ )
{
var cell = _cells[i];
int column = cell.column, row = cell.row, colspan = cell.colspan.Value;
// Collect rows that expand and colspan=1 columns that expand.
if( cell.expandY != 0 && _expandHeight[row] == 0 )
_expandHeight[row] = cell.expandY.Value;
if( colspan == 1 && cell.expandX != 0 && _expandWidth[column] == 0 )
_expandWidth[column] = cell.expandX.Value;
// Compute combined padding/spacing for cells.
// Spacing between elements isn't additive, the larger is used. Also, no spacing around edges.
cell.computedPadLeft = cell.padLeft.get( cell.element ) + ( column == 0 ? 0 : Math.Max( 0, cell.spaceLeft.get( cell.element ) - spaceRightLast ) );
cell.computedPadTop = cell.padTop.get( cell.element );
if( cell.cellAboveIndex != -1 )
{
var above = _cells[cell.cellAboveIndex];
cell.computedPadTop += Math.Max( 0, cell.spaceTop.get( cell.element ) - above.spaceBottom.get( cell.element ) );
}
var spaceRight = cell.spaceRight.get( cell.element );
cell.computedPadRight = cell.padRight.get( cell.element ) + ( ( column + colspan ) == columns ? 0 : spaceRight );
cell.computedPadBottom = cell.padBottom.get( cell.element ) + ( row == rows - 1 ? 0 : cell.spaceBottom.get( cell.element ) );
spaceRightLast = spaceRight;
// Determine minimum and preferred cell sizes.
var prefWidth = cell.prefWidth.get( cell.element );
var prefHeight = cell.prefHeight.get( cell.element );
var minWidth = cell.minWidth.get( cell.element );
var minHeight = cell.minHeight.get( cell.element );
var maxWidth = cell.maxWidth.get( cell.element );
var maxHeight = cell.maxHeight.get( cell.element );
if( prefWidth < minWidth )
prefWidth = minWidth;
if( prefHeight < minHeight )
prefHeight = minHeight;
if( maxWidth > 0 && prefWidth > maxWidth )
prefWidth = maxWidth;
if( maxHeight > 0 && prefHeight > maxHeight )
prefHeight = maxHeight;
if( colspan == 1 )
{
// Spanned column min and pref width is added later.
var hpadding = cell.computedPadLeft + cell.computedPadRight;
_columnPrefWidth[column] = Math.Max( _columnPrefWidth[column], prefWidth + hpadding );
_columnMinWidth[column] = Math.Max( _columnMinWidth[column], minWidth + hpadding );
}
float vpadding = cell.computedPadTop + cell.computedPadBottom;
_rowPrefHeight[row] = Math.Max( _rowPrefHeight[row], prefHeight + vpadding );
_rowMinHeight[row] = Math.Max( _rowMinHeight[row], minHeight + vpadding );
}
float uniformMinWidth = 0, uniformMinHeight = 0;
float uniformPrefWidth = 0, uniformPrefHeight = 0;
for( var i = 0; i < cellCount; i++ )
{
var c = _cells[i];
// Colspan with expand will expand all spanned columns if none of the spanned columns have expand.
var expandX = c.expandX.Value;
if( expandX != 0 )
{
int nn = c.column + c.colspan.Value;
for( int ii = c.column; ii < nn; ii++ )
if( _expandWidth[ii] != 0 )
goto outer;
for( int ii = c.column; ii < nn; ii++ )
_expandWidth[ii] = expandX;
}
outer:
{}
// Collect uniform sizes.
if( c.uniformX.HasValue && c.uniformX.Value && c.colspan == 1 )
{
float hpadding = c.computedPadLeft + c.computedPadRight;
uniformMinWidth = Math.Max( uniformMinWidth, _columnMinWidth[c.column] - hpadding );
uniformPrefWidth = Math.Max( uniformPrefWidth, _columnPrefWidth[c.column] - hpadding );
}
if( c.uniformY.HasValue && c.uniformY.Value )
{
float vpadding = c.computedPadTop + c.computedPadBottom;
uniformMinHeight = Math.Max( uniformMinHeight, _rowMinHeight[c.row] - vpadding );
uniformPrefHeight = Math.Max( uniformPrefHeight, _rowPrefHeight[c.row] - vpadding );
}
}
// Size uniform cells to the same width/height.
if( uniformPrefWidth > 0 || uniformPrefHeight > 0 )
{
for( var i = 0; i < cellCount; i++ )
{
var c = _cells[i];
if( uniformPrefWidth > 0 && c.uniformX.HasValue && c.uniformX.Value && c.colspan == 1 )
{
var hpadding = c.computedPadLeft + c.computedPadRight;
_columnMinWidth[c.column] = uniformMinWidth + hpadding;
_columnPrefWidth[c.column] = uniformPrefWidth + hpadding;
}
if( uniformPrefHeight > 0 && c.uniformY.HasValue && c.uniformY.Value )
{
var vpadding = c.computedPadTop + c.computedPadBottom;
_rowMinHeight[c.row] = uniformMinHeight + vpadding;
_rowPrefHeight[c.row] = uniformPrefHeight + vpadding;
}
}
}
// Distribute any additional min and pref width added by colspanned cells to the columns spanned.
for( var i = 0; i < cellCount; i++ )
{
var c = _cells[i];
var colspan = c.colspan.Value;
if( colspan == 1 )
continue;
var a = c.element;
var minWidth = c.minWidth.get( a );
var prefWidth = c.prefWidth.get( a );
var maxWidth = c.maxWidth.get( a );
if( prefWidth < minWidth )
prefWidth = minWidth;
if( maxWidth > 0 && prefWidth > maxWidth )
prefWidth = maxWidth;
float spannedMinWidth = -( c.computedPadLeft + c.computedPadRight ), spannedPrefWidth = spannedMinWidth;
var totalExpandWidth = 0f;
for( int ii = c.column, nn = ii + colspan; ii < nn; ii++ )
{
spannedMinWidth += _columnMinWidth[ii];
spannedPrefWidth += _columnPrefWidth[ii];
totalExpandWidth += _expandWidth[ii]; // Distribute extra space using expand, if any columns have expand.
}
var extraMinWidth = Math.Max( 0, minWidth - spannedMinWidth );
var extraPrefWidth = Math.Max( 0, prefWidth - spannedPrefWidth );
for( int ii = c.column, nn = ii + colspan; ii < nn; ii++ )
{
float ratio = totalExpandWidth == 0 ? 1f / colspan : _expandWidth[ii] / totalExpandWidth;
_columnMinWidth[ii] += extraMinWidth * ratio;
_columnPrefWidth[ii] += extraPrefWidth * ratio;
}
}
// Determine table min and pref size.
_tableMinWidth = 0;
_tableMinHeight = 0;
_tablePrefWidth = 0;
_tablePrefHeight = 0;
for( var i = 0; i < columns; i++ )
{
_tableMinWidth += _columnMinWidth[i];
_tablePrefWidth += _columnPrefWidth[i];
}
for( var i = 0; i < rows; i++ )
{
_tableMinHeight += _rowMinHeight[i];
_tablePrefHeight += Math.Max( _rowMinHeight[i], _rowPrefHeight[i] );
}
var hpadding_ = _padLeft.get( this ) + _padRight.get( this );
var vpadding_ = _padTop.get( this ) + _padBottom.get( this );
_tableMinWidth = _tableMinWidth + hpadding_;
_tableMinHeight = _tableMinHeight + vpadding_;
_tablePrefWidth = Math.Max( _tablePrefWidth + hpadding_, _tableMinWidth );
_tablePrefHeight = Math.Max( _tablePrefHeight + vpadding_, _tableMinHeight );
}