Change-Id: I4872766d9ed49d4a0765d28ed00e84cecf24dda4tags/7.4.0.beta1
"topRowLogicalIndex: " + this.topRowLogicalIndex | "topRowLogicalIndex: " + this.topRowLogicalIndex | ||||
+ " -> " + topRowLogicalIndex); | + " -> " + topRowLogicalIndex); | ||||
} | } | ||||
assert topRowLogicalIndex >= 0 : "topRowLogicalIndex became negative"; | |||||
assert topRowLogicalIndex >= 0 : "topRowLogicalIndex became negative (top left cell contents: " | |||||
+ visualRowOrder.getFirst().getCells().getItem(0) | |||||
.getInnerText() + ") "; | |||||
/* | /* | ||||
* if there's a smart way of evaluating and asserting the max index, | * if there's a smart way of evaluating and asserting the max index, | ||||
* this would be a nice place to put it. I haven't found out an | * this would be a nice place to put it. I haven't found out an | ||||
removedVisualInside, 0); | removedVisualInside, 0); | ||||
} | } | ||||
else if (removedVisualInside.contains(0) | |||||
&& numberOfRows >= visualRowOrder.size()) { | |||||
/* | |||||
* We're removing so many rows that the viewport is | |||||
* pushed up more than a screenful. This means we can | |||||
* simply scroll up and everything will work without a | |||||
* sweat. | |||||
*/ | |||||
double left = horizontalScrollbar.getScrollPos(); | |||||
int top = contentBottom - visualRowOrder.size() | |||||
* getDefaultRowHeight(); | |||||
setBodyScrollPosition(left, top); | |||||
Range allEscalatorRows = Range.withLength(0, | |||||
visualRowOrder.size()); | |||||
int logicalTargetIndex = getRowCount() | |||||
- allEscalatorRows.length(); | |||||
moveAndUpdateEscalatorRows(allEscalatorRows, 0, | |||||
logicalTargetIndex); | |||||
/* | |||||
* Scrolling the body to the correct location will be | |||||
* fixed automatically. Because the amount of rows is | |||||
* decreased, the viewport is pushed up as the scrollbar | |||||
* shrinks. So no need to do anything there. | |||||
* | |||||
* TODO [[optimize]]: This might lead to a double body | |||||
* refresh. Needs investigation. | |||||
*/ | |||||
} | |||||
else if (contentBottom | else if (contentBottom | ||||
+ (numberOfRows * getDefaultRowHeight()) | + (numberOfRows * getDefaultRowHeight()) | ||||
- viewportBottom < getDefaultRowHeight()) { | - viewportBottom < getDefaultRowHeight()) { | ||||
/* | /* | ||||
* FIXME [[rowheight]]: above coded to work only with | |||||
* default row heights - will not work with variable row | |||||
* heights | |||||
* We're at the end of the row container, everything is | |||||
* added to the top. | |||||
*/ | */ | ||||
/* | /* | ||||
* We're at the end of the row container, everything is | |||||
* added to the top. | |||||
* FIXME [[rowheight]]: above if-clause is coded to only | |||||
* work with default row heights - will not work with | |||||
* variable row heights | |||||
*/ | */ | ||||
paintRemoveRowsAtBottom(removedLogicalInside, | paintRemoveRowsAtBottom(removedLogicalInside, | ||||
removedVisualInside); | removedVisualInside); | ||||
updateTopRowLogicalIndex(-removedLogicalInside.length()); | updateTopRowLogicalIndex(-removedLogicalInside.length()); |
protected static final String ADD_ONE_ROW_TO_BEGINNING = "Add one row to beginning"; | protected static final String ADD_ONE_ROW_TO_BEGINNING = "Add one row to beginning"; | ||||
protected static final String REMOVE_ONE_COLUMN_FROM_BEGINNING = "Remove one column from beginning"; | protected static final String REMOVE_ONE_COLUMN_FROM_BEGINNING = "Remove one column from beginning"; | ||||
protected static final String REMOVE_ONE_ROW_FROM_BEGINNING = "Remove one row from beginning"; | protected static final String REMOVE_ONE_ROW_FROM_BEGINNING = "Remove one row from beginning"; | ||||
protected static final String REMOVE_50_ROWS_FROM_BOTTOM = "Remove 50 rows from bottom"; | |||||
protected static final String REMOVE_50_ROWS_FROM_ALMOST_BOTTOM = "Remove 50 rows from almost bottom"; | |||||
protected static final String ADD_ONE_OF_EACH_ROW = "Add one of each row"; | protected static final String ADD_ONE_OF_EACH_ROW = "Add one of each row"; | ||||
protected static final String RESIZE_FIRST_COLUMN_TO_MAX_WIDTH = "Resize first column to max width"; | protected static final String RESIZE_FIRST_COLUMN_TO_MAX_WIDTH = "Resize first column to max width"; | ||||
} | } | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
protected WebElement getHeaderRow(int row) { | protected WebElement getHeaderRow(int row) { | ||||
return getRow("thead", row); | return getRow("thead", row); | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
protected WebElement getBodyRow(int row) { | protected WebElement getBodyRow(int row) { | ||||
return getRow("tbody", row); | return getRow("tbody", row); | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
protected WebElement getFooterRow(int row) { | protected WebElement getFooterRow(int row) { | ||||
return getRow("tfoot", row); | return getRow("tfoot", row); | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
protected WebElement getHeaderCell(int row, int col) { | protected WebElement getHeaderCell(int row, int col) { | ||||
return getCell("thead", row, col); | return getCell("thead", row, col); | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
protected WebElement getBodyCell(int row, int col) { | protected WebElement getBodyCell(int row, int col) { | ||||
return getCell("tbody", row, col); | return getCell("tbody", row, col); | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
protected WebElement getFooterCell(int row, int col) { | protected WebElement getFooterCell(int row, int col) { | ||||
return getCell("tfoot", row, col); | return getCell("tfoot", row, col); | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
private WebElement getCell(String sectionTag, int row, int col) { | private WebElement getCell(String sectionTag, int row, int col) { | ||||
WebElement rowElement = getRow(sectionTag, row); | WebElement rowElement = getRow(sectionTag, row); | ||||
if (rowElement != null) { | if (rowElement != null) { | ||||
} | } | ||||
} | } | ||||
/** | |||||
* @param row | |||||
* the index of the row element in the section. If negative, the | |||||
* calculation starts from the end (-1 is the last, -2 is the | |||||
* second-to-last etc) | |||||
*/ | |||||
private WebElement getRow(String sectionTag, int row) { | private WebElement getRow(String sectionTag, int row) { | ||||
WebElement escalator = getEscalator(); | WebElement escalator = getEscalator(); | ||||
WebElement tableSection = escalator.findElement(By.tagName(sectionTag)); | WebElement tableSection = escalator.findElement(By.tagName(sectionTag)); | ||||
try { | try { | ||||
return tableSection.findElement(By.xpath("tr[" + (row + 1) + "]")); | |||||
if (row >= 0) { | |||||
int fromFirst = row + 1; | |||||
return tableSection.findElement(By.xpath("tr[" + fromFirst | |||||
+ "]")); | |||||
} else { | |||||
int fromLast = Math.abs(row + 1); | |||||
return tableSection.findElement(By.xpath("tr[last() - " | |||||
+ fromLast + "]")); | |||||
} | |||||
} catch (NoSuchElementException e) { | } catch (NoSuchElementException e) { | ||||
return null; | return null; | ||||
} | } |
*/ | */ | ||||
package com.vaadin.tests.components.grid.basicfeatures; | package com.vaadin.tests.components.grid.basicfeatures; | ||||
import static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assert.assertNotEquals; | import static org.junit.Assert.assertNotEquals; | ||||
import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||
import static org.junit.Assert.assertNull; | import static org.junit.Assert.assertNull; | ||||
public class EscalatorRowColumnTest extends EscalatorBasicClientFeaturesTest { | public class EscalatorRowColumnTest extends EscalatorBasicClientFeaturesTest { | ||||
/** | |||||
* The scroll position of the Escalator when scrolled all the way down, to | |||||
* reveal the 100:th row. | |||||
*/ | |||||
private static final int BOTTOM_SCROLL_POSITION = 1857; | |||||
@Test | @Test | ||||
public void testInit() { | public void testInit() { | ||||
openTestURL(); | openTestURL(); | ||||
assertNotEquals("Column width should've changed", originalWidth, | assertNotEquals("Column width should've changed", originalWidth, | ||||
newWidth); | newWidth); | ||||
} | } | ||||
@Test | |||||
public void testRemoveMoreThanPagefulAtBottomWhileScrolledToBottom() | |||||
throws Exception { | |||||
openTestURL(); | |||||
selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); | |||||
scrollVerticallyTo(BOTTOM_SCROLL_POSITION); | |||||
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_50_ROWS_FROM_BOTTOM); | |||||
assertEquals("Row 49: 0,49", getBodyCell(-1, 0).getText()); | |||||
scrollVerticallyTo(0); | |||||
// let the DOM organize itself | |||||
Thread.sleep(500); | |||||
// if something goes wrong, it'll explode before this. | |||||
assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText()); | |||||
} | |||||
@Test | |||||
public void testRemoveMoreThanPagefulAtBottomWhileScrolledAlmostToBottom() | |||||
throws Exception { | |||||
openTestURL(); | |||||
selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); | |||||
// bottom minus 15 rows. | |||||
scrollVerticallyTo(BOTTOM_SCROLL_POSITION - 15 * 20); | |||||
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_50_ROWS_FROM_BOTTOM); | |||||
assertEquals("Row 49: 0,49", getBodyCell(-1, 0).getText()); | |||||
scrollVerticallyTo(0); | |||||
// let the DOM organize itself | |||||
Thread.sleep(500); | |||||
// if something goes wrong, it'll explode before this. | |||||
assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText()); | |||||
} | |||||
@Test | |||||
public void testRemoveMoreThanPagefulNearBottomWhileScrolledToBottom() | |||||
throws Exception { | |||||
openTestURL(); | |||||
selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); | |||||
scrollVerticallyTo(BOTTOM_SCROLL_POSITION); | |||||
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, | |||||
REMOVE_50_ROWS_FROM_ALMOST_BOTTOM); | |||||
assertEquals("Row 49: 0,99", getBodyCell(-1, 0).getText()); | |||||
scrollVerticallyTo(0); | |||||
// let the DOM organize itself | |||||
Thread.sleep(500); | |||||
// if something goes wrong, it'll explode before this. | |||||
assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText()); | |||||
} | |||||
@Test | |||||
public void testRemoveMoreThanPagefulNearBottomWhileScrolledAlmostToBottom() | |||||
throws Exception { | |||||
openTestURL(); | |||||
selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); | |||||
// bottom minus 15 rows. | |||||
scrollVerticallyTo(BOTTOM_SCROLL_POSITION - 15 * 20); | |||||
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, | |||||
REMOVE_50_ROWS_FROM_ALMOST_BOTTOM); | |||||
// let the DOM organize itself | |||||
Thread.sleep(500); | |||||
assertEquals("Row 49: 0,99", getBodyCell(-1, 0).getText()); | |||||
scrollVerticallyTo(0); | |||||
// let the DOM organize itself | |||||
Thread.sleep(500); | |||||
// if something goes wrong, it'll explode before this. | |||||
assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText()); | |||||
} | |||||
} | } |
.getRowCount() - 50, 50); | .getRowCount() - 50, 50); | ||||
} | } | ||||
}, menupath); | }, menupath); | ||||
addMenuCommand("Remove 50 rows from almost bottom", | |||||
new ScheduledCommand() { | |||||
@Override | |||||
public void execute() { | |||||
removeRows(escalator.getBody(), escalator.getBody() | |||||
.getRowCount() - 60, 50); | |||||
} | |||||
}, menupath); | |||||
addMenuCommand("Remove all, insert 30 and scroll 40px", | addMenuCommand("Remove all, insert 30 and scroll 40px", | ||||
new ScheduledCommand() { | new ScheduledCommand() { | ||||
@Override | @Override |