Change-Id: I8fa99a96c2120583bb1ecd152f8f337aef702614tags/7.2.0.beta1
@@ -17,6 +17,7 @@ | |||
@import "embedded/embedded.scss"; | |||
@import "escalator/escalator.scss"; | |||
@import "formlayout/formlayout.scss"; | |||
@import "grid/grid.scss"; | |||
@import "gridlayout/gridlayout.scss"; | |||
@import "label/label.scss"; | |||
@import "link/link.scss"; | |||
@@ -87,6 +88,7 @@ $line-height: normal; | |||
@include base-embedded; | |||
@include base-escalator; | |||
@include base-formlayout; | |||
@include base-grid; | |||
@include base-gridlayout; | |||
@include base-label; | |||
@include base-link; |
@@ -0,0 +1,3 @@ | |||
@mixin base-grid($primaryStyleName : v-grid) { | |||
@include base-escalator($primaryStyleName); | |||
} |
@@ -39,6 +39,7 @@ import com.google.gwt.event.logical.shared.AttachEvent; | |||
import com.google.gwt.user.client.DOM; | |||
import com.google.gwt.user.client.Element; | |||
import com.google.gwt.user.client.Window; | |||
import com.google.gwt.user.client.ui.UIObject; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.google.web.bindery.event.shared.HandlerRegistration; | |||
import com.vaadin.client.Profiler; | |||
@@ -50,6 +51,7 @@ import com.vaadin.client.ui.grid.PositionFunction.TranslatePosition; | |||
import com.vaadin.client.ui.grid.PositionFunction.WebkitTranslate3DPosition; | |||
import com.vaadin.client.ui.grid.ScrollbarBundle.HorizontalScrollbarBundle; | |||
import com.vaadin.client.ui.grid.ScrollbarBundle.VerticalScrollbarBundle; | |||
import com.vaadin.shared.util.SharedUtil; | |||
/*- | |||
@@ -895,8 +897,6 @@ public class Escalator extends Widget { | |||
} | |||
} | |||
static final String CLASS_NAME = "v-escalator"; | |||
private abstract class AbstractRowContainer implements RowContainer { | |||
private EscalatorUpdater updater = EscalatorUpdater.NULL; | |||
@@ -911,6 +911,12 @@ public class Escalator extends Widget { | |||
/** The height of the combined rows in the DOM. */ | |||
protected double height = -1; | |||
/** | |||
* The primary style name of the escalator. Most commonly provided by | |||
* Escalator as "v-escalator". | |||
*/ | |||
private String primaryStyleName = null; | |||
public AbstractRowContainer(final Element rowContainerElement) { | |||
root = rowContainerElement; | |||
} | |||
@@ -1087,7 +1093,7 @@ public class Escalator extends Widget { | |||
final int rowHeight = ROW_HEIGHT_PX; | |||
final Element tr = DOM.createTR(); | |||
addedRows.add(tr); | |||
tr.addClassName(CLASS_NAME + "-row"); | |||
tr.addClassName(getStylePrimaryName() + "-row"); | |||
referenceRow = insertAfterReferenceAndUpdateIt(root, tr, | |||
referenceRow); | |||
@@ -1209,7 +1215,7 @@ public class Escalator extends Widget { | |||
final Element cellElem = DOM.createElement(getCellElementTagName()); | |||
cellElem.getStyle().setHeight(height, Unit.PX); | |||
cellElem.getStyle().setWidth(width, Unit.PX); | |||
cellElem.addClassName(CLASS_NAME + "-cell"); | |||
cellElem.addClassName(getStylePrimaryName() + "-cell"); | |||
return cellElem; | |||
} | |||
@@ -1461,6 +1467,47 @@ public class Escalator extends Widget { | |||
row = row.getNextSiblingElement(); | |||
} | |||
} | |||
/** | |||
* The primary style name for the container. | |||
* | |||
* @param primaryStyleName | |||
* the style name to use as prefix for all row and cell style | |||
* names. | |||
*/ | |||
protected void setStylePrimaryName(String primaryStyleName) { | |||
String oldStyle = getStylePrimaryName(); | |||
if (SharedUtil.equals(oldStyle, primaryStyleName)) { | |||
return; | |||
} | |||
this.primaryStyleName = primaryStyleName; | |||
// Update already rendered rows and cells | |||
Node row = root.getFirstChild(); | |||
while (row != null) { | |||
Element rowElement = row.cast(); | |||
UIObject.setStylePrimaryName(rowElement, primaryStyleName | |||
+ "-row"); | |||
Node cell = row.getFirstChild(); | |||
while (cell != null) { | |||
Element cellElement = cell.cast(); | |||
UIObject.setStylePrimaryName(cellElement, primaryStyleName | |||
+ "-cell"); | |||
cell = cell.getNextSibling(); | |||
} | |||
row = row.getNextSibling(); | |||
} | |||
} | |||
/** | |||
* Returns the primary style name of the container. | |||
* | |||
* @return The primary style name or <code>null</code> if not set. | |||
*/ | |||
protected String getStylePrimaryName() { | |||
return primaryStyleName; | |||
} | |||
} | |||
private abstract class AbstractStaticRowContainer extends | |||
@@ -1525,6 +1572,12 @@ public class Escalator extends Widget { | |||
protected String getCellElementTagName() { | |||
return "th"; | |||
} | |||
@Override | |||
public void setStylePrimaryName(String primaryStyleName) { | |||
super.setStylePrimaryName(primaryStyleName); | |||
UIObject.setStylePrimaryName(root, primaryStyleName + "-header"); | |||
} | |||
} | |||
private class FooterRowContainer extends AbstractStaticRowContainer { | |||
@@ -1532,6 +1585,12 @@ public class Escalator extends Widget { | |||
super(footElement); | |||
} | |||
@Override | |||
public void setStylePrimaryName(String primaryStyleName) { | |||
super.setStylePrimaryName(primaryStyleName); | |||
UIObject.setStylePrimaryName(root, primaryStyleName + "-footer"); | |||
} | |||
@Override | |||
protected String getCellElementTagName() { | |||
return "td"; | |||
@@ -1564,6 +1623,12 @@ public class Escalator extends Widget { | |||
super(bodyElement); | |||
} | |||
@Override | |||
public void setStylePrimaryName(String primaryStyleName) { | |||
super.setStylePrimaryName(primaryStyleName); | |||
UIObject.setStylePrimaryName(root, primaryStyleName + "-body"); | |||
} | |||
public void updateEscalatorRowsOnScroll() { | |||
if (visualRowOrder.isEmpty()) { | |||
return; | |||
@@ -2952,7 +3017,6 @@ public class Escalator extends Widget { | |||
final Element root = DOM.createDiv(); | |||
setElement(root); | |||
setStyleName(CLASS_NAME); | |||
root.appendChild(verticalScrollbar.getElement()); | |||
root.appendChild(horizontalScrollbar.getElement()); | |||
@@ -2961,21 +3025,18 @@ public class Escalator extends Widget { | |||
.setScrollbarThickness(Util.getNativeScrollbarSize()); | |||
tableWrapper = DOM.createDiv(); | |||
tableWrapper.setClassName(CLASS_NAME + "-tablewrapper"); | |||
root.appendChild(tableWrapper); | |||
final Element table = DOM.createTable(); | |||
tableWrapper.appendChild(table); | |||
headElem.setClassName(CLASS_NAME + "-header"); | |||
table.appendChild(headElem); | |||
bodyElem.setClassName(CLASS_NAME + "-body"); | |||
table.appendChild(bodyElem); | |||
footElem.setClassName(CLASS_NAME + "-footer"); | |||
table.appendChild(footElem); | |||
setStylePrimaryName("v-escalator"); | |||
/* | |||
* Size calculations work only after the Escalator has been attached to | |||
* the DOM. It doesn't matter if the table is populated or not by this | |||
@@ -3479,4 +3540,18 @@ public class Escalator extends Widget { | |||
recalculateElementSizes(); | |||
} | |||
} | |||
@Override | |||
public void setStylePrimaryName(String style) { | |||
super.setStylePrimaryName(style); | |||
verticalScrollbar.setStylePrimaryName(style); | |||
horizontalScrollbar.setStylePrimaryName(style); | |||
UIObject.setStylePrimaryName(tableWrapper, style + "-tablewrapper"); | |||
header.setStylePrimaryName(style); | |||
body.setStylePrimaryName(style); | |||
footer.setStylePrimaryName(style); | |||
} | |||
} |
@@ -476,6 +476,8 @@ public class Grid<T> extends Composite { | |||
public Grid() { | |||
initWidget(escalator); | |||
setStylePrimaryName("v-grid"); | |||
escalator.getHeader().setEscalatorUpdater(createHeaderUpdater()); | |||
escalator.getBody().setEscalatorUpdater(createBodyUpdater()); | |||
escalator.getFooter().setEscalatorUpdater(createFooterUpdater()); | |||
@@ -498,6 +500,13 @@ public class Grid<T> extends Composite { | |||
} | |||
@Override | |||
public void setStylePrimaryName(String style) { | |||
super.setStylePrimaryName(style); | |||
escalator.setStylePrimaryName(style); | |||
} | |||
/** | |||
* Creates the header updater that updates the escalator header rows from | |||
* the column and column group rows. |
@@ -31,7 +31,6 @@ import com.google.gwt.user.client.Element; | |||
* @see HorizontalScrollbarBundle | |||
*/ | |||
abstract class ScrollbarBundle { | |||
private static final String CLASS_NAME = Escalator.CLASS_NAME + "-scroller"; | |||
/** | |||
* The pixel size for OSX's invisible scrollbars. | |||
@@ -50,8 +49,11 @@ abstract class ScrollbarBundle { | |||
* @see VerticalScrollbarBundle#getElement() | |||
*/ | |||
final static class VerticalScrollbarBundle extends ScrollbarBundle { | |||
public VerticalScrollbarBundle() { | |||
root.addClassName(CLASS_NAME + "-vertical"); | |||
@Override | |||
public void setStylePrimaryName(String primaryStyleName) { | |||
super.setStylePrimaryName(primaryStyleName); | |||
root.addClassName(primaryStyleName + "-scroller-vertical"); | |||
} | |||
@Override | |||
@@ -111,8 +113,11 @@ abstract class ScrollbarBundle { | |||
* @see HorizontalScrollbarBundle#getElement() | |||
*/ | |||
final static class HorizontalScrollbarBundle extends ScrollbarBundle { | |||
protected HorizontalScrollbarBundle() { | |||
root.addClassName(CLASS_NAME + "-horizontal"); | |||
@Override | |||
public void setStylePrimaryName(String primaryStyleName) { | |||
super.setStylePrimaryName(primaryStyleName); | |||
root.addClassName(primaryStyleName + "-scroller-horizontal"); | |||
} | |||
@Override | |||
@@ -172,7 +177,16 @@ abstract class ScrollbarBundle { | |||
private ScrollbarBundle() { | |||
root.appendChild(scrollSizeElement); | |||
root.setClassName(CLASS_NAME); | |||
} | |||
/** | |||
* Sets the primary style name | |||
* | |||
* @param primaryStyleName | |||
* The primary style name to use | |||
*/ | |||
public void setStylePrimaryName(String primaryStyleName) { | |||
root.setClassName(primaryStyleName + "-scroller"); | |||
} | |||
/** |
@@ -16,6 +16,7 @@ | |||
package com.vaadin.tests.components.grid; | |||
import java.util.ArrayList; | |||
import java.util.LinkedHashMap; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.util.IndexedContainer; | |||
@@ -70,6 +71,8 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { | |||
grid.getColumn("Column" + col).setWidth(100 + col * 50); | |||
} | |||
createGridActions(); | |||
createColumnActions(); | |||
createHeaderActions(); | |||
@@ -81,6 +84,23 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { | |||
return grid; | |||
} | |||
protected void createGridActions() { | |||
LinkedHashMap<String, String> primaryStyleNames = new LinkedHashMap<String, String>(); | |||
primaryStyleNames.put("v-grid", "v-grid"); | |||
primaryStyleNames.put("v-escalator", "v-escalator"); | |||
primaryStyleNames.put("my-grid", "my-grid"); | |||
createMultiClickAction("Primary style name", "State", | |||
primaryStyleNames, new Command<Grid, String>() { | |||
@Override | |||
public void execute(Grid grid, String value, Object data) { | |||
grid.setPrimaryStyleName(value); | |||
} | |||
}, primaryStyleNames.get("v-grid")); | |||
} | |||
protected void createHeaderActions() { | |||
createCategory("Headers", null); | |||
@@ -39,9 +39,7 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
openTestURL(); | |||
// Column headers should be visible | |||
List<WebElement> cells = getDriver() | |||
.findElements( | |||
By.xpath("//thead[contains(@class, 'v-escalator-header')]//th")); | |||
List<WebElement> cells = getGridHeaderRowCells(); | |||
assertEquals(10, cells.size()); | |||
assertEquals("Column0", cells.get(0).getText()); | |||
assertEquals("Column1", cells.get(1).getText()); | |||
@@ -52,19 +50,15 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
public void testColumnFooterCaptions() throws Exception { | |||
openTestURL(); | |||
String footerCellPath = "//tfoot[contains(@class, 'v-escalator-footer')]" | |||
+ "//td[contains(@class, 'v-escalator-cell')]"; | |||
// footer row should by default be hidden | |||
assertEquals(0, getDriver().findElements(By.xpath(footerCellPath)) | |||
.size()); | |||
List<WebElement> cells = getGridFooterRowCells(); | |||
assertEquals(0, cells.size()); | |||
// Open footer row | |||
selectMenuPath("Component", "Footers", "Visible"); | |||
// Footers should now be visible | |||
List<WebElement> cells = getDriver().findElements( | |||
By.xpath(footerCellPath)); | |||
cells = getGridFooterRowCells(); | |||
assertEquals(10, cells.size()); | |||
assertEquals("Footer 0", cells.get(0).getText()); | |||
assertEquals("Footer 1", cells.get(1).getText()); | |||
@@ -78,27 +72,24 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
// Hide column headers for this test | |||
selectMenuPath("Component", "Headers", "Visible"); | |||
String headerCellPath = "//thead[contains(@class, 'v-escalator-header')]//th"; | |||
List<WebElement> cells = getGridHeaderRowCells(); | |||
// header row should be empty | |||
assertEquals(0, getDriver().findElements(By.xpath(headerCellPath)) | |||
.size()); | |||
assertEquals(0, cells.size()); | |||
// add a group row | |||
selectMenuPath("Component", "Column groups", "Add group row"); | |||
// Empty group row cells should be present | |||
assertEquals(10, getDriver().findElements(By.xpath(headerCellPath)) | |||
.size()); | |||
cells = getGridHeaderRowCells(); | |||
assertEquals(10, cells.size()); | |||
// Group columns 0 & 1 | |||
selectMenuPath("Component", "Column groups", "Column group row 1", | |||
"Group Column 0 & 1"); | |||
List<WebElement> cells = getDriver().findElements( | |||
By.xpath(headerCellPath)); | |||
cells = getGridHeaderRowCells(); | |||
assertEquals("Column 0 & 1", cells.get(0).getText()); | |||
assertEquals("Column 0 & 1", cells.get(1).getText()); | |||
} | |||
@Test | |||
@@ -116,13 +107,8 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
selectMenuPath("Component", "Column groups", "Column group row 1", | |||
"Group Column 0 & 1"); | |||
String footerCellPath = "//tfoot[contains(@class, 'v-escalator-footer')]" | |||
+ "//td[contains(@class, 'v-escalator-cell')]"; | |||
List<WebElement> cells = getDriver().findElements( | |||
By.xpath(footerCellPath)); | |||
List<WebElement> cells = getGridFooterRowCells(); | |||
assertEquals("Column 0 & 1", cells.get(0).getText()); | |||
assertEquals("Column 0 & 1", cells.get(1).getText()); | |||
} | |||
@Test | |||
@@ -150,16 +136,14 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
openTestURL(); | |||
// Column 0 should be visible | |||
String headerCellPath = "//thead[contains(@class, 'v-escalator-header')]//th"; | |||
List<WebElement> cells = getDriver().findElements( | |||
By.xpath(headerCellPath)); | |||
List<WebElement> cells = getGridHeaderRowCells(); | |||
assertEquals("Column0", cells.get(0).getText()); | |||
// Hide column 0 | |||
selectMenuPath("Component", "Columns", "Column0", "Visible"); | |||
// Column 1 should now be the first cell | |||
cells = getDriver().findElements(By.xpath(headerCellPath)); | |||
cells = getGridHeaderRowCells(); | |||
assertEquals("Column1", cells.get(0).getText()); | |||
} | |||
@@ -168,16 +152,14 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
openTestURL(); | |||
// Column 0 should be visible | |||
String headerCellPath = "//thead[contains(@class, 'v-escalator-header')]//th"; | |||
List<WebElement> cells = getDriver().findElements( | |||
By.xpath(headerCellPath)); | |||
List<WebElement> cells = getGridHeaderRowCells(); | |||
assertEquals("Column0", cells.get(0).getText()); | |||
// Hide column 0 | |||
selectMenuPath("Component", "Columns", "Column0", "Remove"); | |||
// Column 1 should now be the first cell | |||
cells = getDriver().findElements(By.xpath(headerCellPath)); | |||
cells = getGridHeaderRowCells(); | |||
assertEquals("Column1", cells.get(0).getText()); | |||
} | |||
@@ -251,13 +233,46 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
cell = getBodyCellByRowAndColumn(1, 1); | |||
assertEquals((100 - cellBorder - cellMargin) + "px", | |||
cell.getCssValue("width")); | |||
} | |||
@Test | |||
public void testPrimaryStyleNames() throws Exception { | |||
openTestURL(); | |||
// v-grid is default primary style namea | |||
assertPrimaryStylename("v-grid"); | |||
selectMenuPath("Component", "State", "Primary style name", | |||
"v-escalator"); | |||
assertPrimaryStylename("v-escalator"); | |||
selectMenuPath("Component", "State", "Primary style name", "my-grid"); | |||
assertPrimaryStylename("my-grid"); | |||
selectMenuPath("Component", "State", "Primary style name", "v-grid"); | |||
assertPrimaryStylename("v-grid"); | |||
} | |||
private void assertPrimaryStylename(String stylename) { | |||
assertTrue(getGridElement().getAttribute("class").contains(stylename)); | |||
String tableWrapperStyleName = getTableWrapper().getAttribute("class"); | |||
assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper")); | |||
String hscrollStyleName = getHorizontalScroller().getAttribute("class"); | |||
assertTrue(hscrollStyleName.contains(stylename + "-scroller")); | |||
assertTrue(hscrollStyleName | |||
.contains(stylename + "-scroller-horizontal")); | |||
String vscrollStyleName = getVerticalScroller().getAttribute("class"); | |||
assertTrue(vscrollStyleName.contains(stylename + "-scroller")); | |||
assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical")); | |||
} | |||
private WebElement getBodyCellByRowAndColumn(int row, int column) { | |||
return getDriver().findElement( | |||
By.xpath("//tbody[contains(@class, 'v-escalator-body')]/tr[" | |||
+ row + "]/td[" + column + "]")); | |||
By.xpath("//div[@id='testComponent']//tbody/tr[" + row | |||
+ "]/td[" + column + "]")); | |||
} | |||
private void selectSubMenu(String menuCaption) { | |||
@@ -276,4 +291,33 @@ public class GridBasicFeaturesTest extends MultiBrowserTest { | |||
selectSubMenu(menuCaptions[i]); | |||
} | |||
} | |||
private WebElement getVerticalScroller() { | |||
return getDriver().findElement( | |||
By.xpath("//div[@id='testComponent']/div[1]")); | |||
} | |||
private WebElement getHorizontalScroller() { | |||
return getDriver().findElement( | |||
By.xpath("//div[@id='testComponent']/div[2]")); | |||
} | |||
private WebElement getTableWrapper() { | |||
return getDriver().findElement( | |||
By.xpath("//div[@id='testComponent']/div[3]")); | |||
} | |||
private WebElement getGridElement() { | |||
return getDriver().findElement(By.id("testComponent")); | |||
} | |||
private List<WebElement> getGridHeaderRowCells() { | |||
return getDriver().findElements( | |||
By.xpath("//div[@id='testComponent']//thead//th")); | |||
} | |||
private List<WebElement> getGridFooterRowCells() { | |||
return getDriver().findElements( | |||
By.xpath("//div[@id='testComponent']//tfoot//td")); | |||
} | |||
} |