Exemplo n.º 1
0
        private void TerminateLastRow(BlockProcessor state, GridTableState tableState, Table gridTable, bool isLastRow)
        {
            var      columns    = tableState.ColumnSlices;
            TableRow currentRow = null;

            foreach (var columnSlice in columns)
            {
                if (columnSlice.CurrentCell != null)
                {
                    if (currentRow == null)
                    {
                        currentRow = new TableRow();
                    }
                    currentRow.Add(columnSlice.CurrentCell);
                    columnSlice.BlockProcessor.Close(columnSlice.CurrentCell);
                }

                // Renew the block parser processor (or reset it for the last row)
                if (columnSlice.BlockProcessor != null)
                {
                    columnSlice.BlockProcessor.ReleaseChild();
                    columnSlice.BlockProcessor = isLastRow ? null : state.CreateChild();
                }

                // Create or erase the cell
                if (isLastRow || columnSlice.CurrentColumnSpan == 0)
                {
                    // We don't need the cell anymore if we have a last row
                    // Or the cell has a columnspan == 0
                    columnSlice.CurrentCell = null;
                }
                else
                {
                    // Else we can create a new cell
                    columnSlice.CurrentCell = new TableCell(this)
                    {
                        ColumnSpan = columnSlice.CurrentColumnSpan
                    };

                    if (columnSlice.BlockProcessor == null)
                    {
                        columnSlice.BlockProcessor = state.CreateChild();
                    }

                    // Ensure that the BlockParser is aware that the TableCell is the top-level container
                    columnSlice.BlockProcessor.Open(columnSlice.CurrentCell);
                }
            }

            if (currentRow != null)
            {
                gridTable.Add(currentRow);
            }
        }
Exemplo n.º 2
0
        private static void Undo(BlockProcessor processor, GridTableState tableState, Table gridTable)
        {
            var parser = processor.Parsers.FindExact <ParagraphBlockParser>();
            // Discard the grid table
            var parent = gridTable.Parent;

            processor.Discard(gridTable);
            var paragraphBlock = new ParagraphBlock(parser)
            {
                Lines = tableState.Lines,
            };

            parent.Add(paragraphBlock);
            processor.Open(paragraphBlock);
        }
Exemplo n.º 3
0
        private static void TerminateCurrentRow(BlockProcessor processor, GridTableState tableState, Table gridTable, bool isLastRow)
        {
            var      columns    = tableState.ColumnSlices;
            TableRow currentRow = null;

            for (int i = 0; i < columns.Count; i++)
            {
                var columnSlice = columns[i];
                if (columnSlice.CurrentCell != null)
                {
                    if (currentRow == null)
                    {
                        currentRow = new TableRow();
                    }
                    // If this cell does not already belong to a row
                    if (columnSlice.CurrentCell.Parent == null)
                    {
                        currentRow.Add(columnSlice.CurrentCell);
                    }
                    // If the cell is not going to span through to the next row
                    if (columnSlice.CurrentCell.AllowClose)
                    {
                        columnSlice.BlockProcessor.Close(columnSlice.CurrentCell);
                    }
                }

                // Renew the block parser processor (or reset it for the last row)
                if (columnSlice.BlockProcessor != null && (columnSlice.CurrentCell == null || columnSlice.CurrentCell.AllowClose))
                {
                    columnSlice.BlockProcessor.ReleaseChild();
                    columnSlice.BlockProcessor = isLastRow ? null : processor.CreateChild();
                }

                // Create or erase the cell
                if (isLastRow || columnSlice.CurrentColumnSpan == 0 || (columnSlice.CurrentCell != null && columnSlice.CurrentCell.AllowClose))
                {
                    // We don't need the cell anymore if we have a last row
                    // Or the cell has a columnspan == 0
                    // And the cell does not have to be kept open to span rows
                    columnSlice.CurrentCell = null;
                }
            }

            if (currentRow != null && currentRow.Count > 0)
            {
                gridTable.Add(currentRow);
            }
        }
Exemplo n.º 4
0
        private BlockState HandleNewRow(BlockProcessor processor, GridTableState tableState, Table gridTable)
        {
            var columns = tableState.ColumnSlices !;

            SetRowSpanState(columns, processor.Line, out bool isHeaderRow, out bool hasRowSpan);
            SetColumnSpanState(columns, processor.Line);
            TerminateCurrentRow(processor, tableState, gridTable, false);
            if (isHeaderRow)
            {
                for (int i = 0; i < gridTable.Count; i++)
                {
                    var row = (TableRow)gridTable[i];
                    row.IsHeader = true;
                }
            }
            tableState.StartRowGroup = gridTable.Count;
            if (hasRowSpan)
            {
                HandleContents(processor, tableState, gridTable);
            }
            return(BlockState.ContinueDiscard);
        }
