]> source.dussan.org Git - vaadin-framework.git/commitdiff
Client-side selection checkbox renderer (#13334)
authorHenrik Paul <henrik@vaadin.com>
Thu, 22 May 2014 12:54:36 +0000 (15:54 +0300)
committerLeif Åstrand <leif@vaadin.com>
Mon, 2 Jun 2014 11:31:26 +0000 (11:31 +0000)
Change-Id: I7b6a5c4ca1d78a97c34b1f7b95d1488edeb8551e

client/src/com/vaadin/client/ui/grid/Grid.java
client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java [new file with mode: 0644]
server/src/com/vaadin/ui/components/grid/Grid.java
shared/src/com/vaadin/shared/ui/grid/GridState.java
uitest/src/com/vaadin/tests/components/grid/GridBasicFeatures.java

index 44e0edce8ec28a8809e06077f19f244aef57af03..0d8c8f9ba981349640037b67a59c41da1b75d793 100644 (file)
@@ -38,6 +38,7 @@ import com.vaadin.client.data.DataSource;
 import com.vaadin.client.ui.SubPartAware;
 import com.vaadin.client.ui.grid.renderers.ComplexRenderer;
 import com.vaadin.client.ui.grid.renderers.TextRenderer;
+import com.vaadin.client.ui.grid.selection.MultiSelectionRenderer;
 import com.vaadin.shared.ui.grid.GridConstants;
 import com.vaadin.shared.ui.grid.HeightMode;
 import com.vaadin.shared.ui.grid.Range;
@@ -78,6 +79,92 @@ import com.vaadin.shared.util.SharedUtil;
  */
 public class Grid<T> extends Composite implements SubPartAware {
 
+    private class SelectionColumn extends GridColumn<Boolean, T> {
+        private boolean initDone = false;
+
+        public SelectionColumn(final Renderer<Boolean> selectColumnRenderer) {
+            super(selectColumnRenderer);
+
+            setHeaderRenderer(new Renderer<String>() {
+                @Override
+                public void render(FlyweightCell cell, String data) {
+                    if (cell.getRow() == escalator.getHeader().getRowCount() - 1) {
+                        selectColumnRenderer.render(cell, Boolean.FALSE);
+                    }
+                }
+            });
+        }
+
+        public void initDone() {
+            initDone = true;
+        }
+
+        @Override
+        public void setFooterCaption(String caption) {
+            if (initDone) {
+                throw new UnsupportedOperationException(
+                        "The selection column is read only");
+            } else {
+                super.setFooterCaption(caption);
+            }
+        }
+
+        @Override
+        public void setFooterRenderer(Renderer<String> renderer) {
+            if (initDone) {
+                throw new UnsupportedOperationException(
+                        "The selection column is read only");
+            } else {
+                super.setFooterRenderer(renderer);
+            }
+        }
+
+        @Override
+        public void setHeaderCaption(String caption) {
+            if (initDone) {
+                throw new UnsupportedOperationException(
+                        "The selection column is read only");
+            } else {
+                super.setHeaderCaption(caption);
+            }
+        }
+
+        @Override
+        public void setHeaderRenderer(Renderer<String> renderer) {
+            if (initDone) {
+                throw new UnsupportedOperationException(
+                        "The selection column is read only");
+            } else {
+                super.setHeaderRenderer(renderer);
+            }
+        }
+
+        @Override
+        public void setVisible(boolean visible) {
+            if (initDone) {
+                throw new UnsupportedOperationException(
+                        "The selection column is read only");
+            } else {
+                super.setVisible(visible);
+            }
+        }
+
+        @Override
+        public void setWidth(int pixels) {
+            if (initDone) {
+                throw new UnsupportedOperationException(
+                        "The selection column is read only");
+            } else {
+                super.setWidth(pixels);
+            }
+        }
+
+        @Override
+        public Boolean getValue(T row) {
+            return Boolean.valueOf(isSelected(row));
+        }
+    }
+
     /**
      * Escalator used internally by grid to render the rows
      */
@@ -114,6 +201,10 @@ public class Grid<T> extends Composite implements SubPartAware {
      */
     private GridColumn<?, T> lastFrozenColumn;
 
+    private Renderer<Boolean> selectColumnRenderer = null;
+
+    private SelectionColumn selectionColumn;
+
     /**
      * Base class for grid columns internally used by the Grid. The user should
      * use {@link GridColumn} when creating new columns.
@@ -215,10 +306,12 @@ public class Grid<T> extends Composite implements SubPartAware {
 
             this.grid = grid;
 
-            setVisible(this.visible);
-            setWidth(this.width);
-            setHeaderCaption(this.header);
-            setFooterCaption(this.footer);
+            if (grid != null) {
+                setVisible(this.visible);
+                setWidth(this.width);
+                setHeaderCaption(this.header);
+                setFooterCaption(this.footer);
+            }
         }
 
         /**
@@ -796,8 +889,7 @@ public class Grid<T> extends Composite implements SubPartAware {
      *            the column to add
      */
     public void addColumn(GridColumn<?, T> column) {
-        ColumnConfiguration conf = escalator.getColumnConfiguration();
-        addColumn(column, conf.getColumnCount());
+        addColumn(column, getColumnCount());
     }
 
     /**
@@ -807,9 +899,24 @@ public class Grid<T> extends Composite implements SubPartAware {
      *            the index where the column should be inserted into
      * @param column
      *            the column to add
+     * @throws IllegalStateException
+     *             if Grid's current selection model renders a selection column,
+     *             and {@code index} is 0.
      */
     public void addColumn(GridColumn<?, T> column, int index) {
+        if (column == selectionColumn) {
+            throw new IllegalArgumentException("The selection column many "
+                    + "not be added manually");
+        } else if (selectionColumn != null && index == 0) {
+            throw new IllegalStateException("A column cannot be inserted "
+                    + "before the selection column");
+        }
 
+        addColumnSkipSelectionColumnCheck(column, index);
+    }
+
+    private void addColumnSkipSelectionColumnCheck(GridColumn<?, T> column,
+            int index) {
         // Register column with grid
         columns.add(index, column);
 
@@ -889,7 +996,15 @@ public class Grid<T> extends Composite implements SubPartAware {
      *            the column to remove
      */
     public void removeColumn(GridColumn<?, T> column) {
+        if (column != null && column.equals(selectionColumn)) {
+            throw new IllegalArgumentException(
+                    "The selection column may not be removed manually.");
+        }
+
+        removeColumnSkipSelectionColumnCheck(column);
+    }
 
+    private void removeColumnSkipSelectionColumnCheck(GridColumn<?, T> column) {
         int columnIndex = columns.indexOf(column);
         int visibleIndex = findVisibleColumnIndex(column);
         columns.remove(columnIndex);
@@ -1559,4 +1674,45 @@ public class Grid<T> extends Composite implements SubPartAware {
         }
         return null;
     }
+
+    private void setSelectColumnRenderer(
+            final Renderer<Boolean> selectColumnRenderer) {
+        if (this.selectColumnRenderer == selectColumnRenderer) {
+            return;
+        }
+
+        if (this.selectColumnRenderer != null) {
+            removeColumnSkipSelectionColumnCheck(selectionColumn);
+        }
+
+        this.selectColumnRenderer = selectColumnRenderer;
+
+        if (selectColumnRenderer != null) {
+            selectionColumn = new SelectionColumn(selectColumnRenderer);
+
+            // FIXME: this needs to be done elsewhere, requires design...
+            selectionColumn.setWidth(25);
+            addColumnSkipSelectionColumnCheck(selectionColumn, 0);
+            selectionColumn.initDone();
+        } else {
+            selectionColumn = null;
+        }
+    }
+
+    /* TODO remove before final */
+    public void setSelectionCheckboxes(boolean set) {
+        if (set) {
+            setSelectColumnRenderer(new MultiSelectionRenderer());
+        } else {
+            setSelectColumnRenderer(null);
+        }
+    }
+
+    /*
+     * This is the same client-side Grid "isSelected" method as in the selection
+     * model design.
+     */
+    private boolean isSelected(T row) {
+        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
new file mode 100644 (file)
index 0000000..847c897
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.client.ui.grid.selection;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.user.client.DOM;
+import com.vaadin.client.ui.grid.FlyweightCell;
+import com.vaadin.client.ui.grid.Renderer;
+
+/* This class will probably not survive the final merge of all selection functionality. */
+public class MultiSelectionRenderer implements Renderer<Boolean> {
+    @Override
+    public void render(FlyweightCell cell, Boolean data) {
+        Element checkbox = Element.as(DOM.createInputCheck());
+        if (Boolean.TRUE.equals(data)) {
+            checkbox.setAttribute("checked", "checked");
+        }
+        cell.getElement().removeAllChildren();
+        cell.getElement().appendChild(checkbox);
+    }
+}
index 49b3f1fa64522236fc7cc52d27008f233f1e3f4e..7f3e3440c7e3437f3b6a6874803ef2f2013d7ee7 100644 (file)
@@ -925,4 +925,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
         removeListener(SelectionChangeEvent.class, listener,
                 SELECTION_CHANGE_METHOD);
     }
+
+    /** FIXME remove once selection mode communcation is done. only for testing. */
+    public void setSelectionCheckboxes(boolean value) {
+        getState().selectionCheckboxes = value;
+    }
 }
index 8fdd8c8ec58f438230f874aa5b70c2e7da3dc61d..acb2a48e3cf5a0de92262bf7ffb3fbd6ff3775c4 100644 (file)
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.annotations.DelegateToWidget;
 
 /**
  * The shared state for the {@link com.vaadin.ui.components.grid.Grid} component
@@ -85,4 +86,8 @@ public class GridState extends AbstractComponentState {
      */
     public HeightMode heightMode = HeightMode.CSS;
 
+    /** FIXME remove once selection mode communcation is done. only for testing. */
+    @DelegateToWidget
+    public boolean selectionCheckboxes;
+
 }
index 91bd6b032d7330544dc27db796083cc646fa5774..1dc500202e5c347c6c773a67cdc47d1ef3bbed01 100644 (file)
@@ -147,6 +147,14 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
     protected void createColumnActions() {
         createCategory("Columns", null);
 
+        createBooleanAction("Selection controls", "Columns", false,
+                new Command<Grid, Boolean>() {
+                    @Override
+                    public void execute(Grid grid, Boolean value, Object data) {
+                        grid.setSelectionCheckboxes(value);
+                    }
+                });
+
         for (int c = 0; c < COLUMNS; c++) {
             createCategory(getColumnProperty(c), "Columns");