summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2015-03-05 11:10:06 +0200
committerPekka Hyvönen <pekka@vaadin.com>2015-03-06 10:16:45 +0200
commit3c84a54591d792b69a4d6d736714941edb1d818a (patch)
tree50580a4520e7943f60e599090a5dcc29dd9b3ec1
parent3abaa644d90c6460e6514b2e8207c178db01b52d (diff)
downloadvaadin-framework-3c84a54591d792b69a4d6d736714941edb1d818a.tar.gz
vaadin-framework-3c84a54591d792b69a4d6d736714941edb1d818a.zip
Dnd-reorder of spanned cells in grid header. (#16643)
Change-Id: I6f2decbbfb393922c4852f5b05ac0d10589ee512
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java101
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java168
2 files changed, 238 insertions, 31 deletions
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 432228be1e..07c888e936 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -3064,20 +3064,32 @@ public class Grid<T> extends ResizeComposite implements
@Override
public void onDrop() {
final int draggedColumnIndex = eventCell.getColumnIndex();
+ final int colspan = header.getRow(eventCell.getRowIndex())
+ .getCell(eventCell.getColumn()).getColspan();
if (latestColumnDropIndex != draggedColumnIndex
- && latestColumnDropIndex != (draggedColumnIndex + 1)) {
+ && latestColumnDropIndex != (draggedColumnIndex + colspan)) {
List<Column<?, T>> columns = getColumns();
- List<Column<?, T>> reordered = new ArrayList<Column<?, T>>(
- columns);
- Column<?, T> moved = reordered.remove(draggedColumnIndex);
+ List<Column<?, T>> reordered = new ArrayList<Column<?, T>>();
if (draggedColumnIndex < latestColumnDropIndex) {
- latestColumnDropIndex--;
+ reordered.addAll(columns.subList(0, draggedColumnIndex));
+ reordered.addAll(columns.subList(draggedColumnIndex
+ + colspan, latestColumnDropIndex));
+ reordered.addAll(columns.subList(draggedColumnIndex,
+ draggedColumnIndex + colspan));
+ reordered.addAll(columns.subList(latestColumnDropIndex,
+ columns.size()));
+ } else {
+ reordered.addAll(columns.subList(0, latestColumnDropIndex));
+ reordered.addAll(columns.subList(draggedColumnIndex,
+ draggedColumnIndex + colspan));
+ reordered.addAll(columns.subList(latestColumnDropIndex,
+ draggedColumnIndex));
+ reordered.addAll(columns.subList(draggedColumnIndex
+ + colspan, columns.size()));
}
- reordered.add(latestColumnDropIndex, moved);
reordered.remove(selectionColumn); // since setColumnOrder will
// add it anyway!
- @SuppressWarnings("unchecked")
Column<?, T>[] array = reordered.toArray(new Column[reordered
.size()]);
setColumnOrder(array);
@@ -3096,13 +3108,15 @@ public class Grid<T> extends ResizeComposite implements
.findRowContainer(focusedCell.getElement());
if (focusedCellColumnIndex == draggedColumnIndex) {
// move with the dragged column
+ final int adjustedDropIndex = latestColumnDropIndex > draggedColumnIndex ? latestColumnDropIndex - 1
+ : latestColumnDropIndex;
cellFocusHandler.setCellFocus(focusedRowIndex,
- latestColumnDropIndex, rowContainer);
+ adjustedDropIndex, rowContainer);
} else if (latestColumnDropIndex <= focusedCellColumnIndex
&& draggedColumnIndex > focusedCellColumnIndex) {
cellFocusHandler.setCellFocus(focusedRowIndex,
focusedCellColumnIndex + 1, rowContainer);
- } else if (latestColumnDropIndex >= focusedCellColumnIndex
+ } else if (latestColumnDropIndex > focusedCellColumnIndex
&& draggedColumnIndex < focusedCellColumnIndex) {
cellFocusHandler.setCellFocus(focusedRowIndex,
focusedCellColumnIndex - 1, rowContainer);
@@ -3171,12 +3185,17 @@ public class Grid<T> extends ResizeComposite implements
private void calculatePossibleDropPositions() {
possibleDropPositions.clear();
- final int draggedColumnIndex = eventCell.getColumnIndex();
- HashSet<Integer> unavailableColumnDropIndices = new HashSet<Integer>();
-
+ final int draggedCellIndex = eventCell.getColumnIndex();
+ final StaticRow<?> draggedCellRow = header.getRow(eventCell
+ .getRowIndex());
+ final int draggedCellRightIndex = draggedCellIndex
+ + draggedCellRow.getCell(eventCell.getColumn())
+ .getColspan();
final int frozenColumns = getSelectionAndFrozenColumnCount();
+ final Range draggedCellRange = Range.between(draggedCellIndex,
+ draggedCellRightIndex);
/*
- * If the dragged cell is adjacent to a spanned cell in any other
+ * If the dragged cell intersects with a spanned cell in any other
* header or footer row, then the drag is limited inside that
* spanned cell. The same rules apply: the cell can't be dropped
* inside another spanned cell. The left and right bounds keep track
@@ -3185,6 +3204,7 @@ public class Grid<T> extends ResizeComposite implements
int leftBound = -1;
int rightBound = getColumnCount() + 1;
+ final HashSet<Integer> unavailableColumnDropIndices = new HashSet<Integer>();
final List<StaticRow<?>> rows = new ArrayList<StaticRow<?>>();
rows.addAll(header.getRows());
rows.addAll(footer.getRows());
@@ -3192,30 +3212,52 @@ public class Grid<T> extends ResizeComposite implements
if (!row.hasSpannedCells()) {
continue;
}
- for (int c = frozenColumns; c < getColumnCount(); c++) {
- StaticCell cell = row.getCell(getColumn(c));
+ final boolean isDraggedCellRow = row.equals(draggedCellRow);
+ for (int cellColumnIndex = frozenColumns; cellColumnIndex < getColumnCount(); cellColumnIndex++) {
+ StaticCell cell = row.getCell(getColumn(cellColumnIndex));
int colspan = cell.getColspan();
if (colspan <= 1) {
continue;
}
- final int spannedCellRightEdgeIndex = c + colspan;
- if (c <= draggedColumnIndex
- && spannedCellRightEdgeIndex > draggedColumnIndex) {
- // the spanned cell overlaps the dragged cell
- if (c <= draggedColumnIndex && c > leftBound) {
- leftBound = c;
+ final int cellColumnRightIndex = cellColumnIndex + colspan;
+ final Range cellRange = Range.between(cellColumnIndex,
+ cellColumnRightIndex);
+ final boolean intersects = draggedCellRange
+ .intersects(cellRange);
+ if (intersects && !isDraggedCellRow) {
+ // if the currently iterated cell is inside or same as
+ // the dragged cell, then it doesn't restrict the drag
+ if (cellRange.isSubsetOf(draggedCellRange)) {
+ cellColumnIndex = cellColumnRightIndex - 1;
+ continue;
+ }
+ /*
+ * if the dragged cell is a spanned cell and it crosses
+ * with the currently iterated cell without sharing
+ * either start or end then not possible to drag the
+ * cell.
+ */
+ if (!draggedCellRange.isSubsetOf(cellRange)) {
+ return;
+ }
+ // the spanned cell overlaps the dragged cell (but is
+ // not the dragged cell)
+ if (cellColumnIndex <= draggedCellIndex
+ && cellColumnIndex > leftBound) {
+ leftBound = cellColumnIndex;
}
- if (spannedCellRightEdgeIndex < rightBound) {
- rightBound = spannedCellRightEdgeIndex;
+ if (cellColumnRightIndex < rightBound) {
+ rightBound = cellColumnRightIndex;
}
- c = spannedCellRightEdgeIndex - 1;
+ cellColumnIndex = cellColumnRightIndex - 1;
}
- else { // can't drop inside a spanned cell
+ else { // can't drop inside a spanned cell, or this is the
+ // dragged cell
while (colspan > 1) {
- c++;
+ cellColumnIndex++;
colspan--;
- unavailableColumnDropIndices.add(c);
+ unavailableColumnDropIndices.add(cellColumnIndex);
}
}
}
@@ -3244,6 +3286,7 @@ public class Grid<T> extends ResizeComposite implements
possibleDropPositions.put(position, getColumnCount());
}
}
+
};
/**
@@ -5537,10 +5580,6 @@ public class Grid<T> extends ResizeComposite implements
.getFrozenColumnCount()) {
return false;
}
- // for now prevent dragging of spanned cells
- if (eventCell.getElement().getColSpan() > 1) {
- return false;
- }
if (event.getTypeInt() == Event.ONMOUSEDOWN
&& event.getButton() == NativeEvent.BUTTON_LEFT
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java
index a7fc3f435d..d4892fb52a 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java
@@ -426,6 +426,174 @@ public class GridColumnReorderTest extends GridBasicClientFeaturesTest {
assertColumnHeaderOrder(1, 3, 4, 5, 2);
}
+ @Test
+ public void testColumnReorder_draggingASpannedCell_dragWorksNormally() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 4, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_twoEqualSpannedCells_bothCanBeDragged() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 4, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 1, 2, 4);
+
+ // when
+ dragAndDropColumnHeader(2, 3, 0, 10);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3, 4);
+ }
+
+ @Test
+ public void testColumReorder_twoCrossingSpanningHeaders_neitherCanBeDragged() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join column cells 0, 1");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 4, 10);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(2, 0, 3, 100);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ }
+
+ @Test
+ public void testColumnReorder_spannedCellHasAnotherSpannedCellInside_canBeDraggedNormally() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(1, 3, 1, 10);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 0, 10);
+
+ // then
+ assertColumnHeaderOrder(3, 4, 5, 0, 1);
+ }
+
+ @Test
+ public void testColumnReorder_spannedCellInsideAnotherSpanned_canBeDraggedWithBoundaries() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(1, 3, 1, 10);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 1, 3, 100);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 5, 3, 4, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 2, 0, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+ }
+
+ @Test
+ public void testColumnReorder_cellInsideAndNextToSpannedCells_canBeDraggedWithBoundaries() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(1, 3, 1, 10);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 3, 0, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 5, 3, 4, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 1, 4, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+ }
+
+ @Test
+ public void testColumnReorder_multipleSpannedCells_dragWorksNormally() {
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 3, 2, -10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ scrollGridHorizontallyTo(100);
+ dragAndDropColumnHeader(2, 4, 2, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 0, 3, 10);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3, 4);
+ }
+
private void toggleColumnReorder() {
selectMenuPath("Component", "State", "Column Reordering");
}