]> source.dussan.org Git - vaadin-framework.git/commitdiff
Implement selection with keyboard (#13334)
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Tue, 19 Aug 2014 08:36:41 +0000 (11:36 +0300)
committerHenrik Paul <henrik@vaadin.com>
Thu, 21 Aug 2014 12:54:19 +0000 (12:54 +0000)
Change-Id: I29a2ac38dfd613e952fd2f939ee8670271255aa3

client/src/com/vaadin/client/ui/grid/Grid.java
client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java
client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java

index cf802b5d484329c76b2bf361a7c7d66c7d57e29d..70d8286c9035792677fd554bd291de786235ed90 100644 (file)
@@ -2222,6 +2222,11 @@ public class Grid<T> extends Composite implements
             throw new IllegalArgumentException("Selection model can't be null");
         }
 
+        if (selectColumnRenderer != null
+                && selectColumnRenderer instanceof ComplexRenderer) {
+            ((ComplexRenderer<?>) selectColumnRenderer).destroy();
+        }
+
         this.selectionModel = selectionModel;
         selectionModel.setGrid(this);
         setSelectColumnRenderer(this.selectionModel
index d5dd845e92fd5164b96ef1c944c2996215b4708d..f0c95e2ddff14718f445ab28d35805d6caf803fd 100644 (file)
@@ -142,4 +142,12 @@ public abstract class ComplexRenderer<T> implements Renderer<T> {
     public boolean onActivate() {
         return false;
     }
+
+    /**
+     * Called when the renderer is deemed to be destroyed and no longer used by
+     * the Grid.
+     */
+    public void destroy() {
+        // Implement if needed
+    }
 }
index 1033b0062353a20804a2805133db68473aaa2fa2..a3030e3a1fd422374ef862ce57aa88d19d6f83d1 100644 (file)
@@ -27,6 +27,7 @@ import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.InputElement;
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
@@ -36,10 +37,17 @@ import com.vaadin.client.Util;
 import com.vaadin.client.data.AbstractRemoteDataSource;
 import com.vaadin.client.data.DataSource;
 import com.vaadin.client.ui.grid.Cell;
+import com.vaadin.client.ui.grid.DataAvailableEvent;
+import com.vaadin.client.ui.grid.DataAvailableHandler;
 import com.vaadin.client.ui.grid.FlyweightCell;
 import com.vaadin.client.ui.grid.Grid;
+import com.vaadin.client.ui.grid.keyevents.BodyKeyDownHandler;
+import com.vaadin.client.ui.grid.keyevents.BodyKeyUpHandler;
+import com.vaadin.client.ui.grid.keyevents.GridKeyDownEvent;
+import com.vaadin.client.ui.grid.keyevents.GridKeyUpEvent;
 import com.vaadin.client.ui.grid.renderers.ComplexRenderer;
 import com.vaadin.client.ui.grid.selection.SelectionModel.Multi.Batched;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 
 /* This class will probably not survive the final merge of all selection functionality. */
 public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
@@ -576,15 +584,74 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
         }
     }
 
+    private class SpaceKeyDownSelectHandler implements BodyKeyDownHandler<T> {
+
+        private HandlerRegistration scrollHandler = null;
+        private boolean spaceDown = false;
+
+        @Override
+        public void onKeyDown(GridKeyDownEvent<T> event) {
+            if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE || spaceDown) {
+                return;
+            }
+
+            spaceDown = true;
+            Cell active = event.getActiveCell();
+            final int rowIndex = active.getRow();
+
+            if (scrollHandler != null) {
+                scrollHandler.removeHandler();
+                scrollHandler = null;
+            }
+
+            scrollHandler = grid
+                    .addDataAvailableHandler(new DataAvailableHandler() {
+
+                        @Override
+                        public void onDataAvailable(DataAvailableEvent event) {
+                            if (event.getAvailableRows().contains(rowIndex)) {
+                                setSelected(rowIndex, !isSelected(rowIndex));
+                                scrollHandler.removeHandler();
+                                scrollHandler = null;
+                            }
+                        }
+                    });
+            grid.scrollToRow(rowIndex, ScrollDestination.ANY);
+        }
+
+    }
+
     private static final String LOGICAL_ROW_PROPERTY_INT = "vEscalatorLogicalRow";
 
     private final Grid<T> grid;
     private HandlerRegistration nativePreviewHandlerRegistration;
+    private final SpaceKeyDownSelectHandler handler = new SpaceKeyDownSelectHandler();
+    private HandlerRegistration spaceDown;
+    private HandlerRegistration spaceUp;
 
     private final AutoScrollHandler autoScrollHandler = new AutoScrollHandler();
 
     public MultiSelectionRenderer(final Grid<T> grid) {
         this.grid = grid;
+        spaceDown = grid.addKeyDownHandler(handler);
+        spaceUp = grid.addKeyUpHandler(new BodyKeyUpHandler<T>() {
+
+            @Override
+            public void onKeyUp(GridKeyUpEvent<T> event) {
+                if (event.getNativeKeyCode() == KeyCodes.KEY_SPACE) {
+                    handler.spaceDown = false;
+                }
+            }
+        });
+    }
+
+    @Override
+    public void destroy() {
+        spaceDown.removeHandler();
+        spaceUp.removeHandler();
+        if (nativePreviewHandlerRegistration != null) {
+            removeNativeHandler();
+        }
     }
 
     @Override
index c190f7d0ec7178957535d9feb033a9d7b952f452..6e2ac91df2f4a3034483a93900280ce2cae826b3 100644 (file)
@@ -19,6 +19,8 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
 
 import com.vaadin.testbench.TestBenchElement;
 import com.vaadin.tests.components.grid.GridElement;
@@ -123,6 +125,32 @@ public class GridSelectionTest extends GridBasicFeaturesTest {
         assertTrue("First row was not selected.", getRow(0).isSelected());
     }
 
+    @Test
+    public void testKeyboardSelection() {
+        openTestURL();
+        setSelectionModelMulti();
+
+        GridElement grid = getGridElement();
+        grid.getCell(3, 1).click();
+        new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+        assertTrue("Grid row 3 was not selected with space key.", grid
+                .getRow(3).isSelected());
+
+        new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+        assertTrue("Grid row 3 was not deselected with space key.", !grid
+                .getRow(3).isSelected());
+
+        grid.scrollToRow(500);
+
+        new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+        assertTrue("Grid row 3 was not selected with space key.", grid
+                .getRow(3).isSelected());
+
+    }
+
     private void setSelectionModelMulti() {
         selectMenuPath("Component", "State", "Selection mode", "multi");
     }