* Rename getMaxEscalatorRowCapacity to describe what it does * Always calculate Escalator max row count the same way This changes Escalator to not take a horizontal scrollbar into account when trying to determine "maximum visible rows". This will add another row, compared to previous versions, when there is a horizontal scrollbar. In reality, it would likely make sense to always add 10 more rows to have some buffer above and below the visible area. Fixes #8661tags/8.1.0.alpha1
@@ -2970,7 +2970,7 @@ public class Escalator extends Widget | |||
private List<TableRowElement> fillAndPopulateEscalatorRowsIfNeeded( | |||
final int index, final int numberOfRows) { | |||
final int escalatorRowsStillFit = getMaxEscalatorRowCapacity() | |||
final int escalatorRowsStillFit = getMaxVisibleRowCount() | |||
- getDomRowCount(); | |||
final int escalatorRowsNeeded = Math.min(numberOfRows, | |||
escalatorRowsStillFit); | |||
@@ -3003,16 +3003,22 @@ public class Escalator extends Widget | |||
} | |||
} | |||
private int getMaxEscalatorRowCapacity() { | |||
final int maxEscalatorRowCapacity = (int) Math | |||
.ceil(getHeightOfSection() / getDefaultRowHeight()) + 1; | |||
private int getMaxVisibleRowCount() { | |||
double heightOfSection = getHeightOfSection(); | |||
// By including the possibly shown scrollbar height, we get a | |||
// consistent count and do not add/remove rows whenever a scrollbar | |||
// is shown | |||
heightOfSection += horizontalScrollbarDeco.getOffsetHeight(); | |||
double defaultRowHeight = getDefaultRowHeight(); | |||
final int maxVisibleRowCount = (int) Math | |||
.ceil(heightOfSection / defaultRowHeight) + 1; | |||
/* | |||
* maxEscalatorRowCapacity can become negative if the headers and | |||
* footers start to overlap. This is a crazy situation, but Vaadin | |||
* blinks the components a lot, so it's feasible. | |||
* maxVisibleRowCount can become negative if the headers and footers | |||
* start to overlap. This is a crazy situation, but Vaadin blinks | |||
* the components a lot, so it's feasible. | |||
*/ | |||
return Math.max(0, maxEscalatorRowCapacity); | |||
return Math.max(0, maxVisibleRowCount); | |||
} | |||
@Override | |||
@@ -3489,12 +3495,12 @@ public class Escalator extends Widget | |||
* TODO [[spacer]]: these assumptions will be totally broken with | |||
* spacers. | |||
*/ | |||
final int maxEscalatorRows = getMaxEscalatorRowCapacity(); | |||
final int maxVisibleRowCount = getMaxVisibleRowCount(); | |||
final int currentTopRowIndex = getLogicalRowIndex( | |||
visualRowOrder.getFirst()); | |||
final Range[] partitions = logicalRange.partitionWith( | |||
Range.withLength(currentTopRowIndex, maxEscalatorRows)); | |||
Range.withLength(currentTopRowIndex, maxVisibleRowCount)); | |||
final Range insideRange = partitions[1]; | |||
return insideRange.offsetBy(-currentTopRowIndex); | |||
} | |||
@@ -3606,8 +3612,8 @@ public class Escalator extends Widget | |||
return; | |||
} | |||
final int maxEscalatorRows = getMaxEscalatorRowCapacity(); | |||
final int neededEscalatorRows = Math.min(maxEscalatorRows, | |||
final int maxVisibleRowCount = getMaxVisibleRowCount(); | |||
final int neededEscalatorRows = Math.min(maxVisibleRowCount, | |||
body.getRowCount()); | |||
final int neededEscalatorRowsDiff = neededEscalatorRows | |||
- visualRowOrder.size(); | |||
@@ -6646,7 +6652,7 @@ public class Escalator extends Widget | |||
* @return the maximum capacity | |||
*/ | |||
public int getMaxVisibleRowCount() { | |||
return body.getMaxEscalatorRowCapacity(); | |||
return body.getMaxVisibleRowCount(); | |||
} | |||
/** |
@@ -2982,7 +2982,7 @@ public class Escalator extends Widget | |||
private List<TableRowElement> fillAndPopulateEscalatorRowsIfNeeded( | |||
final int index, final int numberOfRows) { | |||
final int escalatorRowsStillFit = getMaxEscalatorRowCapacity() | |||
final int escalatorRowsStillFit = getMaxVisibleRowCount() | |||
- getDomRowCount(); | |||
final int escalatorRowsNeeded = Math.min(numberOfRows, | |||
escalatorRowsStillFit); | |||
@@ -3015,16 +3015,22 @@ public class Escalator extends Widget | |||
} | |||
} | |||
private int getMaxEscalatorRowCapacity() { | |||
final int maxEscalatorRowCapacity = (int) Math | |||
.ceil(getHeightOfSection() / getDefaultRowHeight()) + 1; | |||
private int getMaxVisibleRowCount() { | |||
double heightOfSection = getHeightOfSection(); | |||
// By including the possibly shown scrollbar height, we get a | |||
// consistent count and do not add/remove rows whenever a scrollbar | |||
// is shown | |||
heightOfSection += horizontalScrollbarDeco.getOffsetHeight(); | |||
double defaultRowHeight = getDefaultRowHeight(); | |||
final int maxVisibleRowCount = (int) Math | |||
.ceil(heightOfSection / defaultRowHeight) + 1; | |||
/* | |||
* maxEscalatorRowCapacity can become negative if the headers and | |||
* footers start to overlap. This is a crazy situation, but Vaadin | |||
* blinks the components a lot, so it's feasible. | |||
* maxVisibleRowCount can become negative if the headers and footers | |||
* start to overlap. This is a crazy situation, but Vaadin blinks | |||
* the components a lot, so it's feasible. | |||
*/ | |||
return Math.max(0, maxEscalatorRowCapacity); | |||
return Math.max(0, maxVisibleRowCount); | |||
} | |||
@Override | |||
@@ -3507,12 +3513,12 @@ public class Escalator extends Widget | |||
* TODO [[spacer]]: these assumptions will be totally broken with | |||
* spacers. | |||
*/ | |||
final int maxEscalatorRows = getMaxEscalatorRowCapacity(); | |||
final int maxVisibleRowCount = getMaxVisibleRowCount(); | |||
final int currentTopRowIndex = getLogicalRowIndex( | |||
visualRowOrder.getFirst()); | |||
final Range[] partitions = logicalRange.partitionWith( | |||
Range.withLength(currentTopRowIndex, maxEscalatorRows)); | |||
Range.withLength(currentTopRowIndex, maxVisibleRowCount)); | |||
final Range insideRange = partitions[1]; | |||
return insideRange.offsetBy(-currentTopRowIndex); | |||
} | |||
@@ -3624,8 +3630,8 @@ public class Escalator extends Widget | |||
return; | |||
} | |||
final int maxEscalatorRows = getMaxEscalatorRowCapacity(); | |||
final int neededEscalatorRows = Math.min(maxEscalatorRows, | |||
final int maxVisibleRowCount = getMaxVisibleRowCount(); | |||
final int neededEscalatorRows = Math.min(maxVisibleRowCount, | |||
body.getRowCount()); | |||
final int neededEscalatorRowsDiff = neededEscalatorRows | |||
- visualRowOrder.size(); | |||
@@ -6673,7 +6679,7 @@ public class Escalator extends Widget | |||
* @return the maximum capacity | |||
*/ | |||
public int getMaxVisibleRowCount() { | |||
return body.getMaxEscalatorRowCapacity(); | |||
return body.getMaxVisibleRowCount(); | |||
} | |||
/** |
@@ -0,0 +1,92 @@ | |||
package com.vaadin.v7.tests.components.grid; | |||
import com.vaadin.annotations.Theme; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.v7.data.Item; | |||
import com.vaadin.v7.data.util.BeanItemContainer; | |||
import com.vaadin.v7.data.util.GeneratedPropertyContainer; | |||
import com.vaadin.v7.data.util.PropertyValueGenerator; | |||
import com.vaadin.v7.ui.Grid; | |||
import com.vaadin.v7.ui.Grid.Column; | |||
import com.vaadin.v7.ui.renderers.ButtonRenderer; | |||
@Theme("valo") | |||
public class HideGridColumnWhenHavingUnsuitableHeight extends AbstractTestUI { | |||
private Grid grid; | |||
public static class SampleBean { | |||
private String col1; | |||
private String col2; | |||
public SampleBean() { | |||
} | |||
public String getCol1() { | |||
return col1; | |||
} | |||
public void setCol1(String col1) { | |||
this.col1 = col1; | |||
} | |||
public String getCol2() { | |||
return col2; | |||
} | |||
public void setCol2(String col2) { | |||
this.col2 = col2; | |||
} | |||
} | |||
@SuppressWarnings("serial") | |||
@Override | |||
protected void setup(VaadinRequest vaadinRequest) { | |||
grid = new Grid(); | |||
BeanItemContainer<SampleBean> container = generateData(50); | |||
GeneratedPropertyContainer gpc = new GeneratedPropertyContainer( | |||
container); | |||
grid.setContainerDataSource(gpc); | |||
gpc.addGeneratedProperty("Button1", | |||
new PropertyValueGenerator<String>() { | |||
@Override | |||
public String getValue(Item item, Object itemId, | |||
Object propertyId) { | |||
return "Button 1"; | |||
} | |||
@Override | |||
public Class<String> getType() { | |||
return String.class; | |||
} | |||
}); | |||
grid.getColumn("Button1").setRenderer(new ButtonRenderer()); | |||
grid.getColumn("col1").setWidth(1600); | |||
for (Column gridCol : grid.getColumns()) { | |||
gridCol.setHidable(true); | |||
} | |||
grid.setWidth("100%"); | |||
grid.setHeight("425px"); | |||
grid.setColumns("col1", "col2", "Button1"); | |||
addComponent(grid); | |||
} | |||
private BeanItemContainer<SampleBean> generateData(int rows) { | |||
BeanItemContainer<SampleBean> container = new BeanItemContainer<SampleBean>( | |||
SampleBean.class); | |||
for (int y = 0; y < rows; ++y) { | |||
SampleBean sampleBean = new SampleBean(); | |||
sampleBean.setCol1("Row " + y + " Column 1"); | |||
sampleBean.setCol2("Row " + y + " Column 2"); | |||
container.addBean(sampleBean); | |||
} | |||
return container; | |||
} | |||
} |
@@ -290,12 +290,12 @@ public class EscalatorSpacerTest extends EscalatorBasicClientFeaturesTest { | |||
selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX); | |||
/* | |||
* we check for row -2 instead of -1, because escalator has the one row | |||
* we check for row -3 instead of -1, because escalator has two rows | |||
* buffered underneath the footer | |||
*/ | |||
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, SCROLL_TO, ROW_75); | |||
Thread.sleep(500); | |||
assertEquals("Row 75: 0,75", getBodyCell(-2, 0).getText()); | |||
assertEquals("Row 75: 0,75", getBodyCell(-3, 0).getText()); | |||
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, SCROLL_TO, ROW_25); | |||
Thread.sleep(500); |
@@ -0,0 +1,46 @@ | |||
/* | |||
* 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.basics; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | |||
import org.junit.Test; | |||
import com.vaadin.testbench.elements.GridElement; | |||
public class GridScrollTest extends GridBasicsTest { | |||
@Test | |||
public void workPendingWhileScrolling() { | |||
openTestURL("theme=valo"); | |||
String script = "var c = window.vaadin.clients.runcomvaadintestscomponentsgridbasicsGridBasics;\n" | |||
// Scroll down and cause lazy loading | |||
+ "c.getElementByPath(\"//Grid[0]#cell[21]\"); \n" | |||
+ "return c.isActive();"; | |||
Boolean active = (Boolean) executeScript(script); | |||
assertTrue("Grid should be marked to have workPending while scrolling", | |||
active); | |||
} | |||
@Test | |||
public void scrollIntoViewThroughSubPart() { | |||
openTestURL("theme=valo"); | |||
GridElement grid = $(GridElement.class).first(); | |||
assertEquals("(10, 0)", grid.getCell(10, 0).getText()); | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
package com.vaadin.v7.tests.components.grid; | |||
import java.util.List; | |||
import java.util.logging.Level; | |||
import org.junit.Test; | |||
import org.openqa.selenium.By; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.testbench.elements.GridElement; | |||
import com.vaadin.tests.tb3.SingleBrowserTest; | |||
public class HideGridColumnWhenHavingUnsuitableHeightTest | |||
extends SingleBrowserTest { | |||
@Test | |||
public void hideAndScroll() { | |||
openTestURL("debug"); | |||
GridElement grid = $(GridElement.class).first(); | |||
getSidebarOpenButton(grid).click(); | |||
// Hide first column | |||
getSidebarPopup().findElements(By.tagName("td")).get(0).click(); | |||
grid.scrollToRow(25); | |||
assertNoDebugMessage(Level.SEVERE); | |||
} | |||
protected WebElement getSidebarOpenButton(GridElement grid) { | |||
List<WebElement> elements = grid | |||
.findElements(By.className("v-grid-sidebar-button")); | |||
return elements.isEmpty() ? null : elements.get(0); | |||
} | |||
protected WebElement getSidebarPopup() { | |||
List<WebElement> elements = findElements( | |||
By.className("v-grid-sidebar-popup")); | |||
return elements.isEmpty() ? null : elements.get(0); | |||
} | |||
} |