Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix updating Grid's item set when details rows are open. #12231

Merged
merged 1 commit into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ private boolean refreshDetails(int rowIndex) {
// updated, replace reference
indexToDetailConnectorId.put(rowIndex, id);
newOrUpdatedDetails = true;
getWidget().resetVisibleDetails(rowIndex);
}
} else {
// new Details content, listeners will get attached to the connector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ void setSpacer(int rowIndex, double height)
*/
boolean spacerExists(int rowIndex);

/**
* Updates the spacer corresponding with the given rowIndex to currently
* provided contents.
*
* @since
* @param rowIndex
* the row index for the spacer in need of updating
*/
void resetSpacer(int rowIndex);

/**
* Sets a new spacer updater.
* <p>
Expand Down
32 changes: 29 additions & 3 deletions client/src/main/java/com/vaadin/client/widgets/Escalator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4964,6 +4964,11 @@ public boolean spacerExists(int rowIndex) {
return spacerContainer.spacerExists(rowIndex);
}

@Override
public void resetSpacer(int rowIndex) {
spacerContainer.resetSpacer(rowIndex);
}

@Override
public void setSpacerUpdater(SpacerUpdater spacerUpdater)
throws IllegalArgumentException {
Expand Down Expand Up @@ -6111,8 +6116,10 @@ public void setHeight(double height) {
root.getStyle().setHeight(height + defaultCellBorderBottomSize,
Unit.PX);

// move the visible spacers getRow row onwards.
shiftSpacerPositionsAfterRow(getRow(), heightDiff);
if (!delayRepositioning) {
// move the visible spacers getRow row onwards.
shiftSpacerPositionsAfterRow(getRow(), heightDiff);
}

/*
* If we're growing, we'll adjust the scroll size first, then
Expand Down Expand Up @@ -6178,7 +6185,7 @@ public void setHeight(double height) {
tBodyScrollTop + moveDiff);
verticalScrollbar.setScrollPosByDelta(moveDiff);

} else {
} else if (!delayRepositioning) {
body.shiftRowPositions(getRow(), heightDiff);
}

Expand Down Expand Up @@ -6336,6 +6343,8 @@ public void onScroll(ScrollEvent event) {
/** Width of the spacers' decos. Calculated once then cached. */
private double spacerDecoWidth = 0.0D;

private boolean delayRepositioning = false;

public void setSpacer(int rowIndex, double height)
throws IllegalArgumentException {

Expand Down Expand Up @@ -6376,6 +6385,23 @@ public boolean isSpacer(Element row) {
return false;
}

void resetSpacer(int rowIndex) {
if (spacerExists(rowIndex)) {
delayRepositioning = true;
double oldHeight = getSpacer(rowIndex).getHeight();
removeSpacer(rowIndex);
// real height will be determined later
insertNewSpacer(rowIndex, 0);
// reposition content below this point to match lack of height,
// otherwise later repositioning will fail
if (oldHeight > 0) {
shiftSpacerPositionsAfterRow(rowIndex, -oldHeight);
body.shiftRowPositions(rowIndex, -oldHeight);
}
delayRepositioning = false;
}
}

@SuppressWarnings("boxing")
void scrollToSpacer(int spacerIndex, ScrollDestination destination,
int padding) {
Expand Down
11 changes: 11 additions & 0 deletions client/src/main/java/com/vaadin/client/widgets/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -9661,6 +9661,17 @@ public boolean isDetailsVisible(int rowIndex) {
return visibleDetails.contains(Integer.valueOf(rowIndex));
}

/**
* Reset the details row with current contents.
*
* @since
* @param rowIndex
* the index of the row for which details should be reset
*/
public void resetVisibleDetails(int rowIndex) {
escalator.getBody().resetSpacer(rowIndex);
}

/**
* Update details row height.
*
Expand Down
10 changes: 10 additions & 0 deletions server/src/main/java/com/vaadin/ui/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -4997,7 +4997,17 @@ protected SerializableComparator<T> createSortingComparator() {

@Override
protected void internalSetDataProvider(DataProvider<T, ?> dataProvider) {
boolean newProvider = getDataProvider() != dataProvider;
super.internalSetDataProvider(dataProvider);
if (newProvider) {
Set<T> oldVisibleDetails = new HashSet<>(
detailsManager.visibleDetails);
oldVisibleDetails.forEach(item -> {
// close all old details even if the same item exists in the new
// provider
detailsManager.setDetailsVisible(item, false);
});
}
for (Column<T, ?> column : getColumns()) {
column.updateSortable();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.vaadin.tests.components.grid;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.vaadin.data.ValueProvider;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;

public class GridDetailsUpdateItems extends AbstractTestUI {

@Override
protected void setup(VaadinRequest request) {
addComponent(createExamplleLayout());
}

private VerticalLayout createExamplleLayout() {
Collection<String> firstCollection = Arrays.asList("Hello", ",",
"world!");
Collection<String> secondCollection = Arrays.asList("My", "name", "is",
"Sarah");
Collection<String> thirdCollection = Arrays.asList("red", "blue");
Collection<String> fourthCollection = Arrays.asList("spring", "summer",
"autumn", "winter");

VerticalLayout mainLayout = new VerticalLayout();
Grid<Collection<String>> grid = new Grid<>();
grid.setDetailsGenerator(collection -> {
VerticalLayout detailLayout = new VerticalLayout();
collection.forEach(
item -> detailLayout.addComponent(new Label(item)));
return detailLayout;
});
ValueProvider<Collection<String>, String> valueProvider = collection -> String
.join(" ", collection);
grid.addColumn(valueProvider).setCaption("Header");

List<Collection<String>> itemsInitial = Arrays.asList(firstCollection,
secondCollection, thirdCollection, fourthCollection);
grid.setItems(itemsInitial);
for (Collection<String> tmp : itemsInitial) {
grid.setDetailsVisible(tmp, true);
}
mainLayout.addComponent(grid);

Button clickButton = new Button("Change items", event -> {
List<Collection<String>> itemsOverwrite = Arrays
.asList(secondCollection, fourthCollection);
grid.setItems(itemsOverwrite);
for (Collection<String> tmp : itemsOverwrite) {
grid.setDetailsVisible(tmp, true);
}
});
mainLayout.addComponent(clickButton);

return mainLayout;
}

@Override
protected Integer getTicketNumber() {
return 12211;
}

@Override
protected String getTestDescription() {
return "Details should update and not break the positioning "
+ "when the item set is changed.";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ public boolean spacerExists(int rowIndex) {
return rowContainer.spacerExists(rowIndex);
}

@Override
public void resetSpacer(int rowIndex) {
rowContainer.resetSpacer(rowIndex);
}

@Override
public void setSpacerUpdater(SpacerUpdater spacerUpdater)
throws IllegalArgumentException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.vaadin.tests.components.grid;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.number.IsCloseTo.closeTo;
import static org.junit.Assert.assertNotEquals;

import org.junit.Test;

import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.GridElement;
import com.vaadin.testbench.elements.GridElement.GridCellElement;
import com.vaadin.tests.tb3.MultiBrowserTest;

public class GridDetailsUpdateItemsTest extends MultiBrowserTest {

@Test
public void testDetailsUpdateWithItems() {
openTestURL();
GridElement grid = $(GridElement.class).first();
ButtonElement button = $(ButtonElement.class).first();

String details0 = grid.getDetails(0).getText();
System.out.println("details: " + details0);

// change the contents
button.click();
sleep(200);

TestBenchElement detailCell0 = grid.getDetails(0);
// ensure contents have updated
String updatedDetails0 = detailCell0.getText();
assertNotEquals("Details should not be empty", "", updatedDetails0);
assertNotEquals("Unexpected detail contents for row 0", details0,
updatedDetails0);

GridCellElement cell1_0 = grid.getCell(1, 0);
TestBenchElement detailCell1 = grid.getDetails(1);

// ensure positioning is correct
assertDirectlyAbove(detailCell0, cell1_0);
assertDirectlyAbove(cell1_0, detailCell1);
}

private void assertDirectlyAbove(TestBenchElement above,
TestBenchElement below) {
int aboveBottom = above.getLocation().getY()
+ above.getSize().getHeight();
int belowTop = below.getLocation().getY();
assertThat("Unexpected positions.", (double) aboveBottom,
closeTo(belowTop, 1d));
}
}