Пример #1
0
            /// <summary>
            /// Calculates grid width and individual column widths.
            /// </summary>
            public Tuple <nfloat, nfloat[]> CalculateAbsoluteColumnWidth(Grid grid)
            {
                var absoluteColumnWidth = new nfloat[this.ColumnDefinitions.Count()];

                var visibleCols    = Cells.Where(c => c.IncludeInAutoWidthSizeCalcs).Select(c => c.Position.Column).Distinct();
                int numVisibleCols = visibleCols.Count();

                // Calculate full height of grid
                nfloat totalWidth;

                var minColWidth = new nfloat[this.ColumnDefinitions.Count()];

                if (grid.AutoWidth)
                {
                    LogLine($"CalculateAbsoluteColumnWidth AutoWidth");

                    var maxColWidth = new nfloat[this.ColumnDefinitions.Count()];
                    int maxColSpan  = grid.CurrentLayout.cells.Max(c => c.Position.ColumnSpan);

                    for (int colSpan = 1; colSpan <= maxColSpan; colSpan++)
                    {
                        for (int row = 0; row < this.RowDefinitions.Count(); row++)
                        {
                            for (int col = 0; col < this.ColumnDefinitions.Count(); col++)
                            {
                                var colDef = this.ColumnDefinitions[col];
                                var cell   = FindCell(col, row);
                                if (cell == null)
                                {
                                    continue;
                                }
                                if (cell.IncludeInAutoWidthSizeCalcs && cell.Position.ColumnSpan == colSpan)
                                {
                                    nfloat cellWidth = colDef.SizeType == SizeType.Auto && cell.Position.Horizontal == Alignment.Stretched
                                        ? 0f
                                        : colDef.SizeType == SizeType.Fixed
                                            ? colDef.Size
                                            : cell.AutoSizeSize.Width;
                                    cellWidth += cell.Position.Margin.Width();
                                    LogLine($"   {cell.Position} cellWidth={cellWidth}");

                                    if (colSpan == 1)
                                    {
                                        maxColWidth[col] = NMath.Max(maxColWidth[col], cellWidth);
                                    }
                                    else
                                    {
                                        // Need to ensure the other columns we span have enough
                                        // width to account for this spanned column.
                                        nfloat spanWidth = 0;
                                        for (int col2 = cell.Position.Column; col2 < cell.Position.Column + colSpan; col2++)
                                        {
                                            spanWidth += maxColWidth[col2];
                                        }
                                        if (cellWidth > spanWidth)
                                        {
                                            bool hasZeroColWidth = false;
                                            for (int col2 = cell.Position.Column; col2 < cell.Position.Column + colSpan; col2++)
                                            {
                                                if (maxColWidth[col2] == 0)
                                                {
                                                    hasZeroColWidth = true;
                                                }
                                            }
                                            if (hasZeroColWidth)
                                            {
                                                // Cop out: just size equally
                                                for (int col2 = cell.Position.Column; col2 < cell.Position.Column + colSpan; col2++)
                                                {
                                                    minColWidth[col2] = maxColWidth[col2] = cellWidth / colSpan;
                                                }
                                            }
                                            else
                                            {
                                                // Increase size of columns proportionatly
                                                nfloat colWidthUpsizeRation = cellWidth / spanWidth;
                                                for (int col2 = cell.Position.Column; col2 < cell.Position.Column + colSpan; col2++)
                                                {
                                                    maxColWidth[col2] *= colWidthUpsizeRation;
                                                    minColWidth[col2]  = maxColWidth[col2];
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

#if ENABLE_DEBUG_LOG
                    LogLine("minColWidth:");
                    for (int col = 0; col < this.ColumnDefinitions.Count(); col++)
                    {
                        LogLine($"   col {col}: {minColWidth[col]}");
                    }
#endif

                    totalWidth = maxColWidth.Sum(w => (float)w);
                    int numCols = maxColWidth.Count(w => w > 0);
                    totalWidth += numVisibleCols * Spacing + Padding.Left + Padding.Right;
                }
                else
                {
                    totalWidth = grid.Frame.Width;
                }

                // Track available col width available for percent-based sized roiws
                // Add width of fixed size cols
                nfloat fixedWidth = this.ColumnDefinitions.Where((d) => d.Size > 1).Select(d => d.Size).Sum();
                nfloat remaining  = totalWidth - fixedWidth;

                // Add width of auto sized columns
                for (int column = 0; column < this.ColumnDefinitions.Count(); column++)
                {
                    var definition = this.ColumnDefinitions.ElementAt(column);
                    if (definition.Size == -1)
                    {
                        var autoSizedCells = Cells.Where(c => c.Position.Column == column &&
                                                         c.Position.ColumnSpan == 1 && c.IncludeInAutoWidthSizeCalcs &&
                                                         c.Position.Horizontal != Alignment.Stretched);
                        if (autoSizedCells.Any())
                        {
                            nfloat colWidth = autoSizedCells.Max(c => c.AutoSizeSize.Width + c.Position.Margin.Width());
                            colWidth = NMath.Max(minColWidth[column], colWidth);
                            absoluteColumnWidth[column] = colWidth;
                            remaining -= colWidth;
                        }
                    }
                }

                // Add size of padding and spacing
                remaining -= this.Padding.Left + this.Padding.Right;
                remaining -= (numVisibleCols - 1) * this.Spacing;

                remaining = (nfloat)Math.Max(0, remaining);

                for (int column = 0; column < this.ColumnDefinitions.Count(); column++)
                {
                    var definition = this.ColumnDefinitions.ElementAt(column);
                    if (definition.Size != -1)
                    {
                        bool   includeCol = Cells.Where(c => c.Position.Column == column).Any(c => c.IncludeInAutoHeightSizeCalcs);
                        nfloat colWidth   = !includeCol ? 0 : definition.Size > 1 ? definition.Size : definition.Size * remaining;
                        absoluteColumnWidth[column] = NMath.Max(minColWidth[column], colWidth);
                    }
                }

                // In auto width mode, can now take into account absolute and auto sized
                // columns
                if (grid.AutoWidth)
                {
                    totalWidth = (nfloat)(
                        absoluteColumnWidth.Sum(w => w) +
                        Padding.Left + this.Padding.Right +
                        (numVisibleCols - 1) * this.Spacing
                        );
                }

                LogLine($"totalWidth={totalWidth}");

                return(new Tuple <nfloat, nfloat[]>(totalWidth, absoluteColumnWidth));
            }
Пример #2
0
            /// <summary>
            /// Calculates grid height and individual row heights.
            /// </summary>
            public Tuple <nfloat, nfloat[]> CalculateAbsoluteRowHeight(Grid grid)
            {
                var absoluteRowHeight = new nfloat[this.RowDefinitions.Count()];

                var visibleRows    = Cells.Where(c => c.IncludeInAutoHeightSizeCalcs).Select(c => c.Position.Row).Distinct();
                int numVisibleRows = visibleRows.Count();

                // Calculate full height of grid
                nfloat totalHeight;

                var minRowHeight = new nfloat[this.RowDefinitions.Count()];

                if (grid.AutoHeight)
                {
                    LogLine($"CalculateAbsoluteRowHeight AutoHeight");

                    var maxRowHeight = new nfloat[this.RowDefinitions.Count()];

                    int maxRowSpan = grid.CurrentLayout.cells.Max(c => c.Position.RowSpan);

                    for (int rowSpan = 1; rowSpan <= maxRowSpan; rowSpan++)
                    {
                        for (int col = 0; col < this.ColumnDefinitions.Count(); col++)
                        {
                            for (int row = 0; row < this.RowDefinitions.Count(); row++)
                            {
                                var rowDef = this.RowDefinitions[row];
                                var cell   = FindCell(col, row);
                                if (cell == null)
                                {
                                    continue;
                                }
                                if (cell.IncludeInAutoHeightSizeCalcs && cell.Position.RowSpan == rowSpan)
                                {
                                    nfloat cellHeight = rowDef.SizeType == SizeType.Auto && cell.Position.Vertical == Alignment.Stretched
                                        ? 0f
                                        : rowDef.SizeType == SizeType.Fixed
                                            ? rowDef.Size
                                            : cell.AutoSizeSize.Height;
                                    cellHeight += cell.Position.Margin.Height();
                                    LogLine($"   {cell.Position} cellHeight={cellHeight}");

                                    if (rowSpan == 1)
                                    {
                                        maxRowHeight[row] = NMath.Max(maxRowHeight[row], cellHeight);
                                    }
                                    else
                                    {
                                        // Need to ensure the other rows we span have enough
                                        // Height to account for this spanned column.
                                        nfloat spanHeight = 0;
                                        for (int row2 = cell.Position.Row; row2 < cell.Position.Row + rowSpan; row2++)
                                        {
                                            spanHeight += maxRowHeight[row2];
                                        }
                                        if (cellHeight > spanHeight)
                                        {
                                            bool hasZeroRowHeight = false;
                                            for (int row2 = cell.Position.Row; row2 < cell.Position.Row + rowSpan; row2++)
                                            {
                                                if (maxRowHeight[row2] == 0)
                                                {
                                                    hasZeroRowHeight = true;
                                                }
                                            }
                                            if (hasZeroRowHeight)
                                            {
                                                // Cop out: just size equally
                                                for (int row2 = cell.Position.Row; row2 < cell.Position.Row + rowSpan; row2++)
                                                {
                                                    minRowHeight[row2] = maxRowHeight[row2] = cellHeight / rowSpan;
                                                }
                                            }
                                            else
                                            {
                                                // Increase size of columns proportionatly
                                                nfloat colHeightUpsizeRation = cellHeight / spanHeight;
                                                for (int row2 = cell.Position.Row; row2 < cell.Position.Row + rowSpan; row2++)
                                                {
                                                    maxRowHeight[row2] *= colHeightUpsizeRation;
                                                    minRowHeight[row2]  = maxRowHeight[row2];
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

#if ENABLE_DEBUG_LOG
                    LogLine("minRowHeight:");
                    for (int row = 0; row < this.RowDefinitions.Count(); row++)
                    {
                        LogLine($"   row {row}: {minRowHeight[row]}");
                    }
#endif

                    totalHeight = maxRowHeight.Sum(h => (float)h);
                    int numRows = maxRowHeight.Count(h => h > 0);
                    totalHeight += (numVisibleRows - 1) * Spacing + Padding.Top + Padding.Bottom;
                }
                else
                {
                    totalHeight = grid.Frame.Height;
                }

                // Track available row Height available for percent-based sized roiws
                // Add Height of fixed size cols
                nfloat fixedHeight = this.RowDefinitions.Where((d) => d.Size > 1).Select(d => d.Size).Sum();
                nfloat remaining   = totalHeight - fixedHeight;

                // Add Height of auto sized rows
                for (int row = 0; row < this.RowDefinitions.Count(); row++)
                {
                    var definition = this.RowDefinitions.ElementAt(row);
                    if (definition.Size == -1)
                    {
                        var autoSizedCells = Cells.Where(c => c.Position.Row == row &&
                                                         c.Position.RowSpan == 1 && c.IncludeInAutoHeightSizeCalcs &&
                                                         c.Position.Vertical != Alignment.Stretched);
                        if (autoSizedCells.Any())
                        {
                            nfloat rowHeight = autoSizedCells.Max(c => c.AutoSizeSize.Height + c.Position.Margin.Height());
                            rowHeight = NMath.Max(minRowHeight[row], rowHeight);
                            absoluteRowHeight[row] = rowHeight;
                            remaining -= rowHeight;
                        }
                    }
                }

                // Add size of padding and spacing
                remaining -= this.Padding.Top + this.Padding.Bottom;
                remaining -= (numVisibleRows - 1) * this.Spacing;

                remaining = (nfloat)Math.Max(0, remaining);

                for (int row = 0; row < this.RowDefinitions.Count(); row++)
                {
                    var definition = this.RowDefinitions.ElementAt(row);
                    if (definition.Size != -1)
                    {
                        bool   includeRow = Cells.Where(c => c.Position.Row == row).Any(c => c.IncludeInAutoHeightSizeCalcs);
                        nfloat rowHeight  = !includeRow ? 0 : definition.Size > 1 ? definition.Size : definition.Size * remaining;
                        absoluteRowHeight[row] = NMath.Max(minRowHeight[row], rowHeight);
                    }
                }

                // In auto height mode, can now take into account absolute and auto sized
                // rows
                if (grid.AutoHeight)
                {
                    totalHeight = (nfloat)(
                        absoluteRowHeight.Sum(h => h) +
                        Padding.Top + this.Padding.Bottom +
                        (numVisibleRows - 1) * this.Spacing
                        );
                }

                LogLine($"totalHeight={totalHeight}");

                return(new Tuple <nfloat, nfloat[]>(totalHeight, absoluteRowHeight));
            }
Пример #3
0
        private nfloat[] CalculateColumnWidths(CGSize availableSpace)
        {
            var widthsByRow = new List<nfloat[]>();
            foreach (var row in rows)
            {
                for (var i = 0; i < widths.Length; i++)
                {
                    var width = widths[i];
                    var sizeRow = new nfloat[widths.Length];
                    switch (width.Style)
                    {
                        case TableWidthStyle.SizeToFit:
                            sizeRow[i] = (nfloat)row[i].SizeThatFits(new CGSize(nfloat.MaxValue, nfloat.MaxValue)).Width;
                            break;
                        case TableWidthStyle.Fixed:
                            sizeRow[i] = width.Value;
                            break;
                        case TableWidthStyle.Percentage:
                        case TableWidthStyle.Weight:
                            sizeRow[i] = 0;
                            break;
                    }
                    widthsByRow.Add(sizeRow);
                }
            }

            var calculatedWidths = new nfloat[widths.Length];
            for (var i = 0; i < widths.Length; i++)
            {
                calculatedWidths[i] = (nfloat)widthsByRow.Max(x => x[i]);
            }
            var bespokeWidth = calculatedWidths.Sum(x => x) + GetPaddingAndSpacingWidth();
            var remainingWidth = availableSpace.Width - bespokeWidth;
            var weightWidth = (nfloat)(remainingWidth - (nfloat)((nfloat)remainingWidth * widths.Where(x => x.Style == TableWidthStyle.Percentage).Sum(x => x.Value) / 100));
            var totalWeight = widths.Where(x => x.Style == TableWidthStyle.Weight).Sum(x => x.Value);
            var individualWeightWidth = weightWidth / totalWeight;
            var oddManOutWeightWidth = weightWidth - individualWeightWidth * totalWeight;

            var result = new nfloat[widths.Length];
            for (var i = 0; i < result.Length; i++)
            {
                var width = widths[i];
                switch (width.Style)
                {
                    case TableWidthStyle.Fixed:
                    case TableWidthStyle.SizeToFit:
                        result[i] = calculatedWidths[i];
                        break;
                    case TableWidthStyle.Percentage:
                        result[i] = (nfloat)((nfloat)width.Value / 100 * remainingWidth);
                        break;
                    case TableWidthStyle.Weight:
                        result[i] = individualWeightWidth * width.Value + oddManOutWeightWidth;
                        oddManOutWeightWidth = 0;
                        break;
                }
            }
            return result;
        }