Esempio n. 1
0
            // corner sase: if two cells end up on the same row (a.Row + a.RowSpan = b.Row + b.RowSpan),
            // bottom edges of their bounding boxes should be at the same level
            static void AdjustCellSizes(ICollection <TableCellRenderingCommand> commands, DynamicDictionary <int, float> rowBottomOffsets)
            {
                foreach (var command in commands)
                {
                    var lastRow = command.Cell.Row + command.Cell.RowSpan - 1;
                    var height  = rowBottomOffsets[lastRow] - command.Offset.Y;

                    command.Size   = new Size(command.Size.Width, height);
                    command.Offset = new Position(command.Offset.X, rowBottomOffsets[command.Cell.Row - 1]);
                }
            }
Esempio n. 2
0
            ICollection <TableCellRenderingCommand> GetRenderingCommands()
            {
                var rowBottomOffsets = new DynamicDictionary <int, float>();
                var commands         = new List <TableCellRenderingCommand>();

                var cellsToTry      = Cells.Where(x => x.Row + x.RowSpan - 1 >= CurrentRow);
                var currentRow      = CurrentRow;
                var maxRenderingRow = RowsCount;

                foreach (var cell in cellsToTry)
                {
                    // update position of previous row
                    if (cell.Row > currentRow)
                    {
                        rowBottomOffsets[currentRow] = Math.Max(rowBottomOffsets[currentRow], rowBottomOffsets[currentRow - 1]);

                        if (rowBottomOffsets[currentRow - 1] > availableSpace.Height + Size.Epsilon)
                        {
                            break;
                        }

                        foreach (var row in Enumerable.Range(cell.Row, cell.Row - currentRow))
                        {
                            rowBottomOffsets[row] = Math.Max(rowBottomOffsets[row - 1], rowBottomOffsets[row]);
                        }

                        currentRow = cell.Row;
                    }

                    // cell visibility optimizations
                    if (cell.Row > maxRenderingRow)
                    {
                        break;
                    }

                    // calculate cell position / size
                    var topOffset = rowBottomOffsets[cell.Row - 1];

                    var availableWidth    = GetCellWidth(cell);
                    var availableHeight   = availableSpace.Height - topOffset;
                    var availableCellSize = new Size(availableWidth, availableHeight);

                    var cellSize = cell.Measure(availableCellSize);

                    // corner case: if cell within the row is not fully rendered, do not attempt to render next row
                    if (cellSize.Type == SpacePlanType.PartialRender)
                    {
                        maxRenderingRow = Math.Min(maxRenderingRow, cell.Row + cell.RowSpan - 1);
                    }

                    // corner case: if cell within the row want to wrap to the next page, do not attempt to render this row
                    if (cellSize.Type == SpacePlanType.Wrap)
                    {
                        maxRenderingRow = Math.Min(maxRenderingRow, cell.Row - 1);
                        continue;
                    }

                    // update position of the last row that cell occupies
                    var bottomRow = cell.Row + cell.RowSpan - 1;
                    rowBottomOffsets[bottomRow] = Math.Max(rowBottomOffsets[bottomRow], topOffset + cellSize.Height);

                    // accept cell to be rendered
                    commands.Add(new TableCellRenderingCommand()
                    {
                        Cell        = cell,
                        Measurement = cellSize,
                        Size        = new Size(availableWidth, cellSize.Height),
                        Offset      = new Position(columnOffsets[cell.Column - 1], topOffset)
                    });
                }

                if (!commands.Any())
                {
                    return(commands);
                }

                var maxRow = commands.Select(x => x.Cell).Max(x => x.Row + x.RowSpan);

                foreach (var row in Enumerable.Range(CurrentRow, maxRow - CurrentRow))
                {
                    rowBottomOffsets[row] = Math.Max(rowBottomOffsets[row - 1], rowBottomOffsets[row]);
                }

                AdjustCellSizes(commands, rowBottomOffsets);

                // corner case: reject cell if other cells within the same row are rejected
                return(commands.Where(x => x.Cell.Row <= maxRenderingRow).ToList());
            }