Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I/6122: Handling spanned table cells in pasting scenarios #7226

Merged
merged 41 commits into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
830d58e
Move non-rectangular tests to own suite.
jodator May 15, 2020
1b1f1ff
Add tests for non-rectangular table selection.
jodator May 15, 2020
22cb400
Handle horizontal split when making rectangular selection.
jodator May 15, 2020
01002e8
Change the cut cells horizontally utility to single function.
jodator May 15, 2020
8161c72
Move cutCellsHorizontallyAt() to general utils.
jodator May 15, 2020
785c7c6
Fix tests scenarios.
jodator May 15, 2020
1b41a3f
Introduce cutCellsVerticallyAt() and use it pasting scenario.
jodator May 15, 2020
94f582b
Filter cells to check when splitting table.
jodator May 15, 2020
5ad37bf
Cut table cells to a selection bounding box before paste.
jodator May 18, 2020
c67e84d
Refactor utility methods.
jodator May 18, 2020
ed3ca18
Add docs to trimCellsToRectangularSelection().
jodator May 18, 2020
199a199
Add corner cases to the tests.
jodator May 18, 2020
27a73b7
Refactor the logic of splitting cells to a rectangular selection.
jodator May 18, 2020
e28fea1
Change order of jsdoc samples.
jodator May 18, 2020
57bb1f6
Fix tests case.
jodator May 18, 2020
8cfca04
Working corner case fix - last row/column in selection has all spanne…
jodator May 18, 2020
55ef343
Refactor last row/column adjustments.
jodator May 18, 2020
4c2aeb5
Add default values to internal methods.
jodator May 19, 2020
1f3c682
Add test cases for fixing broken table layout.
jodator May 19, 2020
ae90c74
Fix rowspan trim test case.
jodator May 19, 2020
486c16d
Crop pasted table to its established dimensions.
jodator May 19, 2020
6f7357e
Fixing pasted table layout should also occur when selection dimension…
jodator May 19, 2020
081d461
Use single crop pass for fixing pasted table layout and cropping past…
jodator May 19, 2020
6357693
Update internal comments for pasting table scenarios.
jodator May 19, 2020
2c1d1a4
Add test cases for updating selection dimension for multiple empty ro…
jodator May 19, 2020
40c45ad
Set table heading columns now splits overlapping cells vertically.
jodator May 19, 2020
2cba71f
Merge branch 'master' into i/6122-table-paste-spans
jodator May 19, 2020
0ff5a24
Add internal docs comments.
jodator May 19, 2020
d94af12
Some changes made during review to understand how it works.
niegowski May 19, 2020
6cfab6a
Use different wording for expandTableSize() params.
jodator May 20, 2020
ef95552
Revert row/column adjust algorithm to the previous form. Add more docs.
jodator May 20, 2020
12e386f
Add internal docs.
jodator May 20, 2020
eb01054
Add test for splitting table cells in one table cell selected.
jodator May 20, 2020
9c1a0fd
Remove #1,#2 from tests descriptions.
jodator May 20, 2020
fc32f40
Add missing test for removing "headingColumns" attribute.
jodator May 20, 2020
8176e23
Add tests for getVerticallyOverlappingCells() and getHorizontallyOver…
jodator May 20, 2020
aa9a854
Add better comment about fixing selection dimensions.
jodator May 20, 2020
7385fcb
Minor refactor.
jodator May 20, 2020
e50d908
Fix code style in tests.
jodator May 20, 2020
d6720f7
Fix above/blow wording in packages/ckeditor5-table/src/utils.js.
jodator May 20, 2020
b6e540f
Merge branch 'master' into i/6122-table-paste-spans
jodator May 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions packages/ckeditor5-table/src/commands/setheadercolumncommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import Command from '@ckeditor/ckeditor5-core/src/command';

import { findAncestor, isHeadingColumnCell, updateNumericAttribute } from './utils';
import { getColumnIndexes, getSelectionAffectedTableCells } from '../utils';
import { getColumnIndexes, getSelectionAffectedTableCells, getHorizontallyOverlappingCells, splitVertically } from '../utils';

