aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java28
-rw-r--r--server/src/com/vaadin/data/RpcDataProviderExtension.java5
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/DetailsConnectorChange.java45
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java26
4 files changed, 93 insertions, 11 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index 7c568e02e5..51e986933c 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -19,6 +19,7 @@ package com.vaadin.client.connectors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -677,8 +678,13 @@ public class GridConnector extends AbstractHasComponentsConnector implements
customDetailsGenerator
.setDetailsConnectorChanges(connectorChanges);
+ List<DetailsConnectorChange> removedFirst = new ArrayList<DetailsConnectorChange>(
+ connectorChanges);
+ Collections.sort(removedFirst,
+ DetailsConnectorChange.REMOVED_FIRST_COMPARATOR);
+
// refresh moved/added details rows
- for (DetailsConnectorChange change : connectorChanges) {
+ for (DetailsConnectorChange change : removedFirst) {
Integer oldIndex = change.getOldIndex();
Integer newIndex = change.getNewIndex();
@@ -689,13 +695,23 @@ public class GridConnector extends AbstractHasComponentsConnector implements
+ "invalid new index: " + newIndex
+ " (connector: " + change.getConnector() + ")";
- Integer index = newIndex;
- if (index == null) {
- index = oldIndex;
+ if (oldIndex != null) {
+ /* Close the old/removed index */
+ getWidget().setDetailsVisible(oldIndex, false);
+
+ if (change.isShouldStillBeVisible()) {
+ getWidget().setDetailsVisible(oldIndex, true);
+ }
}
- getWidget().setDetailsVisible(index, false);
- getWidget().setDetailsVisible(index, true);
+ if (newIndex != null) {
+ /*
+ * Since the component was lazy loaded, we need to
+ * refresh the details by toggling it.
+ */
+ getWidget().setDetailsVisible(newIndex, false);
+ getWidget().setDetailsVisible(newIndex, true);
+ }
}
detailsConnectorFetcher.responseReceived(fetchId);
}
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java
index 66c17c4afa..a21a81244a 100644
--- a/server/src/com/vaadin/data/RpcDataProviderExtension.java
+++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java
@@ -787,7 +787,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
if (!SharedUtil.equals(oldIndex, newIndex)) {
changes.add(new DetailsConnectorChange(component, oldIndex,
- newIndex));
+ newIndex, emptyDetails.containsKey(component)));
}
}
@@ -798,7 +798,8 @@ public class RpcDataProviderExtension extends AbstractExtension {
Component component = entry.getValue();
Integer newIndex = rowIndexToDetails.inverse().get(component);
if (newIndex == null) {
- changes.add(new DetailsConnectorChange(null, oldIndex, null));
+ changes.add(new DetailsConnectorChange(null, oldIndex,
+ null, emptyDetails.containsValue(oldIndex)));
}
}
diff --git a/shared/src/com/vaadin/shared/ui/grid/DetailsConnectorChange.java b/shared/src/com/vaadin/shared/ui/grid/DetailsConnectorChange.java
index 5b80f27b1e..171a7738a6 100644
--- a/shared/src/com/vaadin/shared/ui/grid/DetailsConnectorChange.java
+++ b/shared/src/com/vaadin/shared/ui/grid/DetailsConnectorChange.java
@@ -16,6 +16,7 @@
package com.vaadin.shared.ui.grid;
import java.io.Serializable;
+import java.util.Comparator;
import com.vaadin.shared.Connector;
@@ -28,9 +29,25 @@ import com.vaadin.shared.Connector;
*/
public class DetailsConnectorChange implements Serializable {
+ public static final Comparator<DetailsConnectorChange> REMOVED_FIRST_COMPARATOR = new Comparator<DetailsConnectorChange>() {
+ @Override
+ public int compare(DetailsConnectorChange a, DetailsConnectorChange b) {
+ boolean deleteA = a.getNewIndex() == null;
+ boolean deleteB = b.getNewIndex() == null;
+ if (deleteA && !deleteB) {
+ return -1;
+ } else if (!deleteA && deleteB) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ };
+
private Connector connector;
private Integer oldIndex;
private Integer newIndex;
+ private boolean shouldStillBeVisible;
/** Create a new connector index change */
public DetailsConnectorChange() {
@@ -48,12 +65,15 @@ public class DetailsConnectorChange implements Serializable {
* the old index
* @param newIndex
* the new index
+ * @param shouldStillBeVisible
+ * details should be visible regardless of {@code connector}
*/
public DetailsConnectorChange(Connector connector, Integer oldIndex,
- Integer newIndex) {
+ Integer newIndex, boolean shouldStillBeVisible) {
this.connector = connector;
this.oldIndex = oldIndex;
this.newIndex = newIndex;
+ this.shouldStillBeVisible = shouldStillBeVisible;
assert assertStateIsOk();
}
@@ -144,4 +164,27 @@ public class DetailsConnectorChange implements Serializable {
public void setNewIndex(Integer newIndex) {
this.newIndex = newIndex;
}
+
+ /**
+ * Checks whether whether the details should remain open, even if connector
+ * might be <code>null</code>.
+ *
+ * @return <code>true</code> iff the details should remain open, even if
+ * connector might be <code>null</code>
+ */
+ public boolean isShouldStillBeVisible() {
+ return shouldStillBeVisible;
+ }
+
+ /**
+ * Sets whether the details should remain open, even if connector might be
+ * <code>null</code>.
+ *
+ * @param shouldStillBeVisible
+ * <code>true</code> iff the details should remain open, even if
+ * connector might be <code>null</code>
+ */
+ public void setShouldStillBeVisible(boolean shouldStillBeVisible) {
+ this.shouldStillBeVisible = shouldStillBeVisible;
+ }
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java
index 7ddd903161..cfaf79ea05 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java
@@ -81,6 +81,22 @@ public class GridDetailsServerTest extends GridBasicFeaturesTest {
}
@Test
+ public void openVisiblePopulatedDetails() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ assertNotNull("details should've populated", getGridElement()
+ .getDetails(0).findElement(By.className("v-widget")));
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void closeVisiblePopulatedDetails() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ getGridElement().getDetails(0);
+ }
+
+ @Test
public void openDetailsOutsideOfActiveRange() throws InterruptedException {
getGridElement().scroll(10000);
selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
@@ -260,8 +276,14 @@ public class GridDetailsServerTest extends GridBasicFeaturesTest {
selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
selectMenuPath(DETAILS_GENERATOR_WATCHING);
selectMenuPath(DETAILS_GENERATOR_NULL);
- assertTrue("Details should be empty with null component",
- getGridElement().getDetails(0).getText().isEmpty());
+
+ try {
+ assertTrue("Details should be empty with null component",
+ getGridElement().getDetails(0).getText().isEmpty());
+ } catch (NoSuchElementException e) {
+ fail("Expected to find a details row with empty content");
+ }
+
selectMenuPath(DETAILS_GENERATOR_WATCHING);
assertFalse("Details should be not empty with details component",
getGridElement().getDetails(0).getText().isEmpty());