Exemplo n.º 5
0
        private BlockState HandleContents(BlockProcessor processor, GridTableState tableState, Table gridTable)
        {
            var isRowLine = processor.CurrentChar == '+';
            var columns   = tableState.ColumnSlices;
            var line      = processor.Line;

            SetColumnSpanState(columns, line);
            if (!isRowLine && !CanContinueRow(columns))
            {
                TerminateCurrentRow(processor, tableState, gridTable, false);
            }
            for (int i = 0; i < columns.Count;)
            {
                var columnSlice     = columns[i];
                var nextColumnIndex = i + columnSlice.CurrentColumnSpan;
                // If the span is 0, we exit
                if (nextColumnIndex == i)
                {
                    break;
                }
                var nextColumn = nextColumnIndex < columns.Count ? columns[nextColumnIndex] : null;

                var sliceForCell = line;
                sliceForCell.Start = line.Start + columnSlice.Start + 1;
                if (nextColumn != null)
                {
                    sliceForCell.End = line.Start + nextColumn.Start - 1;
                }
                else
                {
                    var columnEnd     = columns[columns.Count - 1].End;
                    var columnEndChar = line.PeekCharExtra(columnEnd);
                    // If there is a `|` (or a `+` in the case that we are dealing with a row line
                    // with spanned contents) exactly at the expected end of the table row, we cut the line
                    // otherwise we allow to have the last cell of a row to be open for longer cell content
                    if (columnEndChar == '|' || (isRowLine && columnEndChar == '+'))
                    {
                        sliceForCell.End = line.Start + columnEnd - 1;
                    }
                    else if (line.PeekCharExtra(line.End) == '|')
                    {
                        sliceForCell.End = line.End - 1;
                    }
                }
                sliceForCell.TrimEnd();

                if (!isRowLine || !IsRowSeperator(sliceForCell))
                {
                    if (columnSlice.CurrentCell == null)
                    {
                        columnSlice.CurrentCell = new TableCell(this)
                        {
                            ColumnSpan  = columnSlice.CurrentColumnSpan,
                            ColumnIndex = i
                        };

                        if (columnSlice.BlockProcessor == null)
                        {
                            columnSlice.BlockProcessor = processor.CreateChild();
                        }

                        // Ensure that the BlockParser is aware that the TableCell is the top-level container
                        columnSlice.BlockProcessor.Open(columnSlice.CurrentCell);
                    }
                    // Process the content of the cell
                    columnSlice.BlockProcessor.LineIndex = processor.LineIndex;
                    columnSlice.BlockProcessor.ProcessLine(sliceForCell);
                }

                // Go to next column
                i = nextColumnIndex;
            }
            return(BlockState.ContinueDiscard);
        }
Exemplo n.º 6
0
        public override BlockState TryOpen(BlockProcessor processor)
        {
            // A grid table cannot start more than an indent
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            var            line       = processor.Line;
            GridTableState tableState = null;

            // Match the first row that should be of the minimal form: +---------------
            var c         = line.CurrentChar;
            var lineStart = line.Start;

            while (c == '+')
            {
                var columnStart = line.Start;
                line.NextChar();
                line.TrimStart();

                // if we have reached the end of the line, exit
                c = line.CurrentChar;
                if (c == 0)
                {
                    break;
                }

                // Parse a column alignment
                TableColumnAlign?columnAlign;
                if (!TableHelper.ParseColumnHeader(ref line, '-', out columnAlign))
                {
                    return(BlockState.None);
                }

                tableState = tableState ?? new GridTableState {
                    Start = processor.Start, ExpectRow = true
                };
                tableState.AddColumn(columnStart - lineStart, line.Start - lineStart, columnAlign);

                c = line.CurrentChar;
            }

            if (c != 0 || tableState == null)
            {
                return(BlockState.None);
            }
            // Store the line (if we need later to build a ParagraphBlock because the GridTable was in fact invalid)
            tableState.AddLine(ref processor.Line);
            var table = new Table(this);

            table.SetData(typeof(GridTableState), tableState);

            // Calculate the total width of all columns
            int totalWidth = 0;

            foreach (var columnSlice in tableState.ColumnSlices)
            {
                totalWidth += columnSlice.End - columnSlice.Start - 1;
            }

            // Store the column width and alignment
            foreach (var columnSlice in tableState.ColumnSlices)
            {
                var columnDefinition = new TableColumnDefinition
                {
                    // Column width proportional to the total width
                    Width     = (float)(columnSlice.End - columnSlice.Start - 1) * 100.0f / totalWidth,
                    Alignment = columnSlice.Align
                };
                table.ColumnDefinitions.Add(columnDefinition);
            }

            processor.NewBlocks.Push(table);

            return(BlockState.ContinueDiscard);
        }
