diff options
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()); |