diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2014-07-14 16:40:30 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2014-07-15 11:23:41 +0000 |
commit | f89d015e9252d4470afa6008fd3f004809129b89 (patch) | |
tree | e3470afedf20c4c51849a5a7bb2d11d5d3ed8a24 | |
parent | 3582b43415c7ddd587451f565a5ae70fea8bb51d (diff) | |
download | vaadin-framework-f89d015e9252d4470afa6008fd3f004809129b89.tar.gz vaadin-framework-f89d015e9252d4470afa6008fd3f004809129b89.zip |
Implement active cell painting and mouse interaction (#13334)
Change-Id: Iecb9db0fe6ea9ef0409e2ac0a294ac3508277251
6 files changed, 172 insertions, 12 deletions
diff --git a/WebContent/VAADIN/themes/base/grid/grid.scss b/WebContent/VAADIN/themes/base/grid/grid.scss index 2955f7ecd3..88c7754a10 100644 --- a/WebContent/VAADIN/themes/base/grid/grid.scss +++ b/WebContent/VAADIN/themes/base/grid/grid.scss @@ -19,8 +19,19 @@ right: 5px; } + .#{$primaryStyleName}-cell-active { + border-color: blue; + } + + .#{$primaryStyleName}-header-active { + background: lightgray; + } + + .#{$primaryStyleName}-row-active > td { + background: rgb(244,244,244); + } } - + .#{$primaryStyleName}-row-selected > td { background: lightblue; } diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index d03197e2ef..471f62cdeb 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -235,6 +235,9 @@ public class Grid<T> extends Composite implements private String rowHasDataStyleName; private String rowSelectedStyleName; + private String cellActiveStyleName; + private String rowActiveStyleName; + private String headerFooterFocusedStyleName; /** * Current selection model. @@ -242,6 +245,12 @@ public class Grid<T> extends Composite implements private SelectionModel<T> selectionModel; /** + * Current active cell. + */ + private int activeRow = 0; + private int activeColumn = 0; + + /** * Enumeration for easy setting of selection mode. */ public enum SelectionMode { @@ -430,14 +439,14 @@ public class Grid<T> extends Composite implements } @Override - public void onBrowserEvent(final Cell cell, NativeEvent event) { + public boolean onBrowserEvent(final Cell cell, NativeEvent event) { // Handle sorting events if column is sortable if (grid.getColumn(cell.getColumn()).isSortable()) { if (BrowserEvents.TOUCHSTART.equals(event.getType())) { if (event.getTouches().length() > 1) { - return; + return false; } event.preventDefault(); @@ -452,7 +461,7 @@ public class Grid<T> extends Composite implements } else if (BrowserEvents.TOUCHMOVE.equals(event.getType())) { if (event.getTouches().length() > 1) { - return; + return false; } event.preventDefault(); @@ -472,7 +481,7 @@ public class Grid<T> extends Composite implements } else if (BrowserEvents.TOUCHEND.equals(event.getType())) { if (event.getTouches().length() > 0) { - return; + return false; } if (lazySorter.isRunning()) { @@ -485,7 +494,7 @@ public class Grid<T> extends Composite implements } else if (BrowserEvents.TOUCHCANCEL .equals(event.getType())) { if (event.getChangedTouches().length() > 1) { - return; + return false; } lazySorter.cancel(); @@ -496,7 +505,10 @@ public class Grid<T> extends Composite implements lazySorter.setMultisort(event.getShiftKey()); lazySorter.run(); } + return true; } + return false; + } /** @@ -986,6 +998,10 @@ public class Grid<T> extends Composite implements getRenderer(column) .render(cell, getColumnValue(column)); } + + setStyleName(cell.getElement(), + headerFooterFocusedStyleName, + activeColumn == cell.getColumn()); } } else if (columnGroupRows.size() > 0) { @@ -1023,6 +1039,10 @@ public class Grid<T> extends Composite implements // Cells are reused cellElement.setInnerHTML(null); cell.setColSpan(1); + + setStyleName(cell.getElement(), + headerFooterFocusedStyleName, + activeColumn == cell.getColumn()); } } } @@ -1060,6 +1080,7 @@ public class Grid<T> extends Composite implements refreshHeader(); refreshFooter(); + sinkEvents(Event.ONMOUSEDOWN); setSelectionMode(SelectionMode.SINGLE); escalator @@ -1092,6 +1113,9 @@ public class Grid<T> extends Composite implements escalator.setStylePrimaryName(style); rowHasDataStyleName = getStylePrimaryName() + "-row-has-data"; rowSelectedStyleName = getStylePrimaryName() + "-row-selected"; + cellActiveStyleName = getStylePrimaryName() + "-cell-active"; + headerFooterFocusedStyleName = getStylePrimaryName() + "-header-active"; + rowActiveStyleName = getStylePrimaryName() + "-row-active"; } /** @@ -1194,6 +1218,9 @@ public class Grid<T> extends Composite implements setStyleName(rowElement, rowSelectedStyleName, false); } + setStyleName(rowElement, rowActiveStyleName, + rowIndex == activeRow); + for (FlyweightCell cell : cellsToUpdate) { GridColumn<?, T> column = getColumnFromVisibleIndex(cell .getColumn()); @@ -1201,6 +1228,9 @@ public class Grid<T> extends Composite implements assert column != null : "Column was not found from cell (" + cell.getColumn() + "," + cell.getRow() + ")"; + setStyleName(cell.getElement(), cellActiveStyleName, + isActiveCell(cell)); + Renderer renderer = column.getRenderer(); // Hide cell content if needed @@ -1232,6 +1262,11 @@ public class Grid<T> extends Composite implements } } + private boolean isActiveCell(FlyweightCell cell) { + return cell.getRow() == activeRow + && cell.getColumn() == activeColumn; + } + @Override public void preDetach(Row row, Iterable<FlyweightCell> cellsToDetach) { for (FlyweightCell cell : cellsToDetach) { @@ -2095,8 +2130,19 @@ public class Grid<T> extends Composite implements } if (renderer instanceof ComplexRenderer) { - ((ComplexRenderer<?>) renderer).onBrowserEvent(cell, - event); + ComplexRenderer<?> cplxRenderer = (ComplexRenderer<?>) renderer; + if (cplxRenderer.getConsumedEvents().contains( + event.getType())) { + if (cplxRenderer.onBrowserEvent(cell, event)) { + return; + } + } + } + + // TODO: Support active cells in Headers and Footers, + // 14.07.2014, Teemu Suo-Anttila + if (event.getTypeInt() == Event.ONMOUSEDOWN) { + setActiveCell(cell); } } } @@ -2202,11 +2248,13 @@ public class Grid<T> extends Composite implements if (this.selectColumnRenderer != null) { removeColumnSkipSelectionColumnCheck(selectionColumn); + --activeColumn; } this.selectColumnRenderer = selectColumnRenderer; if (selectColumnRenderer != null) { + ++activeColumn; selectionColumn = new SelectionColumn(selectColumnRenderer); // FIXME: this needs to be done elsewhere, requires design... @@ -2215,6 +2263,7 @@ public class Grid<T> extends Composite implements selectionColumn.initDone(); } else { selectionColumn = null; + refreshBody(); } } @@ -2452,4 +2501,32 @@ public class Grid<T> extends Composite implements fireEvent(new SortEvent<T>(this, Collections.unmodifiableList(sortOrder))); } + + /** + * Set currently active cell used for keyboard navigation. Note that active + * cell is not {@code activeElement}. + * + * @param cell + * a cell object + */ + public void setActiveCell(Cell cell) { + int oldRow = activeRow; + int oldColumn = activeColumn; + + activeRow = cell.getRow(); + activeColumn = cell.getColumn(); + + if (oldRow != activeRow) { + escalator.getBody().refreshRows(oldRow, 1); + escalator.getBody().refreshRows(activeRow, 1); + } + + if (oldColumn != activeColumn) { + if (oldRow == activeRow) { + escalator.getBody().refreshRows(oldRow, 1); + } + refreshHeader(); + refreshFooter(); + } + } } diff --git a/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java b/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java index 6a1f1c3041..d5dd845e92 100644 --- a/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java +++ b/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java @@ -86,6 +86,9 @@ public abstract class ComplexRenderer<T> implements Renderer<T> { * <p> * The events that triggers this needs to be returned by the * {@link #getConsumedEvents()} method. + * <p> + * Returns boolean telling if the event has been completely handled and + * should not cause any other actions. * * @param cell * Object containing information about the cell the event was @@ -93,9 +96,10 @@ public abstract class ComplexRenderer<T> implements Renderer<T> { * * @param event * The original DOM event + * @return true if event should not be handled by grid */ - public void onBrowserEvent(Cell cell, NativeEvent event) { - // Implement if needed + public boolean onBrowserEvent(Cell cell, NativeEvent event) { + return false; } /** diff --git a/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java b/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java index 3754c51f18..aa063a34e7 100644 --- a/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java +++ b/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java @@ -482,7 +482,7 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> { } @Override - public void onBrowserEvent(final Cell cell, final NativeEvent event) { + public boolean onBrowserEvent(final Cell cell, final NativeEvent event) { if (BrowserEvents.TOUCHSTART.equals(event.getType()) || BrowserEvents.MOUSEDOWN.equals(event.getType())) { injectNativeHandler(); @@ -491,6 +491,7 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> { autoScrollHandler.start(logicalRowIndex); event.preventDefault(); event.stopPropagation(); + return true; } else { throw new IllegalStateException("received unexpected event: " + event.getType()); diff --git a/uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java new file mode 100644 index 0000000000..927b941131 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.grid; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class GridKeyboardNavigationTest extends MultiBrowserTest { + + @Override + protected Class<?> getUIClass() { + return GridBasicFeatures.class; + } + + @Test + public void testCellActiveOnClick() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", + cellIsActive(grid, 0, 0)); + grid.getCell(5, 2).click(); + assertFalse("Body cell 0, 0 was still active after clicking", + cellIsActive(grid, 0, 0)); + assertTrue("Body cell 5, 2 is not active after clicking", + cellIsActive(grid, 5, 2)); + } + + @Test + public void testCellNotActiveWhenRendererHandlesEvent() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", + cellIsActive(grid, 0, 0)); + grid.getHeaderCell(0, 3).click(); + assertTrue("Body cell 0, 0 is not active after click on header.", + cellIsActive(grid, 0, 0)); + } + + private boolean cellIsActive(GridElement grid, int row, int col) { + return grid.getCell(row, col).getAttribute("class") + .contains("-cell-active"); + } + + private GridElement getGridElement() { + return $(GridElement.class).first(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java index 40dbbeb370..9ee05cb036 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java @@ -58,11 +58,12 @@ public class RowAwareRendererConnector extends AbstractRendererConnector<Void> { } @Override - public void onBrowserEvent(Cell cell, NativeEvent event) { + public boolean onBrowserEvent(Cell cell, NativeEvent event) { int row = cell.getRow(); String key = getRowKey(row); getRpcProxy(RowAwareRendererRpc.class).clicky(key); cell.getElement().setInnerText("row: " + row + ", key: " + key); + return true; } } |