Exemplo n.º 7
0
        private BlockState ParseRowSeparator(BlockProcessor state, GridTableState tableState, Table gridTable)
        {
            // A grid table must start with a line like this:
            // + ------------- + ------------ + ---------------------------------------- +
            // Spaces are optional

            var  line          = state.Line;
            var  c             = line.CurrentChar;
            bool isFirst       = true;
            var  delimiterChar = '\0';

            while (true)
            {
                if (c == '+')
                {
                    line.NextChar();
                    if (line.IsEmptyOrWhitespace())
                    {
                        if (isFirst)
                        {
                            return(BlockState.None);
                        }
                        break;
                    }

                    TableColumnAlign align;
                    if (TableHelper.ParseColumnHeaderDetect(ref line, ref delimiterChar, out align))
                    {
                        isFirst = false;
                        c       = line.CurrentChar;
                        continue;
                    }
                }

                // If we have any other characters, this is an invalid line
                return(BlockState.None);
            }

            // If we have an header row
            var isHeader = delimiterChar == '=';

            // Terminate the current row
            TerminateLastRow(state, tableState, gridTable, false);

            // If we had a header row separator, we can mark all rows since last row separator
            // to be header rows
            if (isHeader)
            {
                for (int i = tableState.StartRowGroup; i < gridTable.Count; i++)
                {
                    var row = (TableRow)gridTable[i];
                    row.IsHeader = true;
                }
            }

            // Makr the next start row group continue on the next row
            tableState.StartRowGroup = gridTable.Count;

            // We don't keep the line
            return(BlockState.ContinueDiscard);
        }
Exemplo n.º 8
0
        public override BlockState TryOpen(BlockProcessor processor)
        {
            // A grid table cannot start more than an indent
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            var line = processor.Line;

            // A grid table must start with a line like this:
            // + ------------- + ------------ + ---------------------------------------- +
            // Spaces are optional

            GridTableState tableState    = null;
            var            c             = line.CurrentChar;
            var            startPosition = processor.Start;

            while (true)
            {
                if (c == '+')
                {
                    var startCharacter = line.Start;
                    line.NextChar();
                    if (line.IsEmptyOrWhitespace())
                    {
                        if (tableState == null)
                        {
                            return(BlockState.None);
                        }
                        break;
                    }

                    TableColumnAlign align;
                    if (TableHelper.ParseColumnHeader(ref line, '-', out align))
                    {
                        if (tableState == null)
                        {
                            tableState = new GridTableState()
                            {
                                Start     = processor.Start,
                                ExpectRow = true,
                            };
                        }
                        tableState.AddColumn(startCharacter - startPosition, line.Start - 1 - startPosition, align);

                        c = line.CurrentChar;
                        continue;
                    }
                }

                // If we have any other characters, this is an invalid line
                return(BlockState.None);
            }

            // Store the line (if we need later to build a ParagraphBlock because the GridTable was in fact invalid)
            tableState.AddLine(ref processor.Line);

            // Create the grid table
            var table = new Table(this);

            table.SetData(typeof(GridTableState), tableState);


            // Calculate the total width of all columns
            int totalWidth = 0;

            foreach (var columnSlice in tableState.ColumnSlices)
            {
                totalWidth += columnSlice.End - columnSlice.Start;
            }

            // Store the column width and alignment
            foreach (var columnSlice in tableState.ColumnSlices)
            {
                var columnDefinition = new TableColumnDefinition
                {
                    // Column width proportional to the total width
                    Width     = (float)(columnSlice.End - columnSlice.Start) * 100.0f / totalWidth,
                    Alignment = columnSlice.Align,
                };
                table.ColumnDefinitions.Add(columnDefinition);
            }

            processor.NewBlocks.Push(table);

            return(BlockState.ContinueDiscard);
        }