/**
* The header column command.
Expand Down Expand Up @@ -69,12 +69,21 @@ export default class SetHeaderColumnCommand extends Command {

const model = this.editor.model;
const selectedCells = getSelectionAffectedTableCells( model.document.selection );
const { first, last } = getColumnIndexes( selectedCells );
const table = findAncestor( 'table', selectedCells[ 0 ] );

const { first, last } = getColumnIndexes( selectedCells );
const headingColumnsToSet = this.value ? first : last + 1;

model.change( writer => {
const table = findAncestor( 'table', selectedCells[ 0 ] );
if ( headingColumnsToSet ) {
// Changing heading columns requires to check if any of a heading cell is overlapping horizontally the table head.
// Any table cell that has a colspan attribute > 1 will not exceed the table head so we need to fix it in columns before.
const overlappingCells = getHorizontallyOverlappingCells( table, headingColumnsToSet );

for ( const { cell, column } of overlappingCells ) {
splitVertically( cell, column, headingColumnsToSet, writer );
}
}

updateNumericAttribute( 'headingColumns', headingColumnsToSet, table, writer, 0 );
} );
Expand Down
84 changes: 5 additions & 79 deletions packages/ckeditor5-table/src/commands/setheaderrowcommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@

import Command from '@ckeditor/ckeditor5-core/src/command';

import { createEmptyTableCell, findAncestor, updateNumericAttribute } from './utils';
import { getRowIndexes, getSelectionAffectedTableCells } from '../utils';
import TableWalker from '../tablewalker';
import { findAncestor, updateNumericAttribute } from './utils';
import { getVerticallyOverlappingCells, getRowIndexes, getSelectionAffectedTableCells, splitHorizontally } from '../utils';

/**
* The header row command.
Expand Down Expand Up @@ -77,9 +76,10 @@ export default class SetHeaderRowCommand extends Command {
if ( headingRowsToSet ) {
// Changing heading rows requires to check if any of a heading cell is overlapping vertically the table head.
// Any table cell that has a rowspan attribute > 1 will not exceed the table head so we need to fix it in rows below.
const cellsToSplit = getOverlappingCells( table, headingRowsToSet, currentHeadingRows );
const startRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;
const overlappingCells = getVerticallyOverlappingCells( table, headingRowsToSet, startRow );

for ( const cell of cellsToSplit ) {
for ( const { cell } of overlappingCells ) {
splitHorizontally( cell, headingRowsToSet, writer );
}
}
Expand All @@ -102,77 +102,3 @@ export default class SetHeaderRowCommand extends Command {
return !!headingRows && tableCell.parent.index < headingRows;
}
}

// Returns cells that span beyond the new heading section.
//
// @param {module:engine/model/element~Element} table The table to check.
// @param {Number} headingRowsToSet New heading rows attribute.
// @param {Number} currentHeadingRows Current heading rows attribute.
// @returns {Array.<module:engine/model/element~Element>}
function getOverlappingCells( table, headingRowsToSet, currentHeadingRows ) {
const cellsToSplit = [];

const startAnalysisRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;
// We're analyzing only when headingRowsToSet > 0.
const endAnalysisRow = headingRowsToSet - 1;

const tableWalker = new TableWalker( table, { startRow: startAnalysisRow, endRow: endAnalysisRow } );

for ( const { row, rowspan, cell } of tableWalker ) {
if ( rowspan > 1 && row + rowspan > headingRowsToSet ) {
cellsToSplit.push( cell );
}
}

return cellsToSplit;
}

// Splits the table cell horizontally.
//
// @param {module:engine/model/element~Element} tableCell
// @param {Number} headingRows
// @param {module:engine/model/writer~Writer} writer
function splitHorizontally( tableCell, headingRows, writer ) {
const tableRow = tableCell.parent;
const table = tableRow.parent;
const rowIndex = tableRow.index;

const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) );
const newRowspan = headingRows - rowIndex;

const attributes = {};

const spanToSet = rowspan - newRowspan;

if ( spanToSet > 1 ) {
attributes.rowspan = spanToSet;
}

const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 );

if ( colspan > 1 ) {
attributes.colspan = colspan;
}

const startRow = table.getChildIndex( tableRow );
const endRow = startRow + newRowspan;
const tableMap = [ ...new TableWalker( table, { startRow, endRow, includeSpanned: true } ) ];

let columnIndex;

for ( const { row, column, cell, cellIndex } of tableMap ) {
if ( cell === tableCell && columnIndex === undefined ) {
columnIndex = column;
}

if ( columnIndex !== undefined && columnIndex === column && row === endRow ) {
const tableRow = table.getChild( row );
const tableCellPosition = writer.createPositionAt( tableRow, cellIndex );

createEmptyTableCell( writer, tableCellPosition, attributes );
}
}

// Update the rowspan attribute after updating table.
updateNumericAttribute( 'rowspan', newRowspan, tableCell, writer );
}
Loading