]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix active row range handling when removing rows (#15454)
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Wed, 31 Dec 2014 08:25:46 +0000 (10:25 +0200)
committerVaadin Code Review <review@vaadin.com>
Wed, 31 Dec 2014 11:10:47 +0000 (11:10 +0000)
Change-Id: I6de22796051503290db216d4c213401d24a7e2a0

server/src/com/vaadin/data/RpcDataProviderExtension.java
uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java [new file with mode: 0644]

index e8818aa828c75e8fec93e07c741e51981d77f7db..a24ee9acd74cbb82396162a37313a24251e14ee1 100644 (file)
@@ -303,7 +303,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
         }
 
         Object itemIdAtIndex(int index) {
-            return indexToItemId.inverse().get(Integer.valueOf(index));
+            return indexToItemId.get(Integer.valueOf(index));
         }
     }
 
@@ -516,23 +516,39 @@ public class RpcDataProviderExtension extends AbstractExtension {
         }
 
         /**
-         * Removes a single item by its id.
+         * Handles the removal of rows.
+         * <p>
+         * This method's responsibilities are to:
+         * <ul>
+         * <li>shift the internal bookkeeping by <code>count</code> if the
+         * removal happens above currently active range
+         * <li>ignore rows removed below the currently active range
+         * </ul>
          * 
-         * @param itemId
-         *            the id of the removed id. <em>Note:</em> this item does
-         *            not exist anymore in the datasource
+         * @param firstIndex
+         *            the index of the first removed rows
+         * @param count
+         *            the number of rows removed at <code>firstIndex</code>
          */
-        public void removeItemId(Object itemId) {
-            final GridValueChangeListener removedListener = valueChangeListeners
-                    .remove(itemId);
-            if (removedListener != null) {
-                /*
-                 * We removed an item from somewhere in the visible range, so we
-                 * make the active range shorter. The empty hole will be filled
-                 * by the client-side code when it asks for more information.
-                 */
+        public void removeRows(int firstIndex, int count) {
+            int lastRemoved = firstIndex + count;
+            if (lastRemoved < activeRange.getStart()) {
+                /* firstIndex < lastIndex < start */
+                activeRange = activeRange.offsetBy(-count);
+            } else if (firstIndex < activeRange.getEnd()) {
+                final Range deprecated = Range.between(
+                        Math.max(activeRange.getStart(), firstIndex),
+                        Math.min(activeRange.getEnd(), lastRemoved + 1));
+                for (int i = deprecated.getStart(); i < deprecated.getEnd(); ++i) {
+                    Object itemId = keyMapper.itemIdAtIndex(i);
+                    // Item doesn't exist anymore.
+                    valueChangeListeners.remove(itemId);
+                }
+
                 activeRange = Range.withLength(activeRange.getStart(),
-                        activeRange.length() - 1);
+                        activeRange.length() - deprecated.length());
+            } else {
+                /* end <= firstIndex, no need to do anything */
             }
         }
     }
@@ -847,12 +863,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
             rpc.removeRowData(firstIndex, count);
         }
 
-        for (int i = 0; i < count; i++) {
-            Object itemId = keyMapper.itemIdAtIndex(firstIndex + i);
-            if (itemId != null) {
-                activeRowHandler.removeItemId(itemId);
-            }
-        }
+        activeRowHandler.removeRows(firstIndex, count);
     }
 
     /**
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java b/uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java
new file mode 100644 (file)
index 0000000..4a331f3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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 com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+
+public class GridInTabSheet extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        TabSheet sheet = new TabSheet();
+        final Grid grid = new Grid();
+        grid.addColumn("count", Integer.class);
+        for (Integer i = 0; i < 3; ++i) {
+            grid.addRow(i);
+        }
+
+        sheet.addTab(grid);
+        sheet.addTab(new Label("Hidden"));
+
+        addComponent(sheet);
+        addComponent(new Button("Add row to Grid", new Button.ClickListener() {
+
+            private Integer k = 0;
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                grid.addRow(100 + (k++));
+            }
+        }));
+        addComponent(new Button("Remove row from Grid",
+                new Button.ClickListener() {
+
+                    private Integer k = 0;
+
+                    @Override
+                    public void buttonClick(ClickEvent event) {
+                        Object firstItemId = grid.getContainerDataSource()
+                                .firstItemId();
+                        if (firstItemId != null) {
+                            grid.getContainerDataSource().removeItem(
+                                    firstItemId);
+                        }
+                    }
+                }));
+    }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java b/uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java
new file mode 100644 (file)
index 0000000..0fe15b1
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridInTabSheetTest extends MultiBrowserTest {
+
+    @Test
+    public void testRemoveAllRowsAndAddThreeNewOnes() {
+        setDebug(true);
+        openTestURL();
+
+        for (int i = 0; i < 3; ++i) {
+            removeGridRow();
+        }
+
+        for (int i = 0; i < 3; ++i) {
+            addGridRow();
+            assertEquals("" + (100 + i), getGridElement().getCell(i, 1)
+                    .getText());
+        }
+        assertFalse("There was an unexpected error notification",
+                isElementPresent(NotificationElement.class));
+    }
+
+    private void removeGridRow() {
+        $(ButtonElement.class).caption("Remove row from Grid").first().click();
+    }
+
+    private void addGridRow() {
+        $(ButtonElement.class).caption("Add row to Grid").first().click();
+    }
+
+    private GridElement getGridElement() {
+        return $(GridElement.class).first();
+    }
+}