summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2015-04-15 10:24:44 +0300
committerTeemu Suo-Anttila <teemusa@vaadin.com>2015-04-15 10:24:44 +0300
commit2c4e533c9f2aa68211329ea6ce4de0b577407863 (patch)
tree1d9c1cc8bb72678b0edb991947c6fc94112baf0f /server
parent93235f05c9dd4739cdccf87a4858a61904dbf4b5 (diff)
parent7cb23bc63f794a7549dd79c37da2f8bb8e88e20d (diff)
downloadvaadin-framework-2c4e533c9f2aa68211329ea6ce4de0b577407863.tar.gz
vaadin-framework-2c4e533c9f2aa68211329ea6ce4de0b577407863.zip
Merge remote-tracking branch 'origin/master' into grid-7.5
Change-Id: I03fdd2014fd0393341db0f650c065f6d27905b73
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/data/fieldgroup/FieldGroup.java2
-rw-r--r--server/src/com/vaadin/ui/AbsoluteLayout.java3
-rw-r--r--server/src/com/vaadin/ui/AbstractOrderedLayout.java57
-rw-r--r--server/src/com/vaadin/ui/AbstractSelect.java141
-rw-r--r--server/src/com/vaadin/ui/ColorPicker.java12
-rw-r--r--server/src/com/vaadin/ui/Grid.java503
-rw-r--r--server/src/com/vaadin/ui/GridLayout.java325
-rw-r--r--server/src/com/vaadin/ui/MenuBar.java3
-rw-r--r--server/src/com/vaadin/ui/OptionGroup.java27
-rw-r--r--server/src/com/vaadin/ui/Tree.java119
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java80
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignContext.java13
-rw-r--r--server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java62
-rw-r--r--server/tests/src/com/vaadin/tests/design/AbstractComponentSetResponsiveTest.java17
-rw-r--r--server/tests/src/com/vaadin/tests/design/DeclarativeTestBase.java4
-rw-r--r--server/tests/src/com/vaadin/tests/design/DeclarativeTestBaseBase.java6
-rw-r--r--server/tests/src/com/vaadin/tests/design/DesignContextLocalIdTest.java66
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/AbstractLayoutDeclarativeMarginTest.java104
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutDeclarativeTest.java34
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/absolutelayout/ReadDesignTest.java110
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/absolutelayout/WriteDesignTest.java100
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractcomponent/AbstractComponentDeclarativeTest.java241
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractcomponent/ReadDesignTest.java256
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractcomponent/WriteDesignTest.java281
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractselect/OptionGroupDeclarativeTests.java160
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java9
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java95
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java69
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java153
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java267
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java106
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java50
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java200
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/tree/TreeDeclarativeTest.java59
34 files changed, 2828 insertions, 906 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
index 8f1bf8b40a..d370c3906b 100644
--- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
@@ -702,7 +702,7 @@ public class FieldGroup implements Serializable {
/**
* Called after changes are committed to the fields and the item is
- * updated..
+ * updated.
* <p>
* Throw a {@link CommitException} to abort the commit.
*
diff --git a/server/src/com/vaadin/ui/AbsoluteLayout.java b/server/src/com/vaadin/ui/AbsoluteLayout.java
index 63bbe70157..303e8efd6b 100644
--- a/server/src/com/vaadin/ui/AbsoluteLayout.java
+++ b/server/src/com/vaadin/ui/AbsoluteLayout.java
@@ -724,7 +724,7 @@ public class AbsoluteLayout extends AbstractLayout implements
for (Component child : this) {
Element childElement = designContext.createElement(child);
design.appendChild(childElement);
- child.writeDesign(childElement, designContext);
+
// handle position
ComponentPosition position = getPosition(child);
writePositionAttribute(childElement, ATTR_TOP, position
@@ -735,6 +735,7 @@ public class AbsoluteLayout extends AbstractLayout implements
.getBottomUnits().getSymbol(), position.getBottomValue());
writePositionAttribute(childElement, ATTR_LEFT, position
.getLeftUnits().getSymbol(), position.getLeftValue());
+
// handle z-index
if (position.getZIndex() >= 0) {
childElement
diff --git a/server/src/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
index 3aec3b2d7a..0214ff4be1 100644
--- a/server/src/com/vaadin/ui/AbstractOrderedLayout.java
+++ b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
@@ -477,11 +477,32 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
public void readDesign(Element design, DesignContext designContext) {
// process default attributes
super.readDesign(design, designContext);
- // handle margin
+
+ // handle margins
if (design.hasAttr("margin")) {
setMargin(DesignAttributeHandler.readAttribute("margin",
design.attributes(), Boolean.class));
+ } else {
+ boolean marginLeft = DesignAttributeHandler.readAttribute(
+ "margin-left", design.attributes(), getMargin().hasLeft(),
+ Boolean.class);
+
+ boolean marginRight = DesignAttributeHandler.readAttribute(
+ "margin-right", design.attributes(),
+ getMargin().hasRight(), Boolean.class);
+
+ boolean marginTop = DesignAttributeHandler.readAttribute(
+ "margin-top", design.attributes(), getMargin().hasTop(),
+ Boolean.class);
+
+ boolean marginBottom = DesignAttributeHandler.readAttribute(
+ "margin-bottom", design.attributes(), getMargin()
+ .hasBottom(), Boolean.class);
+
+ setMargin(new MarginInfo(marginTop, marginBottom, marginLeft,
+ marginRight));
}
+
// handle children
for (Element childComponent : design.children()) {
Attributes attr = childComponent.attributes();
@@ -532,12 +553,36 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
public void writeDesign(Element design, DesignContext designContext) {
// write default attributes
super.writeDesign(design, designContext);
- // handle margin
+
AbstractOrderedLayout def = (AbstractOrderedLayout) designContext
.getDefaultInstance(this);
- if (getMargin().getBitMask() != def.getMargin().getBitMask()) {
- design.attr("margin", "");
+
+ // handle margin
+ MarginInfo marginInfo = getMargin();
+
+ if (marginInfo.hasAll()) {
+ DesignAttributeHandler.writeAttribute("margin",
+ design.attributes(), marginInfo.hasAll(), def.getMargin()
+ .hasAll(), Boolean.class);
+ } else {
+
+ DesignAttributeHandler.writeAttribute("margin-left", design
+ .attributes(), marginInfo.hasLeft(), def.getMargin()
+ .hasLeft(), Boolean.class);
+
+ DesignAttributeHandler.writeAttribute("margin-right", design
+ .attributes(), marginInfo.hasRight(), def.getMargin()
+ .hasRight(), Boolean.class);
+
+ DesignAttributeHandler.writeAttribute("margin-top", design
+ .attributes(), marginInfo.hasTop(), def.getMargin()
+ .hasTop(), Boolean.class);
+
+ DesignAttributeHandler.writeAttribute("margin-bottom", design
+ .attributes(), marginInfo.hasBottom(), def.getMargin()
+ .hasBottom(), Boolean.class);
}
+
// handle children
if (!designContext.shouldWriteChildren(this, def)) {
return;
@@ -578,6 +623,10 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
protected Collection<String> getCustomAttributes() {
Collection<String> customAttributes = super.getCustomAttributes();
customAttributes.add("margin");
+ customAttributes.add("margin-left");
+ customAttributes.add("margin-right");
+ customAttributes.add("margin-top");
+ customAttributes.add("margin-bottom");
return customAttributes;
}
diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java
index 4c5e6b6ea3..6ac0dad5e4 100644
--- a/server/src/com/vaadin/ui/AbstractSelect.java
+++ b/server/src/com/vaadin/ui/AbstractSelect.java
@@ -2188,28 +2188,13 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
}
@Override
- public void readDesign(Element design, DesignContext designContext) {
+ public void readDesign(Element design, DesignContext context) {
// handle default attributes
- super.readDesign(design, designContext);
+ super.readDesign(design, context);
// handle children specifying selectable items (<option>)
Set<String> selected = new HashSet<String>();
for (Element child : design.children()) {
- if (!"option".equals(child.nodeName())) {
- throw new DesignException(
- "Unsupported child element in a select: "
- + child.nodeName() + ".");
- }
- String itemId = child.html();
- addItem(itemId);
- if (child.hasAttr("icon")) {
- setItemIcon(
- itemId,
- DesignAttributeHandler.readAttribute("icon",
- child.attributes(), Resource.class));
- }
- if (child.hasAttr("selected")) {
- selected.add(itemId);
- }
+ readItem(child, selected, context);
}
if (!selected.isEmpty()) {
if (isMultiSelect()) {
@@ -2223,29 +2208,117 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
}
}
+ /**
+ * Reads an Item from a design and inserts it into the data source.
+ * Hierarchical select components should override this method to recursively
+ * recursively read any child items as well.
+ *
+ * @since
+ * @param child
+ * a child element representing the item
+ * @param selected
+ * A set accumulating selected items. If the item that is read is
+ * marked as selected, its item id should be added to this set.
+ * @param context
+ * the DesignContext instance used in parsing
+ * @return the item id of the new item
+ *
+ * @throws DesignException
+ * if the tag name of the {@code child} element is not
+ * {@code option}.
+ */
+ protected String readItem(Element child, Set<String> selected,
+ DesignContext context) {
+ if (!"option".equals(child.tagName())) {
+ throw new DesignException("Unrecognized child element in "
+ + getClass().getSimpleName() + ": " + child.tagName());
+ }
+
+ String itemId;
+ if (child.hasAttr("item-id")) {
+ itemId = child.attr("item-id");
+ addItem(itemId);
+ setItemCaption(itemId, child.html());
+ } else {
+ addItem(itemId = child.html());
+ }
+
+ if (child.hasAttr("icon")) {
+ setItemIcon(
+ itemId,
+ DesignAttributeHandler.readAttribute("icon",
+ child.attributes(), Resource.class));
+ }
+
+ if (child.hasAttr("selected")) {
+ selected.add(itemId);
+ }
+
+ return itemId;
+ }
+
@Override
- public void writeDesign(Element design, DesignContext designContext) {
+ public void writeDesign(Element design, DesignContext context) {
// Write default attributes
- super.writeDesign(design, designContext);
+ super.writeDesign(design, context);
// Write options if warranted
- if (designContext.shouldWriteData(this)) {
- for (Object itemId : getItemIds()) {
- Element optionElement = design.appendElement("option");
+ if (context.shouldWriteData(this)) {
+ writeItems(design, context);
+ }
+ }
- optionElement.html(getItemCaption(itemId));
+ /**
+ * Writes the data source items to a design. Hierarchical select components
+ * should override this method to only write the root items.
+ *
+ * @since
+ * @param design
+ * the element into which to insert the items
+ * @param context
+ * the DesignContext instance used in writing
+ */
+ protected void writeItems(Element design, DesignContext context) {
+ for (Object itemId : getItemIds()) {
+ writeItem(design, itemId, context);
+ }
+ }
- Resource icon = getItemIcon(itemId);
- if (icon != null) {
- DesignAttributeHandler.writeAttribute("icon",
- optionElement.attributes(), icon, null,
- Resource.class);
- }
+ /**
+ * Writes a data source Item to a design. Hierarchical select components
+ * should override this method to recursively write any child items as well.
+ *
+ * @since
+ * @param design
+ * the element into which to insert the item
+ * @param itemId
+ * the id of the item to write
+ * @param context
+ * the DesignContext instance used in writing
+ * @return
+ */
+ protected Element writeItem(Element design, Object itemId,
+ DesignContext context) {
+ Element element = design.appendElement("option");
- if (isSelected(itemId)) {
- optionElement.attr("selected", "");
- }
- }
+ String caption = getItemCaption(itemId);
+ if (caption != null && !caption.equals(itemId.toString())) {
+ element.html(caption);
+ element.attr("item-id", itemId.toString());
+ } else {
+ element.html(itemId.toString());
}
+
+ Resource icon = getItemIcon(itemId);
+ if (icon != null) {
+ DesignAttributeHandler.writeAttribute("icon", element.attributes(),
+ icon, null, Resource.class);
+ }
+
+ if (isSelected(itemId)) {
+ element.attr("selected", "");
+ }
+
+ return element;
}
} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/ColorPicker.java b/server/src/com/vaadin/ui/ColorPicker.java
index f65b67db72..9e46c4e718 100644
--- a/server/src/com/vaadin/ui/ColorPicker.java
+++ b/server/src/com/vaadin/ui/ColorPicker.java
@@ -64,16 +64,4 @@ public class ColorPicker extends AbstractColorPicker {
addStyleName(STYLENAME_DEFAULT);
}
- @Override
- public void beforeClientResponse(boolean initial) {
- super.beforeClientResponse(initial);
-
- if (isDefaultCaptionEnabled()
- && ((getState().caption == null || ""
- .equals(getState().caption)))
- && "".equals(getState().width)) {
- getState().width = "100px";
- }
- }
-
}
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index cd97e90e2e..1d7eac7b3c 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -37,6 +37,10 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.guava.common.collect.Sets.SetView;
import com.vaadin.data.Container;
@@ -93,6 +97,10 @@ import com.vaadin.shared.ui.grid.GridStaticSectionState.RowState;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.grid.ScrollDestination;
import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
+import com.vaadin.ui.renderers.HtmlRenderer;
import com.vaadin.ui.renderers.Renderer;
import com.vaadin.ui.renderers.TextRenderer;
import com.vaadin.util.ReflectTools;
@@ -1448,7 +1456,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
* @param <ROWTYPE>
* the type of the rows in the section
*/
- protected static abstract class StaticSection<ROWTYPE extends StaticSection.StaticRow<?>>
+ abstract static class StaticSection<ROWTYPE extends StaticSection.StaticRow<?>>
implements Serializable {
/**
@@ -1620,6 +1628,86 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
getRowState().styleName = styleName;
}
+ /**
+ * Writes the declarative design to the given table row element.
+ *
+ * @since
+ * @param trElement
+ * Element to write design to
+ * @param designContext
+ * the design context
+ */
+ protected void writeDesign(Element trElement,
+ DesignContext designContext) {
+ Set<CELLTYPE> visited = new HashSet<CELLTYPE>();
+ for (Grid.Column column : section.grid.getColumns()) {
+ CELLTYPE cell = getCell(column.getPropertyId());
+ if (visited.contains(cell)) {
+ continue;
+ }
+ visited.add(cell);
+
+ Element cellElement = trElement
+ .appendElement(getCellTagName());
+ cell.writeDesign(cellElement, designContext);
+
+ for (Entry<Set<CELLTYPE>, CELLTYPE> entry : cellGroups
+ .entrySet()) {
+ if (entry.getValue() == cell) {
+ cellElement.attr("colspan", ""
+ + entry.getKey().size());
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Reads the declarative design from the given table row element.
+ *
+ * @since
+ * @param trElement
+ * Element to read design from
+ * @param designContext
+ * the design context
+ * @throws DesignException
+ * if the given table row contains unexpected children
+ */
+ protected void readDesign(Element trElement,
+ DesignContext designContext) throws DesignException {
+ Elements cellElements = trElement.children();
+ int totalColSpans = 0;
+ for (int i = 0; i < cellElements.size(); ++i) {
+ Element element = cellElements.get(i);
+ if (!element.tagName().equals(getCellTagName())) {
+ throw new DesignException(
+ "Unexpected element in tr while expecting "
+ + getCellTagName() + ": "
+ + element.tagName());
+ }
+
+ int columnIndex = i + totalColSpans;
+
+ int colspan = DesignAttributeHandler.readAttribute(
+ "colspan", element.attributes(), 1, int.class);
+
+ Set<CELLTYPE> cells = new HashSet<CELLTYPE>();
+ for (int c = 0; c < colspan; ++c) {
+ cells.add(getCell(section.grid.getColumns()
+ .get(columnIndex + c).getPropertyId()));
+ }
+
+ if (colspan > 1) {
+ totalColSpans += colspan - 1;
+ join(cells).readDesign(element, designContext);
+ } else {
+ cells.iterator().next()
+ .readDesign(element, designContext);
+ }
+ }
+ }
+
+ abstract protected String getCellTagName();
}
/**
@@ -1739,6 +1827,15 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
}
/**
+ * Returns the type of content stored in this cell.
+ *
+ * @return cell content type
+ */
+ public GridStaticCellType getCellType() {
+ return cellState.type;
+ }
+
+ /**
* Returns the custom style name for this cell.
*
* @return the style name or null if no style name has been set
@@ -1766,6 +1863,57 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
cellState.connector = null;
}
}
+
+ /**
+ * Writes the declarative design to the given table cell element.
+ *
+ * @since
+ * @param cellElement
+ * Element to write design to
+ * @param designContext
+ * the design context
+ */
+ protected void writeDesign(Element cellElement,
+ DesignContext designContext) {
+ switch (cellState.type) {
+ case TEXT:
+ DesignAttributeHandler.writeAttribute("plain-text",
+ cellElement.attributes(), "", null, String.class);
+ cellElement.appendText(getText());
+ break;
+ case HTML:
+ cellElement.append(getHtml());
+ break;
+ case WIDGET:
+ cellElement.appendChild(designContext
+ .createElement(getComponent()));
+ break;
+ }
+ }
+
+ /**
+ * Reads the declarative design from the given table cell element.
+ *
+ * @since
+ * @param cellElement
+ * Element to read design from
+ * @param designContext
+ * the design context
+ */
+ protected void readDesign(Element cellElement,
+ DesignContext designContext) {
+ if (!cellElement.hasAttr("plain-text")) {
+ if (cellElement.children().size() > 0
+ && cellElement.child(0).tagName().contains("-")) {
+ setComponent(designContext.readDesign(cellElement
+ .child(0)));
+ } else {
+ setHtml(cellElement.html());
+ }
+ } else {
+ setText(cellElement.html());
+ }
+ }
}
protected Grid grid;
@@ -1995,6 +2143,50 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
}
return false;
}
+
+ /**
+ * Writes the declarative design to the given table section element.
+ *
+ * @since
+ * @param tableSectionElement
+ * Element to write design to
+ * @param designContext
+ * the design context
+ */
+ protected void writeDesign(Element tableSectionElement,
+ DesignContext designContext) {
+ for (ROWTYPE row : rows) {
+ row.writeDesign(tableSectionElement.appendElement("tr"),
+ designContext);
+ }
+ }
+
+ /**
+ * Writes the declarative design from the given table section element.
+ *
+ * @since
+ * @param tableSectionElement
+ * Element to read design from
+ * @param designContext
+ * the design context
+ * @throws DesignException
+ * if the table section contains unexpected children
+ */
+ protected void readDesign(Element tableSectionElement,
+ DesignContext designContext) throws DesignException {
+ while (rows.size() > 0) {
+ removeRow(0);
+ }
+
+ for (Element row : tableSectionElement.children()) {
+ if (!row.tagName().equals("tr")) {
+ throw new DesignException("Unexpected element in "
+ + tableSectionElement.tagName() + ": "
+ + row.tagName());
+ }
+ appendRow().readDesign(row, designContext);
+ }
+ }
}
/**
@@ -2092,6 +2284,16 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
}
}
}
+
+ @Override
+ protected void readDesign(Element tableSectionElement,
+ DesignContext designContext) {
+ super.readDesign(tableSectionElement, designContext);
+
+ if (defaultRow == null && !rows.isEmpty()) {
+ grid.setDefaultHeaderRow(rows.get(0));
+ }
+ }
}
/**
@@ -2107,10 +2309,41 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
getRowState().defaultRow = value;
}
+ private boolean isDefaultRow() {
+ return getRowState().defaultRow;
+ }
+
@Override
protected HeaderCell createCell() {
return new HeaderCell(this);
}
+
+ @Override
+ protected String getCellTagName() {
+ return "th";
+ }
+
+ @Override
+ protected void writeDesign(Element trElement,
+ DesignContext designContext) {
+ super.writeDesign(trElement, designContext);
+
+ if (section.grid.getDefaultHeaderRow() == this) {
+ DesignAttributeHandler.writeAttribute("default",
+ trElement.attributes(), true, null, boolean.class);
+ }
+ }
+
+ @Override
+ protected void readDesign(Element trElement, DesignContext designContext) {
+ super.readDesign(trElement, designContext);
+
+ boolean defaultRow = DesignAttributeHandler.readAttribute(
+ "default", trElement.attributes(), false, boolean.class);
+ if (defaultRow) {
+ section.grid.setDefaultHeaderRow(this);
+ }
+ }
}
/**
@@ -2167,6 +2400,11 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
return new FooterCell(this);
}
+ @Override
+ protected String getCellTagName() {
+ return "td";
+ }
+
}
/**
@@ -2930,6 +3168,80 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
public boolean isHidable() {
return getState().hidable;
}
+
+ /*
+ * Writes the design attributes for this column into given element.
+ *
+ * @since
+ *
+ * @param design Element to write attributes into
+ *
+ * @param designContext the design context
+ */
+ protected void writeDesign(Element design, DesignContext designContext) {
+ Attributes attributes = design.attributes();
+ GridColumnState def = new GridColumnState();
+ // Sortable is a special attribute that depends on the container.
+ DesignAttributeHandler.writeAttribute("sortable", attributes,
+ isSortable(), null, boolean.class);
+ DesignAttributeHandler.writeAttribute("editable", attributes,
+ isEditable(), def.editable, boolean.class);
+ DesignAttributeHandler.writeAttribute("width", attributes,
+ getWidth(), def.width, Double.class);
+ DesignAttributeHandler.writeAttribute("min-width", attributes,
+ getMinimumWidth(), def.minWidth, Double.class);
+ DesignAttributeHandler.writeAttribute("max-width", attributes,
+ getMaximumWidth(), def.maxWidth, Double.class);
+ DesignAttributeHandler.writeAttribute("expand", attributes,
+ getExpandRatio(), def.expandRatio, Integer.class);
+ DesignAttributeHandler.writeAttribute("property-id", attributes,
+ getPropertyId(), null, Object.class);
+ }
+
+ /**
+ * Reads the design attributes for this column from given element.
+ *
+ * @since
+ * @param design
+ * Element to read attributes from
+ * @param designContext
+ * the design context
+ */
+ protected void readDesign(Element design, DesignContext designContext) {
+ Attributes attributes = design.attributes();
+
+ if (design.hasAttr("sortable")) {
+ setSortable(DesignAttributeHandler.readAttribute("sortable",
+ attributes, boolean.class));
+ }
+
+ if (design.hasAttr("editable")) {
+ setEditable(DesignAttributeHandler.readAttribute("editable",
+ attributes, boolean.class));
+ }
+
+ // Read size info where necessary.
+ if (design.hasAttr("width")) {
+ setWidth(DesignAttributeHandler.readAttribute("width",
+ attributes, Double.class));
+ }
+ if (design.hasAttr("min-width")) {
+ setMinimumWidth(DesignAttributeHandler.readAttribute(
+ "min-width", attributes, Double.class));
+ }
+ if (design.hasAttr("max-width")) {
+ setMaximumWidth(DesignAttributeHandler.readAttribute(
+ "max-width", attributes, Double.class));
+ }
+ if (design.hasAttr("expand")) {
+ if (design.attr("expand").isEmpty()) {
+ setExpandRatio(1);
+ } else {
+ setExpandRatio(DesignAttributeHandler.readAttribute(
+ "expand", attributes, Integer.class));
+ }
+ }
+ }
}
/**
@@ -3109,13 +3421,15 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
setFrozenColumnCount(columns.size());
}
- // Update sortable columns
- if (event.getContainer() instanceof Sortable) {
- Collection<?> sortableProperties = ((Sortable) event
- .getContainer()).getSortableContainerPropertyIds();
- for (Entry<Object, Column> columnEntry : columns.entrySet()) {
- columnEntry.getValue().setSortable(
- sortableProperties.contains(columnEntry.getKey()));
+ // Unset sortable for non-sortable columns.
+ if (datasource instanceof Sortable) {
+ Collection<?> sortables = ((Sortable) datasource)
+ .getSortableContainerPropertyIds();
+ for (Object propertyId : columns.keySet()) {
+ Column column = columns.get(propertyId);
+ if (!sortables.contains(propertyId) && column.isSortable()) {
+ column.setSortable(false);
+ }
}
}
}
@@ -3233,7 +3547,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
* Grid initial setup
*/
private void initGrid() {
- setSelectionMode(SelectionMode.SINGLE);
+ setSelectionMode(getDefaultSelectionMode());
addSelectionListener(new SelectionListener() {
@Override
public void select(SelectionEvent event) {
@@ -3905,6 +4219,12 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
column.setHeaderCaption(humanFriendlyPropertyId);
column.setHidingToggleCaption(humanFriendlyPropertyId);
+ if (datasource instanceof Sortable
+ && ((Sortable) datasource).getSortableContainerPropertyIds()
+ .contains(datasourcePropertyId)) {
+ column.setSortable(true);
+ }
+
return column;
}
@@ -3986,7 +4306,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
if (numberOfColumns < -1 || numberOfColumns > columns.size()) {
throw new IllegalArgumentException(
"count must be between -1 and the current number of columns ("
- + columns + ")");
+ + columns.size() + "): " + numberOfColumns);
}
getState().frozenColumnCount = numberOfColumns;
@@ -5626,4 +5946,167 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
public boolean isDetailsVisible(Object itemId) {
return datasourceExtension.isDetailsVisible(itemId);
}
+
+ protected SelectionMode getDefaultSelectionMode() {
+ return SelectionMode.SINGLE;
+ }
+
+ @Override
+ public void readDesign(Element design, DesignContext context) {
+ super.readDesign(design, context);
+
+ Attributes attrs = design.attributes();
+ if (attrs.hasKey("editable")) {
+ setEditorEnabled(DesignAttributeHandler.readAttribute("editable",
+ attrs, boolean.class));
+ }
+ if (attrs.hasKey("frozen-columns")) {
+ setFrozenColumnCount(DesignAttributeHandler.readAttribute(
+ "frozen-columns", attrs, int.class));
+ }
+ if (attrs.hasKey("rows")) {
+ setHeightByRows(DesignAttributeHandler.readAttribute("rows", attrs,
+ double.class));
+ setHeightMode(HeightMode.ROW);
+ }
+ if (attrs.hasKey("selection-mode")) {
+ setSelectionMode(DesignAttributeHandler.readAttribute(
+ "selection-mode", attrs, SelectionMode.class));
+ }
+
+ if (design.children().size() > 0) {
+ if (design.children().size() > 1
+ || !design.child(0).tagName().equals("table")) {
+ throw new DesignException(
+ "Grid needs to have a table element as its only child");
+ }
+ Element table = design.child(0);
+
+ Elements colgroups = table.getElementsByTag("colgroup");
+ if (colgroups.size() != 1) {
+ throw new DesignException(
+ "Table element in declarative Grid needs to have a"
+ + " colgroup defining the columns used in Grid");
+ }
+
+ int i = 0;
+ for (Element col : colgroups.get(0).getElementsByTag("col")) {
+ String propertyId = DesignAttributeHandler.readAttribute(
+ "property-id", col.attributes(), "property-" + i,
+ String.class);
+ addColumn(propertyId, String.class).readDesign(col, context);
+ ++i;
+ }
+
+ for (Element child : table.children()) {
+ if (child.tagName().equals("thead")) {
+ header.readDesign(child, context);
+ } else if (child.tagName().equals("tbody")) {
+ for (Element row : child.children()) {
+ Elements cells = row.children();
+ Object[] data = new String[cells.size()];
+ for (int c = 0; c < cells.size(); ++c) {
+ data[c] = cells.get(c).html();
+ }
+ addRow(data);
+ }
+
+ // Since inline data is used, set HTML renderer for columns
+ for (Column c : getColumns()) {
+ c.setRenderer(new HtmlRenderer());
+ }
+ } else if (child.tagName().equals("tfoot")) {
+ footer.readDesign(child, context);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext context) {
+ super.writeDesign(design, context);
+
+ Attributes attrs = design.attributes();
+ Grid def = context.getDefaultInstance(this);
+
+ DesignAttributeHandler.writeAttribute("editable", attrs,
+ isEditorEnabled(), def.isEditorEnabled(), boolean.class);
+
+ DesignAttributeHandler.writeAttribute("frozen-columns", attrs,
+ getFrozenColumnCount(), def.getFrozenColumnCount(), int.class);
+
+ if (getHeightMode() == HeightMode.ROW) {
+ DesignAttributeHandler.writeAttribute("rows", attrs,
+ getHeightByRows(), def.getHeightByRows(), double.class);
+ }
+
+ SelectionMode selectionMode = null;
+
+ if (selectionModel.getClass().equals(SingleSelectionModel.class)) {
+ selectionMode = SelectionMode.SINGLE;
+ } else if (selectionModel.getClass().equals(MultiSelectionModel.class)) {
+ selectionMode = SelectionMode.MULTI;
+ } else if (selectionModel.getClass().equals(NoSelectionModel.class)) {
+ selectionMode = SelectionMode.NONE;
+ }
+
+ assert selectionMode != null : "Unexpected selection model "
+ + selectionModel.getClass().getName();
+
+ DesignAttributeHandler.writeAttribute("selection-mode", attrs,
+ selectionMode, getDefaultSelectionMode(), SelectionMode.class);
+
+ if (columns.isEmpty()) {
+ // Empty grid. Structure not needed.
+ return;
+ }
+
+ // Do structure.
+ Element tableElement = design.appendElement("table");
+ Element colGroup = tableElement.appendElement("colgroup");
+
+ List<Column> columnOrder = getColumns();
+ for (int i = 0; i < columnOrder.size(); ++i) {
+ Column column = columnOrder.get(i);
+ Element colElement = colGroup.appendElement("col");
+ column.writeDesign(colElement, context);
+ }
+
+ // Always write thead. Reads correctly when there no header rows
+ header.writeDesign(tableElement.appendElement("thead"), context);
+
+ if (context.shouldWriteData(this)) {
+ Element bodyElement = tableElement.appendElement("tbody");
+ for (Object itemId : datasource.getItemIds()) {
+ Element tableRow = bodyElement.appendElement("tr");
+ for (Column c : getColumns()) {
+ Object value = datasource.getItem(itemId)
+ .getItemProperty(c.getPropertyId()).getValue();
+ tableRow.appendElement("td").append(
+ (value != null ? value.toString() : ""));
+ }
+ }
+ }
+
+ if (footer.getRowCount() > 0) {
+ footer.writeDesign(tableElement.appendElement("tfoot"), context);
+ }
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("editor-enabled");
+ result.add("editable");
+ result.add("frozen-column-count");
+ result.add("frozen-columns");
+ result.add("height-by-rows");
+ result.add("rows");
+ result.add("selection-mode");
+ result.add("header-visible");
+ result.add("footer-visible");
+ result.add("editor-error-handler");
+ result.add("height-mode");
+ return result;
+ }
}
diff --git a/server/src/com/vaadin/ui/GridLayout.java b/server/src/com/vaadin/ui/GridLayout.java
index 96854c5b1b..35110b39ab 100644
--- a/server/src/com/vaadin/ui/GridLayout.java
+++ b/server/src/com/vaadin/ui/GridLayout.java
@@ -17,12 +17,21 @@
package com.vaadin.ui;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
import com.vaadin.event.LayoutEvents.LayoutClickListener;
@@ -36,6 +45,8 @@ import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc;
import com.vaadin.shared.ui.gridlayout.GridLayoutState;
import com.vaadin.shared.ui.gridlayout.GridLayoutState.ChildComponentData;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* A layout where the components are laid out on a grid using cell coordinates.
@@ -1282,4 +1293,316 @@ public class GridLayout extends AbstractLayout implements
public boolean isHideEmptyRowsAndColumns() {
return getState(false).hideEmptyRowsAndColumns;
}
-}
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * After reading the design, cursorY is set to point to a row outside of the
+ * GridLayout area. CursorX is reset to 0.
+ */
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+
+ // Prepare a 2D map for reading column contents
+ Elements rowElements = design.getElementsByTag("row");
+ List<Map<Integer, Component>> rows = new ArrayList<Map<Integer, Component>>();
+ for (int i = 0; i < rowElements.size(); ++i) {
+ rows.add(new HashMap<Integer, Component>());
+ }
+ setRows(Math.max(rows.size(), 1));
+
+ List<Integer> columnExpandRatios = new ArrayList<Integer>();
+ for (int row = 0; row < rowElements.size(); ++row) {
+ Element rowElement = rowElements.get(row);
+
+ // Row Expand
+ if (rowElement.hasAttr("expand")) {
+ int expand = DesignAttributeHandler.readAttribute("expand",
+ rowElement.attributes(), int.class);
+ setRowExpandRatio(row, expand);
+ }
+
+ Elements cols = rowElement.children();
+
+ // Amount of skipped columns due to spanned components
+ int skippedColumns = 0;
+
+ for (int column = 0; column < cols.size(); ++column) {
+ while (rows.get(row).containsKey(column + skippedColumns)) {
+ // Skip any spanned components
+ skippedColumns++;
+ }
+
+ Element col = cols.get(column);
+ Component child = null;
+
+ if (col.children().size() > 0) {
+ child = designContext.readDesign(col.child(0));
+ // TODO: Currently ignoring any extra children.
+ // Needs Error handling?
+ } // Else: Empty placeholder. No child component.
+
+ // Handle rowspan and colspan for this child component
+ Attributes attr = col.attributes();
+ int colspan = DesignAttributeHandler.readAttribute("colspan",
+ attr, 1, int.class);
+ int rowspan = DesignAttributeHandler.readAttribute("rowspan",
+ attr, 1, int.class);
+
+ for (int rowIndex = row; rowIndex < row + rowspan; ++rowIndex) {
+ for (int colIndex = column; colIndex < column + colspan; ++colIndex) {
+ if (rowIndex == rows.size()) {
+ // Rowspan with not enough rows. Fix by adding rows.
+ rows.add(new HashMap<Integer, Component>());
+ }
+ rows.get(rowIndex)
+ .put(colIndex + skippedColumns, child);
+ }
+ }
+
+ // Read column expand ratios if handling the first row.
+ if (row == 0) {
+ if (col.hasAttr("expand")) {
+ for (String expand : col.attr("expand").split(",")) {
+ columnExpandRatios.add(Integer.parseInt(expand));
+ }
+ } else {
+ for (int c = 0; c < colspan; ++c) {
+ columnExpandRatios.add(0);
+ }
+ }
+ }
+
+ skippedColumns += (colspan - 1);
+ }
+ }
+
+ // Calculate highest column count and set columns
+ int colMax = 0;
+ for (Map<Integer, Component> cols : rows) {
+ if (colMax < cols.size()) {
+ colMax = cols.size();
+ }
+ }
+ setColumns(Math.max(colMax, 1));
+
+ for (int i = 0; i < columnExpandRatios.size(); ++i) {
+ setColumnExpandRatio(i, columnExpandRatios.get(i));
+ }
+
+ // Reiterate through the 2D map and add components to GridLayout
+ Set<Component> visited = new HashSet<Component>();
+
+ // Ignore any missing components
+ visited.add(null);
+
+ for (int i = 0; i < rows.size(); ++i) {
+ Map<Integer, Component> row = rows.get(i);
+ for (int j = 0; j < colMax; ++j) {
+ Component child = row.get(j);
+ if (visited.contains(child)) {
+ // Empty location or already handled child
+ continue;
+ }
+ visited.add(child);
+
+ // Figure out col and rowspan from 2D map
+ int colspan = 0;
+ while (j + colspan + 1 < row.size()
+ && row.get(j + colspan + 1) == child) {
+ ++colspan;
+ }
+
+ int rowspan = 0;
+ while (i + rowspan + 1 < rows.size()
+ && rows.get(i + rowspan + 1).get(j) == child) {
+ ++rowspan;
+ }
+
+ // Add component with area
+ addComponent(child, j, i, j + colspan, i + rowspan);
+ }
+ }
+ // Set cursor position explicitly
+ setCursorY(getRows());
+ setCursorX(0);
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+
+ GridLayout def = designContext.getDefaultInstance(this);
+ if (components.isEmpty()
+ || !designContext.shouldWriteChildren(this, def)) {
+ return;
+ }
+
+ final Map<Connector, ChildComponentData> childData = getState().childData;
+
+ // Make a 2D map of component areas.
+ Component[][] componentMap = new Component[getState().rows][getState().columns];
+ final Component dummyComponent = new Label("");
+
+ for (Component component : components) {
+ ChildComponentData coords = childData.get(component);
+ for (int row = coords.row1; row <= coords.row2; ++row) {
+ for (int col = coords.column1; col <= coords.column2; ++col) {
+ componentMap[row][col] = component;
+ }
+ }
+ }
+
+ // Go through the map and write only needed column tags
+ Set<Connector> visited = new HashSet<Connector>();
+
+ // Skip the dummy placeholder
+ visited.add(dummyComponent);
+
+ for (int i = 0; i < componentMap.length; ++i) {
+ Element row = design.appendElement("row");
+
+ // Row Expand
+ DesignAttributeHandler.writeAttribute("expand", row.attributes(),
+ (int) getRowExpandRatio(i), 0, int.class);
+
+ int colspan = 1;
+ Element col;
+ for (int j = 0; j < componentMap[i].length; ++j) {
+ Component child = componentMap[i][j];
+ if (child != null) {
+ if (visited.contains(child)) {
+ // Child has already been written in the design
+ continue;
+ }
+ visited.add(child);
+
+ Element childElement = designContext.createElement(child);
+ col = row.appendElement("column");
+
+ // Write child data into design
+ ChildComponentData coords = childData.get(child);
+
+ Alignment alignment = getComponentAlignment(child);
+ if (alignment.isMiddle()) {
+ childElement.attr(":middle", "");
+ } else if (alignment.isBottom()) {
+ childElement.attr(":bottom", "");
+ }
+ if (alignment.isCenter()) {
+ childElement.attr(":center", "");
+ } else if (alignment.isRight()) {
+ childElement.attr(":right", "");
+ }
+
+ col.appendChild(childElement);
+ if (coords.row1 != coords.row2) {
+ col.attr("rowspan", ""
+ + (1 + coords.row2 - coords.row1));
+ }
+
+ colspan = 1 + coords.column2 - coords.column1;
+ if (colspan > 1) {
+ col.attr("colspan", "" + colspan);
+ }
+
+ } else {
+ boolean hasExpands = false;
+ if (i == 0
+ && lastComponentOnRow(componentMap[i], j, visited)) {
+ // A column with expand and no content in the end of
+ // first row needs to be present.
+ for (int c = j; c < componentMap[i].length; ++c) {
+ if ((int) getColumnExpandRatio(c) > 0) {
+ hasExpands = true;
+ }
+ }
+ }
+
+ if (lastComponentOnRow(componentMap[i], j, visited)
+ && !hasExpands) {
+ continue;
+ }
+
+ // Empty placeholder tag.
+ col = row.appendElement("column");
+
+ // Use colspan to make placeholders more pleasant
+ while (j + colspan < componentMap[i].length
+ && componentMap[i][j + colspan] == child) {
+ ++colspan;
+ }
+
+ int rowspan = getRowSpan(componentMap, i, j, colspan, child);
+ if (colspan > 1) {
+ col.attr("colspan", "" + colspan);
+ }
+ if (rowspan > 1) {
+ col.attr("rowspan", "" + rowspan);
+ }
+ for (int x = 0; x < rowspan; ++x) {
+ for (int y = 0; y < colspan; ++y) {
+ // Mark handled columns
+ componentMap[i + x][j + y] = dummyComponent;
+ }
+ }
+ }
+
+ // Column expands
+ if (i == 0) {
+ // Only do expands on first row
+ String expands = "";
+ boolean expandRatios = false;
+ for (int c = 0; c < colspan; ++c) {
+ int colExpand = (int) getColumnExpandRatio(j + c);
+ if (colExpand > 0) {
+ expandRatios = true;
+ }
+ expands += (c > 0 ? "," : "") + colExpand;
+ }
+ if (expandRatios) {
+ col.attr("expand", expands);
+ }
+ }
+
+ j += colspan - 1;
+ }
+ }
+ }
+
+ private int getRowSpan(Component[][] compMap, int i, int j, int colspan,
+ Component child) {
+ int rowspan = 1;
+ while (i + rowspan < compMap.length && compMap[i + rowspan][j] == child) {
+ for (int k = 0; k < colspan; ++k) {
+ if (compMap[i + rowspan][j + k] != child) {
+ return rowspan;
+ }
+ }
+ rowspan++;
+ }
+ return rowspan;
+ }
+
+ private boolean lastComponentOnRow(Component[] componentArray, int j,
+ Set<Connector> visited) {
+ while ((++j) < componentArray.length) {
+ Component child = componentArray[j];
+ if (child != null && !visited.contains(child)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("cursor-x");
+ result.add("cursor-y");
+ result.add("rows");
+ result.add("columns");
+ return result;
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/MenuBar.java b/server/src/com/vaadin/ui/MenuBar.java
index 747ce42727..c11cf02aaf 100644
--- a/server/src/com/vaadin/ui/MenuBar.java
+++ b/server/src/com/vaadin/ui/MenuBar.java
@@ -1008,8 +1008,9 @@ public class MenuBar extends AbstractComponent implements LegacyComponent,
if (node instanceof Element
&& ((Element) node).tagName().equals("menu")) {
subMenus.add((Element) node);
+ } else {
+ caption += node.toString();
}
- caption += node.toString();
}
MenuItem menu = new MenuItem(caption.trim(), icon, null);
diff --git a/server/src/com/vaadin/ui/OptionGroup.java b/server/src/com/vaadin/ui/OptionGroup.java
index 393f5399f6..ff2e384285 100644
--- a/server/src/com/vaadin/ui/OptionGroup.java
+++ b/server/src/com/vaadin/ui/OptionGroup.java
@@ -21,6 +21,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.Container;
import com.vaadin.event.FieldEvents;
import com.vaadin.event.FieldEvents.BlurEvent;
@@ -30,6 +32,7 @@ import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.shared.ui.optiongroup.OptionGroupConstants;
+import com.vaadin.ui.declarative.DesignContext;
/**
* Configures select to be used as an option group.
@@ -252,4 +255,28 @@ public class OptionGroup extends AbstractSelect implements
public boolean isHtmlContentAllowed() {
return htmlContentAllowed;
}
+
+ @Override
+ protected String readItem(Element child, Set<String> selected,
+ DesignContext context) {
+ String itemId = super.readItem(child, selected, context);
+
+ if (child.hasAttr("disabled")) {
+ setItemEnabled(itemId, false);
+ }
+
+ return itemId;
+ }
+
+ @Override
+ protected Element writeItem(Element design, Object itemId,
+ DesignContext context) {
+ Element elem = super.writeItem(design, itemId, context);
+
+ if (!isItemEnabled(itemId)) {
+ elem.attr("disabled", "");
+ }
+
+ return elem;
+ }
}
diff --git a/server/src/com/vaadin/ui/Tree.java b/server/src/com/vaadin/ui/Tree.java
index a86a9bd64b..6f5ec96f63 100644
--- a/server/src/com/vaadin/ui/Tree.java
+++ b/server/src/com/vaadin/ui/Tree.java
@@ -30,6 +30,8 @@ import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.util.ContainerHierarchicalWrapper;
@@ -57,6 +59,9 @@ import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.MultiSelectMode;
import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.shared.ui.tree.TreeConstants;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
import com.vaadin.util.ReflectTools;
/**
@@ -1301,19 +1306,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
}
}
- /**
- * Tree does not support lazy options loading mode. Setting this true will
- * throw UnsupportedOperationException.
- *
- * @see com.vaadin.ui.Select#setLazyLoading(boolean)
- */
- public void setLazyLoading(boolean useLazyLoading) {
- if (useLazyLoading) {
- throw new UnsupportedOperationException(
- "Lazy options loading is not supported by Tree.");
- }
- }
-
private ItemStyleGenerator itemStyleGenerator;
private DropHandler dropHandler;
@@ -1803,4 +1795,105 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
}
expanded.removeAll(removedItemIds);
}
+
+ /**
+ * Reads an Item from a design and inserts it into the data source.
+ * Recursively handles any children of the item as well.
+ *
+ * @since
+ * @param node
+ * an element representing the item (tree node).
+ * @param selected
+ * A set accumulating selected items. If the item that is read is
+ * marked as selected, its item id should be added to this set.
+ * @param context
+ * the DesignContext instance used in parsing
+ * @return the item id of the new item
+ *
+ * @throws DesignException
+ * if the tag name of the {@code node} element is not
+ * {@code node}.
+ */
+ @Override
+ protected String readItem(Element node, Set<String> selected,
+ DesignContext context) {
+
+ if (!"node".equals(node.tagName())) {
+ throw new DesignException("Unrecognized child element in "
+ + getClass().getSimpleName() + ": " + node.tagName());
+ }
+
+ String itemId = node.attr("text");
+ addItem(itemId);
+ if (node.hasAttr("icon")) {
+ Resource icon = DesignAttributeHandler.readAttribute("icon",
+ node.attributes(), Resource.class);
+ setItemIcon(itemId, icon);
+ }
+ if (node.hasAttr("selected")) {
+ selected.add(itemId);
+ }
+
+ for (Element child : node.children()) {
+ String childItemId = readItem(child, selected, context);
+ setParent(childItemId, itemId);
+ }
+ return itemId;
+ }
+
+ /**
+ * Recursively writes the root items and their children to a design.
+ *
+ * @since
+ * @param design
+ * the element into which to insert the items
+ * @param context
+ * the DesignContext instance used in writing
+ */
+ @Override
+ protected void writeItems(Element design, DesignContext context) {
+ for (Object itemId : rootItemIds()) {
+ writeItem(design, itemId, context);
+ }
+ }
+
+ /**
+ * Recursively writes a data source Item and its children to a design.
+ *
+ * @since
+ * @param design
+ * the element into which to insert the item
+ * @param itemId
+ * the id of the item to write
+ * @param context
+ * the DesignContext instance used in writing
+ * @return
+ */
+ @Override
+ protected Element writeItem(Element design, Object itemId,
+ DesignContext context) {
+ Element element = design.appendElement("node");
+
+ element.attr("text", itemId.toString());
+
+ Resource icon = getItemIcon(itemId);
+ if (icon != null) {
+ DesignAttributeHandler.writeAttribute("icon", element.attributes(),
+ icon, null, Resource.class);
+ }
+
+ if (isSelected(itemId)) {
+ element.attr("selected", "");
+ }
+
+ Collection<?> children = getChildren(itemId);
+ if (children != null) {
+ // Yeah... see #5864
+ for (Object childItemId : children) {
+ writeItem(element, childItemId, context);
+ }
+ }
+
+ return element;
+ }
}
diff --git a/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java b/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
index 2b446bda0e..e93a5c51cb 100644
--- a/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
+++ b/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
@@ -218,18 +218,68 @@ public class DesignAttributeHandler implements Serializable {
}
/**
- * Reads the given attribute from a set of attributes.
+ * Writes the given attribute value to a set of attributes if it differs
+ * from the default attribute value.
+ *
+ * @param attribute
+ * the attribute key
+ * @param attributes
+ * the set of attributes where the new attribute is written
+ * @param value
+ * the attribute value
+ * @param defaultValue
+ * the default attribute value
+ * @param inputType
+ * the type of the input value
+ */
+ public static <T> void writeAttribute(String attribute,
+ Attributes attributes, T value, T defaultValue, Class<T> inputType) {
+ if (!getFormatter().canConvert(inputType)) {
+ throw new IllegalArgumentException("input type: "
+ + inputType.getName() + " not supported");
+ }
+ if (!SharedUtil.equals(value, defaultValue)) {
+ String attributeValue = toAttributeValue(inputType, value);
+ attributes.put(attribute, attributeValue);
+ }
+ }
+
+ /**
+ * Reads the given attribute from a set of attributes. If attribute does not
+ * exist return a given default value.
*
* @param attribute
* the attribute key
* @param attributes
* the set of attributes to read from
+ * @param defaultValue
+ * the default value to return if attribute does not exist
* @param outputType
* the output type for the attribute
* @return the attribute value or the default value if the attribute is not
* found
*/
public static <T> T readAttribute(String attribute, Attributes attributes,
+ T defaultValue, Class<T> outputType) {
+ T value = readAttribute(attribute, attributes, outputType);
+ if (value != null) {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Reads the given attribute from a set of attributes.
+ *
+ * @param attribute
+ * the attribute key
+ * @param attributes
+ * the set of attributes to read from
+ * @param outputType
+ * the output type for the attribute
+ * @return the attribute value or null
+ */
+ public static <T> T readAttribute(String attribute, Attributes attributes,
Class<T> outputType) {
if (!getFormatter().canConvert(outputType)) {
throw new IllegalArgumentException("output type: "
@@ -249,33 +299,6 @@ public class DesignAttributeHandler implements Serializable {
}
/**
- * Writes the given attribute value to a set of attributes if it differs
- * from the default attribute value.
- *
- * @param attribute
- * the attribute key
- * @param attributes
- * the set of attributes where the new attribute is written
- * @param value
- * the attribute value
- * @param defaultValue
- * the default attribute value
- * @param inputType
- * the type of the input value
- */
- public static <T> void writeAttribute(String attribute,
- Attributes attributes, T value, T defaultValue, Class<T> inputType) {
- if (!getFormatter().canConvert(inputType)) {
- throw new IllegalArgumentException("input type: "
- + inputType.getName() + " not supported");
- }
- if (!SharedUtil.equals(value, defaultValue)) {
- String attributeValue = toAttributeValue(inputType, value);
- attributes.put(attribute, attributeValue);
- }
- }
-
- /**
* Returns the design attribute name corresponding the given method name.
* For example given a method name <code>setPrimaryStyleName</code> the
* return value would be <code>primary-style-name</code>
@@ -425,5 +448,4 @@ public class DesignAttributeHandler implements Serializable {
return (methods != null && methods.length > 1) ? methods[1] : null;
}
}
-
}
diff --git a/server/src/com/vaadin/ui/declarative/DesignContext.java b/server/src/com/vaadin/ui/declarative/DesignContext.java
index fe3abcfb77..657e15896c 100644
--- a/server/src/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/com/vaadin/ui/declarative/DesignContext.java
@@ -170,6 +170,7 @@ public class DesignContext implements Serializable {
* component, the mapping from c to the string is removed. Similarly, if
* component was mapped to some string s different from localId, the mapping
* from s to component is removed.
+ *
* @param component
* The component whose local id is to be set.
* @param localId
@@ -185,6 +186,18 @@ public class DesignContext implements Serializable {
}
/**
+ * Returns the local id for a component
+ *
+ * @param component
+ * The component whose local id to get.
+ * @return the local id of the component, or null if the component has no
+ * local id assigned
+ */
+ public String getComponentLocalId(Component component) {
+ return componentToLocalId.get(component);
+ }
+
+ /**
* Creates a mapping between the given caption and the component. Returns
* true if caption was already mapped to some component.
*
diff --git a/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java b/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
index e6dee44812..3bc1ebfbf9 100644
--- a/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
+++ b/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
@@ -16,7 +16,9 @@
package com.vaadin.tests.components.menubar;
import java.io.IOException;
+import java.util.List;
+import org.junit.Assert;
import org.junit.Test;
import com.vaadin.server.ExternalResource;
@@ -128,7 +130,7 @@ public class MenuBarDeclarativeTest extends DeclarativeTestBase<MenuBar> {
MenuBar menuBar = new MenuBar();
menuBar.setHtmlContentAllowed(true);
MenuItem fileMenu = menuBar.addItem("<b>File</b>", null);
- fileMenu.addItem("<font style='color: red'>Save</font>", null);
+ fileMenu.addItem("<font style=\"color: red\">Save</font>", null);
fileMenu.addItem("Open", new ThemeResource(
"../runo/icons/16/folder.png"), null);
fileMenu.addSeparator();
@@ -136,4 +138,62 @@ public class MenuBarDeclarativeTest extends DeclarativeTestBase<MenuBar> {
testRead(design, menuBar);
testWrite(design, menuBar);
}
+
+ @Override
+ public MenuBar testRead(String design, MenuBar expected) {
+ MenuBar result = super.testRead(design, expected);
+
+ List<MenuItem> expectedMenuItems = expected.getItems();
+ List<MenuItem> actualMenuItems = result.getItems();
+ Assert.assertEquals("Different amount of menu items",
+ expectedMenuItems.size(), actualMenuItems.size());
+
+ for (int i = 0; i < expectedMenuItems.size(); ++i) {
+ compareMenus(expectedMenuItems.get(i), actualMenuItems.get(i));
+ }
+
+ return result;
+ }
+
+ private void compareMenus(MenuItem expected, MenuItem actual) {
+ String baseError = "Error Comparing MenuItem " + expected.getText()
+ + ": ";
+ Assert.assertEquals(baseError + "Visibile", expected.isVisible(),
+ actual.isVisible());
+ Assert.assertEquals(baseError + "Checkable", expected.isCheckable(),
+ actual.isCheckable());
+ Assert.assertEquals(baseError + "Checked", expected.isChecked(),
+ actual.isChecked());
+ Assert.assertEquals(baseError + "Separator", expected.isSeparator(),
+ actual.isSeparator());
+ Assert.assertEquals(baseError + "Enabled", expected.isEnabled(),
+ actual.isEnabled());
+
+ Assert.assertEquals(baseError + "Text", expected.getText(),
+ actual.getText());
+ Assert.assertEquals(baseError + "Description",
+ expected.getDescription(), actual.getDescription());
+ Assert.assertEquals(baseError + "Style Name", expected.getStyleName(),
+ actual.getStyleName());
+
+ if (expected.getIcon() != null) {
+ Assert.assertNotNull(baseError + "Icon was null", actual.getIcon());
+ } else {
+ if (actual.getIcon() != null) {
+ Assert.fail(baseError + "Icon should've been null");
+ }
+ }
+
+ Assert.assertEquals(baseError + "Has Children", expected.hasChildren(),
+ actual.hasChildren());
+ if (expected.hasChildren()) {
+ List<MenuItem> children = expected.getChildren();
+ List<MenuItem> actualChildren = actual.getChildren();
+ Assert.assertEquals(baseError + "Child count", children.size(),
+ actualChildren.size());
+ for (int i = 0; i < children.size(); ++i) {
+ compareMenus(children.get(i), actualChildren.get(i));
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/design/AbstractComponentSetResponsiveTest.java b/server/tests/src/com/vaadin/tests/design/AbstractComponentSetResponsiveTest.java
index f7dbd0c97e..83b3e577dc 100644
--- a/server/tests/src/com/vaadin/tests/design/AbstractComponentSetResponsiveTest.java
+++ b/server/tests/src/com/vaadin/tests/design/AbstractComponentSetResponsiveTest.java
@@ -17,21 +17,22 @@ package com.vaadin.tests.design;
import org.junit.Test;
-import com.vaadin.tests.design.DeclarativeTestBase;
-import com.vaadin.ui.GridLayout;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Label;
public class AbstractComponentSetResponsiveTest extends
- DeclarativeTestBase<GridLayout> {
+ DeclarativeTestBase<Label> {
@Test
public void testResponsiveFlag() {
- GridLayout gl = new GridLayout();
- gl.setResponsive(true);
+ Label label = new Label();
+ label.setContentMode(ContentMode.HTML);
+ label.setResponsive(true);
- String design = "<v-grid-layout responsive='true' />";
+ String design = "<v-label responsive='true' />";
- testWrite(design, gl);
- testRead(design, gl);
+ testWrite(design, label);
+ testRead(design, label);
}
}
diff --git a/server/tests/src/com/vaadin/tests/design/DeclarativeTestBase.java b/server/tests/src/com/vaadin/tests/design/DeclarativeTestBase.java
index 10f1e5c711..7e8b5c7767 100644
--- a/server/tests/src/com/vaadin/tests/design/DeclarativeTestBase.java
+++ b/server/tests/src/com/vaadin/tests/design/DeclarativeTestBase.java
@@ -60,6 +60,10 @@ public abstract class DeclarativeTestBase<T extends Component> extends
if (readMethod == null || writeMethod == null) {
continue;
}
+ // Needed to access public properties inherited from a
+ // nonpublic superclass, see #17425
+ readMethod.setAccessible(true);
+ writeMethod.setAccessible(true);
if (Connector.class.isAssignableFrom(c)
&& readMethod.getName().equals("getParent")) {
// Hack to break cycles in the connector hierarchy
diff --git a/server/tests/src/com/vaadin/tests/design/DeclarativeTestBaseBase.java b/server/tests/src/com/vaadin/tests/design/DeclarativeTestBaseBase.java
index 4cb627d035..3afef0e2ee 100644
--- a/server/tests/src/com/vaadin/tests/design/DeclarativeTestBaseBase.java
+++ b/server/tests/src/com/vaadin/tests/design/DeclarativeTestBaseBase.java
@@ -140,8 +140,10 @@ public abstract class DeclarativeTestBaseBase<T extends Component> {
}
- public void testRead(String design, T expected) {
- assertEquals(expected, read(design));
+ public T testRead(String design, T expected) {
+ T read = read(design);
+ assertEquals(expected, read);
+ return read;
}
public void testWrite(String design, T expected) {
diff --git a/server/tests/src/com/vaadin/tests/design/DesignContextLocalIdTest.java b/server/tests/src/com/vaadin/tests/design/DesignContextLocalIdTest.java
index c3d7e6d8cf..6cedb17409 100644
--- a/server/tests/src/com/vaadin/tests/design/DesignContextLocalIdTest.java
+++ b/server/tests/src/com/vaadin/tests/design/DesignContextLocalIdTest.java
@@ -20,11 +20,26 @@ import static org.junit.Assert.assertEquals;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import org.jsoup.nodes.Element;
import org.junit.Test;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.Accordion;
import com.vaadin.ui.Button;
+import com.vaadin.ui.ComponentContainer;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.CustomLayout;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.SingleComponentContainer;
+import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.VerticalSplitPanel;
+import com.vaadin.ui.Window;
import com.vaadin.ui.declarative.Design;
import com.vaadin.ui.declarative.DesignContext;
@@ -57,4 +72,55 @@ public class DesignContextLocalIdTest {
assertEquals("Found the wrong component by local id.", ctx
.getComponentByLocalId("bar").getClass(), TextField.class);
}
+
+ @Test
+ public void testWriteLocalId() {
+ DesignContext ctx = new DesignContext();
+
+ Button b = new Button();
+ ctx.setComponentLocalId(b, "button-id");
+
+ assertEquals("button-id", ctx.createElement(b).attr("_id"));
+ }
+
+ @Test
+ public void testWriteChildLocalIds() throws Exception {
+ DesignContext ctx = new DesignContext();
+
+ ComponentContainer[] ctrs = { new AbsoluteLayout(), new CssLayout(),
+ new GridLayout(1, 1), new CustomLayout(),
+ new HorizontalLayout(), new VerticalLayout(), new Accordion(),
+ new HorizontalSplitPanel(), new TabSheet(),
+ new VerticalSplitPanel() };
+
+ Button b = new Button();
+ ctx.setComponentLocalId(b, "button-id");
+
+ for (ComponentContainer ctr : ctrs) {
+ ctr.addComponent(b);
+ Element e = ctx.createElement(ctr);
+ assertEquals("Unexpected child local id for "
+ + ctr.getClass().getSimpleName(), "button-id", e
+ .getElementsByTag("v-button").first().attr("_id"));
+ }
+
+ SingleComponentContainer[] sctrs = { new Window(), new Panel() };
+
+ for (SingleComponentContainer ctr : sctrs) {
+ ctr.setContent(b);
+ Element e = ctx.createElement(ctr);
+ assertEquals("Unexpected child local id for "
+ + ctr.getClass().getSimpleName(), "button-id", e
+ .getElementsByTag("v-button").first().attr("_id"));
+ }
+ }
+
+ @Test
+ public void testGetLocalId() {
+ DesignContext ctx = new DesignContext();
+ Label label = new Label();
+ ctx.setComponentLocalId(label, "my-local-id");
+ ctx.setRootComponent(label);
+ assertEquals("my-local-id", ctx.getComponentLocalId(label));
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/AbstractLayoutDeclarativeMarginTest.java b/server/tests/src/com/vaadin/tests/server/component/AbstractLayoutDeclarativeMarginTest.java
new file mode 100644
index 0000000000..70855f67dc
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/AbstractLayoutDeclarativeMarginTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.server.component;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.MarginInfo;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.AbstractLayout;
+import com.vaadin.ui.VerticalLayout;
+
+public class AbstractLayoutDeclarativeMarginTest extends
+ DeclarativeTestBase<AbstractLayout> {
+
+ @Test
+ public void testMarginInfo() {
+ VerticalLayout vl = new VerticalLayout();
+
+ String left = getMarginTag(true, false, false, false);
+ MarginInfo leftInfo = getMarginInfo(true, false, false, false);
+
+ String right = getMarginTag(false, true, false, false);
+ MarginInfo rightInfo = getMarginInfo(false, true, false, false);
+
+ String top = getMarginTag(false, false, true, false);
+ MarginInfo topInfo = getMarginInfo(false, false, true, false);
+
+ String bottom = getMarginTag(false, false, false, true);
+ MarginInfo bottomInfo = getMarginInfo(false, false, false, true);
+
+ String topLeft = getMarginTag(true, false, true, false);
+ MarginInfo topLeftInfo = getMarginInfo(true, false, true, false);
+
+ String topRight = getMarginTag(false, true, true, false);
+ MarginInfo topRightInfo = getMarginInfo(false, true, true, false);
+
+ String bottomLeft = getMarginTag(true, false, false, true);
+ MarginInfo bottomLeftInfo = getMarginInfo(true, false, false, true);
+
+ String bottomRight = getMarginTag(false, true, false, true);
+ MarginInfo bottomRightInfo = getMarginInfo(false, true, false, true);
+
+ testRW(vl, left, leftInfo);
+ testRW(vl, right, rightInfo);
+ testRW(vl, top, topInfo);
+ testRW(vl, bottom, bottomInfo);
+
+ testRW(vl, topLeft, topLeftInfo);
+ testRW(vl, topRight, topRightInfo);
+ testRW(vl, bottomLeft, bottomLeftInfo);
+ testRW(vl, bottomRight, bottomRightInfo);
+
+ // Test special case of all edges margin'ed
+ testRW(vl, getMarginTag(true, true, true, true), new MarginInfo(true));
+ }
+
+ private void testRW(VerticalLayout vl, String design, MarginInfo margin) {
+ vl.setMargin(margin);
+ testWrite(design, vl);
+ testRead(design, vl);
+ }
+
+ private String getMarginTag(boolean left, boolean right, boolean top,
+ boolean bottom) {
+ String s = "<v-vertical-layout ";
+
+ if (left && right && top && bottom) {
+ s += "margin='true'";
+ } else {
+ if (left) {
+ s += "margin-left='true' ";
+ }
+ if (right) {
+ s += "margin-right='true' ";
+ }
+ if (top) {
+ s += "margin-top='true' ";
+ }
+ if (bottom) {
+ s += "margin-bottom='true' ";
+ }
+ }
+ return s + " />";
+ }
+
+ private MarginInfo getMarginInfo(boolean left, boolean right, boolean top,
+ boolean bottom) {
+ return new MarginInfo(top, right, bottom, left);
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutDeclarativeTest.java
index 14629827fb..80ca95733c 100644
--- a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutDeclarativeTest.java
+++ b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/AbsoluteLayoutDeclarativeTest.java
@@ -31,38 +31,30 @@ public class AbsoluteLayoutDeclarativeTest extends
DeclarativeTestBase<AbsoluteLayout> {
@Test
- public void testPlainTextRead() {
- testRead(getDesign(), getExpected());
- }
-
- @Test
- public void testPlainTextWrite() {
- testWrite(getDesign(), getExpected());
- }
-
- protected String getDesign() {
- return "<v-absolute-layout>"
+ public void testAbsoluteLayoutFeatures() {
+ String design = "<v-absolute-layout caption=\"test-layout\">"
+ "<v-button :top='100px' :left='0px' :z-index=21>OK</v-button>"
+ "<v-button :bottom='0px' :right='0px'>Cancel</v-button>"
+ "</v-absolute-layout>";
- }
-
- protected AbsoluteLayout getExpected() {
- AbsoluteLayout c = new AbsoluteLayout();
+ AbsoluteLayout layout = new AbsoluteLayout();
+ layout.setCaption("test-layout");
Button b1 = new Button("OK");
b1.setCaptionAsHtml(true);
Button b2 = new Button("Cancel");
b2.setCaptionAsHtml(true);
+ layout.addComponent(b1, "top: 100px; left: 0px; z-index: 21");
+ layout.addComponent(b2, "bottom: 0px; right: 0px;");
- c.addComponent(b1, "top: 100px; left: 0px; z-index: 21");
- c.addComponent(b2, "bottom: 0px; right: 0px;");
- System.out.println(c.getComponentCount());
- return c;
- };
+ testWrite(design, layout);
+ testRead(design, layout);
+ }
@Test
public void testEmpty() {
- testRead("<v-absolute-layout/>", new AbsoluteLayout());
+ String design = "<v-absolute-layout/>";
+ AbsoluteLayout layout = new AbsoluteLayout();
+ testRead(design, layout);
+ testWrite(design, layout);
}
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ReadDesignTest.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ReadDesignTest.java
deleted file mode 100644
index f17e1ada44..0000000000
--- a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/ReadDesignTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.server.component.absolutelayout;
-
-import java.util.Iterator;
-
-import junit.framework.TestCase;
-
-import org.jsoup.nodes.Attributes;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Tag;
-
-import com.vaadin.server.Sizeable;
-import com.vaadin.ui.AbsoluteLayout;
-import com.vaadin.ui.AbsoluteLayout.ComponentPosition;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.declarative.DesignContext;
-
-/**
- * Test case for reading AbsoluteLayout from design
- *
- * @since
- * @author Vaadin Ltd
- */
-public class ReadDesignTest extends TestCase {
-
- private AbsoluteLayout root;
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- root = createLayout();
- }
-
- public void testAttributes() {
- assertEquals("test-layout", root.getCaption());
- Iterator<Component> children = root.iterator();
- assertEquals("test-label", children.next().getCaption());
- assertEquals("test-button", children.next().getCaption());
- }
-
- public void testTopLeftPosition() {
- ComponentPosition position = root.getPosition(root.iterator().next());
- assertEquals(Sizeable.Unit.PIXELS, position.getTopUnits());
- assertEquals(100.0f, position.getTopValue());
- assertEquals(Sizeable.Unit.PERCENTAGE, position.getLeftUnits());
- assertEquals(50.0f, position.getLeftValue());
- }
-
- public void testBottomRightPosition() {
- Iterator<Component> children = root.iterator();
- children.next();
- ComponentPosition position = root.getPosition(children.next());
- assertEquals(Sizeable.Unit.PIXELS, position.getBottomUnits());
- assertEquals(100.0f, position.getBottomValue());
- assertEquals(Sizeable.Unit.PERCENTAGE, position.getRightUnits());
- assertEquals(50.0f, position.getRightValue());
- }
-
- public void testZIndex() {
- ComponentPosition position = root.getPosition(root.iterator().next());
- assertEquals(2, position.getZIndex());
- }
-
- private AbsoluteLayout createLayout() {
- DesignContext ctx = new DesignContext();
- Element design = createDesign();
- Component child = ctx.readDesign(design);
- return (AbsoluteLayout) child;
- }
-
- private Element createDesign() {
-
- Attributes rootAttributes = new Attributes();
- rootAttributes.put("caption", "test-layout");
- Element node = new Element(Tag.valueOf("v-absolute-layout"), "",
- rootAttributes);
-
- Attributes firstChildAttributes = new Attributes();
- firstChildAttributes.put("caption", "test-label");
- firstChildAttributes.put(":top", "100px");
- firstChildAttributes.put(":left", "50%");
- firstChildAttributes.put(":z-index", "2");
- Element firstChild = new Element(Tag.valueOf("v-label"), "",
- firstChildAttributes);
- node.appendChild(firstChild);
-
- Attributes secondChildAttributes = new Attributes();
- secondChildAttributes.put(":bottom", "100px");
- secondChildAttributes.put(":right", "50%");
- Element secondChild = new Element(Tag.valueOf("v-button"), "",
- secondChildAttributes);
- secondChild.html("test-button");
- node.appendChild(secondChild);
- return node;
- }
-}
diff --git a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/WriteDesignTest.java b/server/tests/src/com/vaadin/tests/server/component/absolutelayout/WriteDesignTest.java
deleted file mode 100644
index 39a2207819..0000000000
--- a/server/tests/src/com/vaadin/tests/server/component/absolutelayout/WriteDesignTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.server.component.absolutelayout;
-
-import junit.framework.TestCase;
-
-import org.jsoup.nodes.Attributes;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Tag;
-
-import com.vaadin.ui.AbsoluteLayout;
-import com.vaadin.ui.Label;
-import com.vaadin.ui.declarative.DesignContext;
-
-/**
- * Test case for writing AbsoluteLayout to design
- *
- * @since
- * @author Vaadin Ltd
- */
-public class WriteDesignTest extends TestCase {
-
- public void testSynchronizeEmptyLayout() {
- AbsoluteLayout layout = createTestLayout();
- layout.removeAllComponents();
- Element design = createDesign();
- layout.writeDesign(design, createDesignContext());
- assertEquals(0, design.childNodes().size());
- assertEquals("changed-caption", design.attr("caption"));
- }
-
- public void testSynchronizeLayoutWithChildren() {
- AbsoluteLayout layout = createTestLayout();
- Element design = createDesign();
- layout.writeDesign(design, createDesignContext());
- assertEquals(2, design.childNodes().size());
- assertEquals("v-label", ((Element) design.childNode(0)).tagName());
- assertEquals("v-label", ((Element) design.childNode(1)).tagName());
- }
-
- public void testSynchronizePosition() {
- AbsoluteLayout layout = createTestLayout();
- Element design = createDesign();
- layout.writeDesign(design, createDesignContext());
- Attributes attributes = design.childNode(0).attributes();
- assertEquals("50px", attributes.get(":top"));
- assertEquals("50%", attributes.get(":left"));
- assertEquals("2", attributes.get(":z-index"));
- attributes = design.childNode(1).attributes();
- assertEquals("50px", attributes.get(":bottom"));
- assertEquals("50%", attributes.get(":right"));
- }
-
- private AbsoluteLayout createTestLayout() {
- AbsoluteLayout layout = new AbsoluteLayout();
- layout.setCaption("changed-caption");
- layout.addComponent(new Label("test-label"),
- "top:50px;left:50%;z-index:2");
- layout.addComponent(new Label("test-label-2"),
- "bottom:50px;right:50%;z-index:3");
- return layout;
- }
-
- private Element createDesign() {
- // make sure that the design node has old content that should be removed
- Attributes rootAttributes = new Attributes();
- rootAttributes.put("caption", "test-layout");
- Element node = new Element(Tag.valueOf("v-absolute-layout"), "",
- rootAttributes);
- Attributes firstChildAttributes = new Attributes();
- firstChildAttributes.put("caption", "test-label");
- Element firstChild = new Element(Tag.valueOf("v-label"), "",
- firstChildAttributes);
- node.appendChild(firstChild);
-
- Attributes secondChildAttributes = new Attributes();
- secondChildAttributes.put("caption", "test-button");
- Element secondChild = new Element(Tag.valueOf("v-button"), "",
- secondChildAttributes);
- node.appendChild(secondChild);
- return node;
- }
-
- private DesignContext createDesignContext() {
- return new DesignContext();
- }
-}
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/AbstractComponentDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/AbstractComponentDeclarativeTest.java
new file mode 100644
index 0000000000..4f45168a32
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/AbstractComponentDeclarativeTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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.server.component.abstractcomponent;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.lang.reflect.Field;
+import java.nio.charset.Charset;
+import java.util.Locale;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.parser.Tag;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.ErrorMessage.ErrorLevel;
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.FileResource;
+import com.vaadin.server.Responsive;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.server.UserError;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.declarative.Design;
+import com.vaadin.ui.declarative.DesignContext;
+
+/**
+ * Test cases for reading and writing the properties of AbstractComponent.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class AbstractComponentDeclarativeTest extends
+ DeclarativeTestBase<AbstractComponent> {
+
+ private AbstractComponent component;
+
+ @Before
+ public void setUp() {
+ Label l = new Label();
+ l.setContentMode(ContentMode.HTML);
+ component = l;
+ }
+
+ @Test
+ public void testEmptyDesign() {
+ String design = "<v-label>";
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testProperties() {
+ String design = "<v-label id=\"testId\" primary-style-name=\"test-style\" "
+ + "caption=\"test-caption\" locale=\"fi_FI\" description=\"test-description\" "
+ + "error=\"<div>test-error</div>\" immediate=\"true\"/>";
+ component.setId("testId");
+ component.setPrimaryStyleName("test-style");
+ component.setCaption("test-caption");
+ component.setLocale(new Locale("fi", "FI"));
+ component.setDescription("test-description");
+ component.setComponentError(new UserError("<div>test-error</div>",
+ com.vaadin.server.AbstractErrorMessage.ContentMode.HTML,
+ ErrorLevel.ERROR));
+ component.setImmediate(true);
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testReadImmediate() {
+ // Additional tests for the immediate property, including
+ // explicit immediate values
+ String[] design = { "<v-label/>", "<v-label immediate=\"false\"/>",
+ "<v-label immediate=\"true\"/>", "<v-label immediate=\"\"/>" };
+ Boolean[] explicitImmediate = { null, Boolean.FALSE, Boolean.TRUE,
+ Boolean.TRUE };
+ boolean[] immediate = { false, false, true, true };
+ for (int i = 0; i < design.length; i++) {
+ component = (AbstractComponent) Design
+ .read(new ByteArrayInputStream(design[i].getBytes(Charset
+ .forName("UTF-8"))));
+ assertEquals(immediate[i], component.isImmediate());
+ assertEquals(explicitImmediate[i], getExplicitImmediate(component));
+ }
+ }
+
+ @Test
+ public void testExternalIcon() {
+ String design = "<v-label icon=\"http://example.com/example.gif\"/>";
+ component
+ .setIcon(new ExternalResource("http://example.com/example.gif"));
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testThemeIcon() {
+ String design = "<v-label icon=\"theme://example.gif\"/>";
+ component.setIcon(new ThemeResource("example.gif"));
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testFileResourceIcon() {
+ String design = "<v-label icon=\"img/example.gif\"/>";
+ component.setIcon(new FileResource(new File("img/example.gif")));
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testWidthAndHeight() {
+ String design = "<v-label width=\"70%\" height=\"12px\"/>";
+ component.setWidth("70%");
+ component.setHeight("12px");
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testSizeFull() {
+ String design = "<v-label size-full=\"true\"/>";
+ component.setSizeFull();
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testSizeAuto() {
+ String design = "<v-label size-auto=\"true\"/>";
+ component.setSizeUndefined();
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testHeightFull() {
+ String design = "<v-label height-full=\"true\"/ width=\"20px\"/>";
+ component.setHeight("100%");
+ component.setWidth("20px");
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testHeightAuto() {
+ String design = "<v-horizontal-split-panel height-auto=\"true\"/ width=\"20px\" >";
+ // we need to have default height of 100% -> use split panel
+ AbstractComponent component = new HorizontalSplitPanel();
+ component.setHeight(null);
+ component.setWidth("20px");
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testWidthFull() {
+ String design = "<v-button width-full=\"true\"/ height=\"20px\">Foo</button>";
+ AbstractComponent component = new Button();
+ component.setCaptionAsHtml(true);
+ component.setCaption("Foo");
+ component.setHeight("20px");
+ component.setWidth("100%");
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testWidthAuto() {
+ String design = "<v-label height=\"20px\"/ width-auto=\"true\"/>";
+ component.setCaptionAsHtml(false);
+ component.setHeight("20px");
+ component.setWidth(null);
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testResponsive() {
+ String design = "<v-label responsive =\"true\"/>";
+ Responsive.makeResponsive(component);
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void testResponsiveFalse() {
+ String design = "<v-label responsive =\"false\"/>";
+ // Only test read as the attribute responsive=false would not be written
+ testRead(design, component);
+ }
+
+ @Test
+ public void testReadAlreadyResponsive() {
+ AbstractComponent component = new Label();
+ Responsive.makeResponsive(component);
+ Element design = createDesign("responsive", "");
+ component.readDesign(design, new DesignContext());
+ assertEquals("Component should have only one extension", 1, component
+ .getExtensions().size());
+ }
+
+ private Element createDesign(String key, String value) {
+ Attributes attributes = new Attributes();
+ attributes.put(key, value);
+ Element node = new Element(Tag.valueOf("v-label"), "", attributes);
+ return node;
+ }
+
+ private Boolean getExplicitImmediate(AbstractComponent component) {
+ try {
+ Field immediate = AbstractComponent.class
+ .getDeclaredField("explicitImmediateValue");
+ immediate.setAccessible(true);
+ return (Boolean) immediate.get(component);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Getting the field explicitImmediateValue failed.");
+ }
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/ReadDesignTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/ReadDesignTest.java
deleted file mode 100644
index 79979e03d9..0000000000
--- a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/ReadDesignTest.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * 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.server.component.abstractcomponent;
-
-import java.lang.reflect.Field;
-
-import junit.framework.TestCase;
-
-import org.jsoup.nodes.Attributes;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Tag;
-
-import com.vaadin.server.ExternalResource;
-import com.vaadin.server.FileResource;
-import com.vaadin.server.Responsive;
-import com.vaadin.server.ThemeResource;
-import com.vaadin.ui.AbstractComponent;
-import com.vaadin.ui.Label;
-import com.vaadin.ui.declarative.DesignContext;
-
-/**
- * Test case for reading the attributes of the AbstractComponent from design
- *
- * @author Vaadin Ltd
- */
-public class ReadDesignTest extends TestCase {
-
- private DesignContext ctx;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- ctx = new DesignContext();
- }
-
- public void testSynchronizeId() {
- Element design = createDesign("id", "testId");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals("testId", component.getId());
- }
-
- public void testSynchronizePrimaryStyleName() {
- Element design = createDesign("primary-style-name", "test-style");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals("test-style", component.getPrimaryStyleName());
- }
-
- public void testSynchronizeCaption() {
- Element design = createDesign("caption", "test-caption");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals("test-caption", component.getCaption());
- }
-
- public void testSynchronizeLocale() {
- Element design = createDesign("locale", "fi_FI");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals("fi", component.getLocale().getLanguage());
- assertEquals("FI", component.getLocale().getCountry());
- }
-
- public void testSynchronizeExternalIcon() {
- Element design = createDesign("icon", "http://example.com/example.gif");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertTrue("Incorrect resource type returned", component.getIcon()
- .getClass().isAssignableFrom(ExternalResource.class));
- assertEquals("http://example.com/example.gif",
- ((ExternalResource) component.getIcon()).getURL());
- }
-
- public void testSynchronizeThemeIcon() {
- Element design = createDesign("icon", "theme://example.gif");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertTrue("Incorrect resource type returned", component.getIcon()
- .getClass().isAssignableFrom(ThemeResource.class));
- }
-
- public void testSynchronizeFileResource() {
- Element design = createDesign("icon", "img/example.gif");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertTrue("Incorrect resource type returned", component.getIcon()
- .getClass().isAssignableFrom(FileResource.class));
- }
-
- public void testSynchronizeImmediate() {
- Element design = createDesign("immediate", "true");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(true, component.isImmediate());
- assertEquals(Boolean.TRUE, getExplicitImmediate(component));
- // Synchronize with a design having no immediate attribute -
- // explicitImmediate should then be null.
- design = createDesign("description", "test-description");
- component = getComponent();
- component.readDesign(design, ctx);
- // Synchronize with a design having immediate = false
- design = createDesign("immediate", "false");
- component.readDesign(design, ctx);
- assertEquals(false, component.isImmediate());
- assertEquals(Boolean.FALSE, getExplicitImmediate(component));
- // Synchronize with a design having immediate = "" - should correspond
- // to
- // true.
- design = createDesign("immediate", "");
- component.readDesign(design, ctx);
- assertEquals(true, component.isImmediate());
- assertEquals(Boolean.TRUE, getExplicitImmediate(component));
- }
-
- public void testSynchronizeDescription() {
- Element design = createDesign("description", "test-description");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals("test-description", component.getDescription());
- }
-
- public void testSynchronizeComponentError() {
- Element design = createDesign("error", "<div>test-error</div>");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals("<div>test-error</div>", component.getComponentError()
- .getFormattedHtmlMessage());
- }
-
- public void testSynchronizeSizeFull() {
- Element design = createDesign("size-full", "");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(100, component.getWidth(), 0.1f);
- assertEquals(100, component.getHeight(), 0.1f);
- }
-
- public void testSynchronizeSizeAuto() {
- Element design = createDesign("size-auto", "");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(-1, component.getWidth(), 0.1f);
- assertEquals(-1, component.getHeight(), 0.1f);
- }
-
- public void testSynchronizeHeightFull() {
- Element design = createDesign("height-full", "");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(100, component.getHeight(), 0.1f);
- }
-
- public void testSynchronizeHeightAuto() {
- Element design = createDesign("height-auto", "");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(-1, component.getHeight(), 0.1f);
- }
-
- public void testSynchronizeWidthFull() {
- Element design = createDesign("width-full", "");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(100, component.getWidth(), 0.1f);
- }
-
- public void testSynchronizeWidthAuto() {
- Element design = createDesign("width-auto", "");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(-1, component.getWidth(), 0.1f);
- }
-
- public void testSynchronizeWidth() {
- Element design = createDesign("width", "12px");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(12, component.getWidth(), 0.1f);
- assertEquals(com.vaadin.server.Sizeable.Unit.PIXELS,
- component.getWidthUnits());
- }
-
- public void testSynchronizeHeight() {
- Element design = createDesign("height", "12px");
- AbstractComponent component = getComponent();
- component.readDesign(design, ctx);
- assertEquals(12, component.getHeight(), 0.1f);
- assertEquals(com.vaadin.server.Sizeable.Unit.PIXELS,
- component.getHeightUnits());
- }
-
- public void testSynchronizeNotResponsive() {
- AbstractComponent component = getComponent();
- Responsive.makeResponsive(component);
- Element design = createDesign("responsive", "false");
- component.readDesign(design, ctx);
- assertEquals("Component should not have extensions", 0, component
- .getExtensions().size());
- }
-
- public void testSynchronizeResponsive() {
- AbstractComponent component = getComponent();
- Element design = createDesign("responsive", "");
- component.readDesign(design, ctx);
- assertEquals("Component should have one extension", 1, component
- .getExtensions().size());
- assertTrue("Extension should be responsive", component.getExtensions()
- .iterator().next() instanceof Responsive);
- }
-
- public void testSynchronizeAlreadyResponsive() {
- AbstractComponent component = getComponent();
- Responsive.makeResponsive(component);
- Element design = createDesign("responsive", "");
- component.readDesign(design, ctx);
- assertEquals("Component should have only one extension", 1, component
- .getExtensions().size());
- }
-
- private AbstractComponent getComponent() {
- return new Label();
- }
-
- private Element createDesign(String key, String value) {
- Attributes attributes = new Attributes();
- attributes.put(key, value);
- Element node = new Element(Tag.valueOf("v-label"), "", attributes);
- return node;
- }
-
- private Boolean getExplicitImmediate(AbstractComponent component) {
- try {
- Field immediate = AbstractComponent.class
- .getDeclaredField("explicitImmediateValue");
- immediate.setAccessible(true);
- return (Boolean) immediate.get(component);
- } catch (Exception e) {
- throw new RuntimeException(
- "Getting the field explicitImmediateValue failed.");
- }
- }
-}
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/WriteDesignTest.java b/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/WriteDesignTest.java
deleted file mode 100644
index 68b7a46cde..0000000000
--- a/server/tests/src/com/vaadin/tests/server/component/abstractcomponent/WriteDesignTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * 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.server.component.abstractcomponent;
-
-import java.io.File;
-import java.util.Locale;
-
-import junit.framework.TestCase;
-
-import org.jsoup.nodes.Attributes;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Tag;
-
-import com.vaadin.server.AbstractErrorMessage.ContentMode;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
-import com.vaadin.server.ExternalResource;
-import com.vaadin.server.FileResource;
-import com.vaadin.server.Responsive;
-import com.vaadin.server.ThemeResource;
-import com.vaadin.server.UserError;
-import com.vaadin.ui.AbstractComponent;
-import com.vaadin.ui.Button;
-import com.vaadin.ui.HorizontalSplitPanel;
-import com.vaadin.ui.TabSheet;
-import com.vaadin.ui.declarative.DesignContext;
-
-/**
- * Test case for writing the attributes of the AbstractComponent to design
- *
- * @author Vaadin Ltd
- */
-public class WriteDesignTest extends TestCase {
-
- private DesignContext ctx;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- ctx = new DesignContext();
- }
-
- public void testSynchronizeId() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setId("testId");
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("testId", design.attr("id"));
- }
-
- public void testSynchronizePrimaryStyleName() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setPrimaryStyleName("test-style");
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("test-style", design.attr("primary-style-name"));
- }
-
- public void testSynchronizeCaption() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setCaption("test-caption");
- component.writeDesign(design, ctx);
- // We only changed the caption, which is not
- // an attribute.
- assertEquals(0, design.attributes().size());
- assertEquals("test-caption", design.html());
- }
-
- public void testSynchronizeLocale() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setLocale(new Locale("fi", "FI"));
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("fi_FI", design.attr("locale"));
- }
-
- public void testSynchronizeExternalIcon() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component
- .setIcon(new ExternalResource("http://example.com/example.gif"));
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("http://example.com/example.gif", design.attr("icon"));
- }
-
- public void testSynchronizeThemeIcon() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setIcon(new ThemeResource("example.gif"));
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("theme://example.gif", design.attr("icon"));
- }
-
- public void testSynchronizeFileResource() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setIcon(new FileResource(new File("img/example.gif")));
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("img/example.gif", design.attr("icon"));
- }
-
- public void testSynchronizeImmediate() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- // no immediate attribute should be written before setting immediate to
- // some value
- component.writeDesign(design, ctx);
- assertFalse(design.hasAttr("immediate"));
- component.setImmediate(true);
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("true", design.attr("immediate"));
- }
-
- public void testSynchronizeImmediateByDefault() {
- Element design = createDesign();
- TabSheet byDefaultImmediate = new TabSheet();
- // no immediate attribute should be written before setting immediate to
- // false
- byDefaultImmediate.writeDesign(design, ctx);
- assertFalse(design.hasAttr("immediate"));
- byDefaultImmediate.setImmediate(false);
- byDefaultImmediate.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("false", design.attr("immediate"));
- }
-
- public void testSynchronizeDescription() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setDescription("test-description");
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("test-description", design.attr("description"));
- }
-
- public void testSynchronizeComponentError() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setComponentError(new UserError("<div>test-error</div>",
- ContentMode.HTML, ErrorLevel.ERROR));
- component.writeDesign(design, ctx);
- // we only changed one of the attributes, others are at default values
- assertEquals(1, design.attributes().size());
- assertEquals("<div>test-error</div>", design.attr("error"));
- }
-
- public void testSynchronizeSizeFull() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setSizeFull();
- component.writeDesign(design, ctx);
- // there should be only size full
- assertEquals(1, design.attributes().size());
- assertEquals("true", design.attr("size-full"));
- }
-
- public void testSynchronizeSizeAuto() {
- Element design = createDesign();
- AbstractComponent component = getPanel();
- component.setSizeUndefined();
- component.writeDesign(design, ctx);
- // there should be only size auto
- assertEquals(1, design.attributes().size());
- assertEquals("true", design.attr("size-auto"));
- }
-
- public void testSynchronizeHeightFull() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setHeight("100%");
- component.setWidth("20px");
- component.writeDesign(design, ctx);
- assertEquals("true", design.attr("height-full"));
- }
-
- public void testSynchronizeHeightAuto() {
- Element design = createDesign();
- // we need to have default height of 100% -> use split panel
- AbstractComponent component = getPanel();
- component.setHeight(null);
- component.setWidth("20px");
- component.writeDesign(design, ctx);
- assertEquals("true", design.attr("height-auto"));
- }
-
- public void testSynchronizeWidthFull() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setHeight("20px");
- component.setWidth("100%");
- component.writeDesign(design, ctx);
- assertEquals("true", design.attr("width-full"));
- }
-
- public void testSynchronizeWidthAuto() {
- Element design = createDesign();
- // need to get label, otherwise the default would be auto
- AbstractComponent component = getPanel();
- component.setHeight("20px");
- component.setWidth(null);
- component.writeDesign(design, ctx);
- assertEquals("true", design.attr("width-auto"));
- }
-
- public void testSynchronizeWidth() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setHeight("20px");
- component.setWidth("70%");
- component.writeDesign(design, ctx);
- assertEquals("70%", design.attr("width"));
- }
-
- public void testSynchronizeHeight() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- component.setHeight("20px");
- component.setWidth("70%");
- component.writeDesign(design, ctx);
- assertEquals("20px", design.attr("height"));
- }
-
- public void testSynchronizeResponsive() {
- Element design = createDesign();
- AbstractComponent component = getComponent();
- Responsive.makeResponsive(component);
- component.writeDesign(design, ctx);
- assertTrue("Design attributes should have key 'responsive'", design
- .attributes().hasKey("responsive"));
- assertFalse("Responsive attribute should not be 'false'",
- design.attr("responsive").equalsIgnoreCase("false"));
- }
-
- private AbstractComponent getComponent() {
- Button button = new Button();
- button.setHtmlContentAllowed(true);
- return button;
- }
-
- private AbstractComponent getPanel() {
- return new HorizontalSplitPanel();
- }
-
- private Element createDesign() {
- Attributes attr = new Attributes();
- attr.put("should_be_removed", "foo");
- Element node = new Element(Tag.valueOf("v-button"), "", attr);
- Element child = new Element(Tag.valueOf("to-be-removed"), "foo", attr);
- node.appendChild(child);
- return node;
- }
-}
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractselect/OptionGroupDeclarativeTests.java b/server/tests/src/com/vaadin/tests/server/component/abstractselect/OptionGroupDeclarativeTests.java
new file mode 100644
index 0000000000..4d75e0b59f
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractselect/OptionGroupDeclarativeTests.java
@@ -0,0 +1,160 @@
+/*
+ * 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.server.component.abstractselect;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.ThemeResource;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.OptionGroup;
+
+public class OptionGroupDeclarativeTests extends
+ DeclarativeTestBase<OptionGroup> {
+
+ private OptionGroup og;
+
+ @Before
+ public void init() {
+ og = new OptionGroup();
+ }
+
+ @Test
+ public void testBasicSyntax() {
+
+ String expected = "<v-option-group />";
+ testReadWrite(expected);
+
+ }
+
+ @Test
+ public void testOptionSyntax() {
+
+ og.addItems("foo", "bar", "baz", "bang");
+
+ //@formatter:off
+ String expected =
+ "<v-option-group>"
+ + "<option>foo</option>"
+ + "<option>bar</option>"
+ + "<option>baz</option>"
+ + "<option>bang</option>"
+ + "</v-option-group>";
+ //@formatter:on
+
+ testReadWrite(expected);
+
+ }
+
+ @Test
+ public void testDisabledOptionSyntax() {
+
+ og.addItems("foo", "bar", "baz", "bang");
+ og.setItemEnabled("baz", false);
+
+ //@formatter:off
+ String expected =
+ "<v-option-group>"
+ + "<option>foo</option>"
+ + "<option>bar</option>"
+ + "<option disabled>baz</option>"
+ + "<option>bang</option>"
+ + "</v-option-group>";
+ //@formatter:on
+
+ testReadWrite(expected);
+
+ }
+
+ @Test
+ public void testIconSyntax() {
+
+ og.addItems("foo", "bar", "baz", "bang");
+ og.setItemIcon("bar", new ThemeResource("foobar.png"));
+
+ //@formatter:off
+ String expected =
+ "<v-option-group>"
+ + "<option>foo</option>"
+ + "<option icon='theme://foobar.png'>bar</option>"
+ + "<option>baz</option>"
+ + "<option>bang</option>"
+ + "</v-option-group>";
+ //@formatter:on
+
+ testReadWrite(expected);
+
+ }
+
+ @Test
+ public void testHTMLCaption() {
+
+ og.addItems("foo", "bar", "baz", "bang");
+
+ og.setHtmlContentAllowed(true);
+
+ og.setItemCaption("foo", "<b>True</b>");
+ og.setItemCaption("bar", "<font color='red'>False</font>");
+
+ //@formatter:off
+ String expected =
+ "<v-option-group html-content-allowed='true'>"
+ + "<option item-id=\"foo\"><b>True</b></option>"
+ + "<option item-id=\"bar\"><font color='red'>False</font></option>"
+ + "<option>baz</option>"
+ + "<option>bang</option>"
+ + "</v-option-group>";
+ //@formatter:on
+
+ testReadWrite(expected);
+ }
+
+ @Test
+ public void testPlaintextCaption() {
+
+ og.addItems("foo", "bar", "baz", "bang");
+
+ og.setItemCaption("foo", "<b>True</b>");
+ og.setItemCaption("bar", "<font color='red'>False</font>");
+
+ //@formatter:off
+ String expected =
+ "<v-option-group>"
+ + "<option item-id=\"foo\"><b>True</b></option>"
+ + "<option item-id=\"bar\"><font color='red'>False</font></option>"
+ + "<option>baz</option>"
+ + "<option>bang</option>"
+ + "</v-option-group>";
+ //@formatter:on
+
+ testReadWrite(expected);
+ }
+
+ private void testReadWrite(String design) {
+ testWrite(design, og, true);
+ testRead(design, og);
+ }
+
+ @Override
+ public OptionGroup testRead(String design, OptionGroup expected) {
+
+ OptionGroup read = super.testRead(design, expected);
+ testWrite(design, read, true);
+
+ return read;
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
index fda662e4d9..dbc8cfff3c 100644
--- a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
@@ -302,4 +302,13 @@ public class GridColumns {
}
return null;
}
+
+ @Test
+ public void testAddAndRemoveSortableColumn() {
+ boolean sortable = grid.getColumn("column1").isSortable();
+ grid.removeColumn("column1");
+ grid.addColumn("column1");
+ assertEquals("Column sortability changed when re-adding", sortable,
+ grid.getColumn("column1").isSortable());
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java
new file mode 100644
index 0000000000..1c22a69571
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.server.component.grid.declarative;
+
+import org.junit.Test;
+
+import com.vaadin.ui.Grid;
+
+public class GridColumnDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testSimpleGridColumns() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true width='100' property-id='Column1'>"
+ + " <col sortable=false max-width='200' expand='2' property-id='Column2'>"
+ + " <col sortable=true editable=false min-width='15' expand='1' property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead />" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class).setWidth(100);
+ grid.addColumn("Column2", String.class).setMaximumWidth(200)
+ .setExpandRatio(2).setSortable(false);
+ grid.addColumn("Column3", String.class).setMinimumWidth(15)
+ .setExpandRatio(1).setEditable(false);
+
+ // Remove the default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ // Use the read grid component to do another pass on write.
+ testRead(design, grid, true);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testReadColumnsWithoutPropertyId() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true width='100' property-id='Column1'>"
+ + " <col sortable=true max-width='200' expand='2'>" // property-id="property-1"
+ + " <col sortable=true min-width='15' expand='1' property-id='Column3'>"
+ + "</colgroup>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class).setWidth(100);
+ grid.addColumn("property-1", String.class).setMaximumWidth(200)
+ .setExpandRatio(2);
+ grid.addColumn("Column3", String.class).setMinimumWidth(15)
+ .setExpandRatio(1);
+
+ testRead(design, grid);
+ }
+
+ @Test
+ public void testReadEmptyExpand() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true expand />"
+ + "</colgroup>" //
+ + "</table></v-grid>";
+
+ Grid grid = new Grid();
+ grid.addColumn("property-0", String.class).setExpandRatio(1);
+
+ testRead(design, grid);
+ }
+
+ @Test
+ public void testReadColumnWithNoAttributes() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>" //
+ + " <col />" //
+ + "</colgroup>" //
+ + "</table></v-grid>";
+
+ Grid grid = new Grid();
+ grid.addColumn("property-0", String.class);
+
+ testRead(design, grid);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java
new file mode 100644
index 0000000000..e17f3ee0be
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.server.component.grid.declarative;
+
+import static org.junit.Assert.assertSame;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.grid.HeightMode;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.MultiSelectionModel;
+import com.vaadin.ui.Grid.NoSelectionModel;
+import com.vaadin.ui.Grid.SingleSelectionModel;
+
+/**
+ * Tests declarative support for {@link Grid} properties.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridDeclarativeAttributeTest extends DeclarativeTestBase<Grid> {
+
+ @Test
+ public void testBasicAttributes() {
+
+ String design = "<v-grid editable='true' rows=20 frozen-columns=-1 "
+ + "editor-save-caption='Tallenna' editor-cancel-caption='Peruuta'>";
+
+ Grid grid = new Grid();
+ grid.setEditorEnabled(true);
+ grid.setHeightMode(HeightMode.ROW);
+ grid.setHeightByRows(20);
+ grid.setFrozenColumnCount(-1);
+ grid.setEditorSaveCaption("Tallenna");
+ grid.setEditorCancelCaption("Peruuta");
+
+ testRead(design, grid);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testSelectionMode() {
+ String design = "<v-grid selection-mode='none'>";
+ assertSame(NoSelectionModel.class, read(design).getSelectionModel()
+ .getClass());
+
+ design = "<v-grid selection-mode='single'>";
+ assertSame(SingleSelectionModel.class, read(design).getSelectionModel()
+ .getClass());
+
+ design = "<v-grid selection-mode='multi'>";
+ assertSame(MultiSelectionModel.class, read(design).getSelectionModel()
+ .getClass());
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java
new file mode 100644
index 0000000000..2a4b3f01fc
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java
@@ -0,0 +1,153 @@
+/*
+ * 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.server.component.grid.declarative;
+
+import java.util.List;
+
+import org.junit.Assert;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.FooterCell;
+import com.vaadin.ui.Grid.FooterRow;
+import com.vaadin.ui.Grid.HeaderCell;
+import com.vaadin.ui.Grid.HeaderRow;
+
+public class GridDeclarativeTestBase extends DeclarativeTestBase<Grid> {
+
+ @Override
+ public Grid testRead(String design, Grid expected) {
+ return testRead(design, expected, false);
+ }
+
+ public Grid testRead(String design, Grid expected, boolean retestWrite) {
+ return testRead(design, expected, retestWrite, false);
+ }
+
+ public Grid testRead(String design, Grid expected, boolean retestWrite,
+ boolean writeData) {
+ Grid actual = super.testRead(design, expected);
+
+ compareGridColumns(expected, actual);
+ compareHeaders(expected, actual);
+ compareFooters(expected, actual);
+
+ if (retestWrite) {
+ testWrite(design, actual, writeData);
+ }
+
+ return actual;
+ }
+
+ private void compareHeaders(Grid expected, Grid actual) {
+ Assert.assertEquals("Different header row count",
+ expected.getHeaderRowCount(), actual.getHeaderRowCount());
+ for (int i = 0; i < expected.getHeaderRowCount(); ++i) {
+ HeaderRow expectedRow = expected.getHeaderRow(i);
+ HeaderRow actualRow = actual.getHeaderRow(i);
+
+ if (expectedRow.equals(expected.getDefaultHeaderRow())) {
+ Assert.assertEquals("Different index for default header row",
+ actual.getDefaultHeaderRow(), actualRow);
+ }
+
+ for (Column c : expected.getColumns()) {
+ String baseError = "Difference when comparing cell for "
+ + c.toString() + " on header row " + i + ": ";
+ Object propertyId = c.getPropertyId();
+ HeaderCell expectedCell = expectedRow.getCell(propertyId);
+ HeaderCell actualCell = actualRow.getCell(propertyId);
+
+ switch (expectedCell.getCellType()) {
+ case TEXT:
+ Assert.assertEquals(baseError + "Text content",
+ expectedCell.getText(), actualCell.getText());
+ break;
+ case HTML:
+ Assert.assertEquals(baseError + "HTML content",
+ expectedCell.getHtml(), actualCell.getHtml());
+ break;
+ case WIDGET:
+ assertEquals(baseError + "Component content",
+ expectedCell.getComponent(),
+ actualCell.getComponent());
+ break;
+ }
+ }
+ }
+ }
+
+ private void compareFooters(Grid expected, Grid actual) {
+ Assert.assertEquals("Different footer row count",
+ expected.getFooterRowCount(), actual.getFooterRowCount());
+ for (int i = 0; i < expected.getFooterRowCount(); ++i) {
+ FooterRow expectedRow = expected.getFooterRow(i);
+ FooterRow actualRow = actual.getFooterRow(i);
+
+ for (Column c : expected.getColumns()) {
+ String baseError = "Difference when comparing cell for "
+ + c.toString() + " on footer row " + i + ": ";
+ Object propertyId = c.getPropertyId();
+ FooterCell expectedCell = expectedRow.getCell(propertyId);
+ FooterCell actualCell = actualRow.getCell(propertyId);
+
+ switch (expectedCell.getCellType()) {
+ case TEXT:
+ Assert.assertEquals(baseError + "Text content",
+ expectedCell.getText(), actualCell.getText());
+ break;
+ case HTML:
+ Assert.assertEquals(baseError + "HTML content",
+ expectedCell.getHtml(), actualCell.getHtml());
+ break;
+ case WIDGET:
+ assertEquals(baseError + "Component content",
+ expectedCell.getComponent(),
+ actualCell.getComponent());
+ break;
+ }
+ }
+ }
+ }
+
+ private void compareGridColumns(Grid expected, Grid actual) {
+ List<Column> columns = expected.getColumns();
+ List<Column> actualColumns = actual.getColumns();
+ Assert.assertEquals("Different amount of columns", columns.size(),
+ actualColumns.size());
+ for (int i = 0; i < columns.size(); ++i) {
+ Column col1 = columns.get(i);
+ Column col2 = actualColumns.get(i);
+ String baseError = "Error when comparing columns for property "
+ + col1.getPropertyId() + ": ";
+ assertEquals(baseError + "Property id", col1.getPropertyId(),
+ col2.getPropertyId());
+ assertEquals(baseError + "Width", col1.getWidth(), col2.getWidth());
+ assertEquals(baseError + "Maximum width", col1.getMaximumWidth(),
+ col2.getMaximumWidth());
+ assertEquals(baseError + "Minimum width", col1.getMinimumWidth(),
+ col2.getMinimumWidth());
+ assertEquals(baseError + "Expand ratio", col1.getExpandRatio(),
+ col2.getExpandRatio());
+ assertEquals(baseError + "Sortable", col1.isSortable(),
+ col2.isSortable());
+ assertEquals(baseError + "Editable", col1.isEditable(),
+ col2.isEditable());
+
+ }
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java
new file mode 100644
index 0000000000..b4e82950cb
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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.server.component.grid.declarative;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.FooterRow;
+import com.vaadin.ui.Grid.HeaderRow;
+import com.vaadin.ui.Label;
+
+public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testSingleDefaultHeader() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + " <col sortable=true property-id='Column2'>"
+ + " <col sortable=true property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead>" //
+ + " <tr default='true'><th plain-text=''>Column1<th plain-text=''>Column2<th plain-text=''>Column3</tr>" //
+ + "</thead>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testSingleDefaultHTMLHeader() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + " <col sortable=true property-id='Column2'>"
+ + " <col sortable=true property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead>" //
+ + " <tr default='true'><th>Column1<th>Column2<th>Column3</tr>" //
+ + "</thead>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ HeaderRow row = grid.getDefaultHeaderRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testNoHeaderRows() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + "</colgroup>" //
+ + "<thead />" //
+ + "</table></v-grid>";
+
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testMultipleHeadersWithColSpans() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + " <col sortable=true property-id='Column2'>"
+ + " <col sortable=true property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead>" //
+ + " <tr><th colspan=3>Baz</tr>"
+ + " <tr default='true'><th>Column1<th>Column2<th>Column3</tr>" //
+ + " <tr><th>Foo<th colspan=2>Bar</tr>" //
+ + "</thead>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ HeaderRow row = grid.getDefaultHeaderRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ grid.prependHeaderRow().join("Column1", "Column2", "Column3")
+ .setHtml("Baz");
+ row = grid.appendHeaderRow();
+ row.getCell("Column1").setHtml("Foo");
+ row.join("Column2", "Column3").setHtml("Bar");
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testSingleDefaultFooter() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + " <col sortable=true property-id='Column2'>"
+ + " <col sortable=true property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tfoot>" //
+ + " <tr><td plain-text=''>Column1<td plain-text=''>Column2<td plain-text=''>Column3</tr>" //
+ + "</tfoot>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ FooterRow row = grid.appendFooterRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setText(c.getHeaderCaption());
+ }
+
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testSingleDefaultHTMLFooter() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + " <col sortable=true property-id='Column2'>"
+ + " <col sortable=true property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tfoot>" //
+ + " <tr><td>Column1<td>Column2<td>Column3</tr>" //
+ + "</tfoot>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ FooterRow row = grid.appendFooterRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testMultipleFootersWithColSpans() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + " <col sortable=true property-id='Column2'>"
+ + " <col sortable=true property-id='Column3'>"
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written.
+ + "<tfoot>" //
+ + " <tr><td colspan=3>Baz</tr>"
+ + " <tr><td>Column1<td>Column2<td>Column3</tr>" //
+ + " <tr><td>Foo<td colspan=2>Bar</tr>" //
+ + "</tfoot>" //
+ + "</table></v-grid>";
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.addColumn("Column2", String.class);
+ grid.addColumn("Column3", String.class);
+
+ FooterRow row = grid.appendFooterRow();
+ for (Column c : grid.getColumns()) {
+ row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption());
+ }
+
+ grid.prependFooterRow().join("Column1", "Column2", "Column3")
+ .setHtml("Baz");
+ row = grid.appendFooterRow();
+ row.getCell("Column1").setHtml("Foo");
+ row.join("Column2", "Column3").setHtml("Bar");
+
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid);
+ testRead(design, grid, true);
+ }
+
+ @Test
+ public void testComponentInGridHeader() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + "</colgroup>" //
+ + "<thead>" //
+ + "<tr default=true><th><v-label><b>Foo</b></v-label></tr>"
+ + "</thead>"//
+ + "</table></v-grid>";
+
+ Label component = new Label("<b>Foo</b>");
+ component.setContentMode(ContentMode.HTML);
+
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.getDefaultHeaderRow().getCell("Column1").setComponent(component);
+
+ testRead(design, grid, true);
+ testWrite(design, grid);
+ }
+
+ @Test
+ public void testComponentInGridFooter() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Column1'>"
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tfoot>" //
+ + "<tr><td><v-label><b>Foo</b></v-label></tr>"//
+ + "</tfoot>" //
+ + "</table></v-grid>";
+
+ Label component = new Label("<b>Foo</b>");
+ component.setContentMode(ContentMode.HTML);
+
+ Grid grid = new Grid();
+ grid.addColumn("Column1", String.class);
+ grid.prependFooterRow().getCell("Column1").setComponent(component);
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testRead(design, grid, true);
+ testWrite(design, grid);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java
new file mode 100644
index 0000000000..fefd49a587
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.server.component.grid.declarative;
+
+import org.junit.Test;
+
+import com.vaadin.ui.Grid;
+
+public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testSimpleInlineData() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Col1' />"
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + "<tr><td>Foo</tr>" //
+ + "<tr><td>Bar</tr>" //
+ + "<tr><td>Baz</tr>" //
+ + "</table></v-grid>";
+
+ Grid grid = new Grid();
+ grid.addColumn("Col1", String.class);
+ grid.addRow("Foo");
+ grid.addRow("Bar");
+ grid.addRow("Baz");
+
+ // Remove default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid, true);
+ testRead(design, grid, true, true);
+ }
+
+ @Test
+ public void testMultipleColumnsInlineData() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Col1' />"
+ + " <col sortable=true property-id='Col2' />"
+ + " <col sortable=true property-id='Col3' />" //
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + "<tr><td>Foo<td>Bar<td>Baz</tr>" //
+ + "<tr><td>My<td>Summer<td>Car</tr>" //
+ + "</table></v-grid>";
+
+ Grid grid = new Grid();
+ grid.addColumn("Col1", String.class);
+ grid.addColumn("Col2", String.class);
+ grid.addColumn("Col3", String.class);
+ grid.addRow("Foo", "Bar", "Baz");
+ grid.addRow("My", "Summer", "Car");
+
+ // Remove default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid, true);
+ testRead(design, grid, true, true);
+ }
+
+ @Test
+ public void testMultipleColumnsInlineDataReordered() {
+ String design = "<v-grid><table>"//
+ + "<colgroup>"
+ + " <col sortable=true property-id='Col2' />"
+ + " <col sortable=true property-id='Col3' />"
+ + " <col sortable=true property-id='Col1' />" //
+ + "</colgroup>" //
+ + "<thead />" // No headers read or written
+ + "<tbody>" //
+ + "<tr><td>Bar<td>Baz<td>Foo</tr>" //
+ + "<tr><td>Summer<td>Car<td>My</tr>" //
+ + "</table></v-grid>";
+
+ Grid grid = new Grid();
+ grid.addColumn("Col1", String.class);
+ grid.addColumn("Col2", String.class);
+ grid.addColumn("Col3", String.class);
+ grid.addRow("Foo", "Bar", "Baz");
+ grid.addRow("My", "Summer", "Car");
+ grid.setColumnOrder("Col2", "Col3", "Col1");
+
+ // Remove default header
+ grid.removeHeaderRow(grid.getDefaultHeaderRow());
+
+ testWrite(design, grid, true);
+ testRead(design, grid, true, true);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java
new file mode 100644
index 0000000000..dc74f46d4d
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.server.component.grid.declarative;
+
+import org.junit.Test;
+
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.declarative.DesignException;
+
+public class GridStructureDeclarativeTest extends GridDeclarativeTestBase {
+
+ @Test
+ public void testReadEmptyGrid() {
+ String design = "<v-grid />";
+ testRead(design, new Grid(), false);
+ }
+
+ @Test
+ public void testEmptyGrid() {
+ String design = "<v-grid></v-grid>";
+ Grid expected = new Grid();
+ testWrite(design, expected);
+ testRead(design, expected, true);
+ }
+
+ @Test(expected = DesignException.class)
+ public void testMalformedGrid() {
+ String design = "<v-grid><v-label /></v-grid>";
+ testRead(design, new Grid());
+ }
+
+ @Test(expected = DesignException.class)
+ public void testGridWithNoColGroup() {
+ String design = "<v-grid><table><thead><tr><th>Foo</tr></thead></table></v-grid>";
+ testRead(design, new Grid());
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java
new file mode 100644
index 0000000000..7c9c126707
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.server.component.gridlayout;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.declarative.DesignContext;
+
+public class GridLayoutDeclarativeTest extends DeclarativeTestBase<GridLayout> {
+
+ @Test
+ public void testSimpleGridLayout() {
+ Button b1 = new Button("Button 0,0");
+ Button b2 = new Button("Button 0,1");
+ Button b3 = new Button("Button 1,0");
+ Button b4 = new Button("Button 1,1");
+ b1.setCaptionAsHtml(true);
+ b2.setCaptionAsHtml(true);
+ b3.setCaptionAsHtml(true);
+ b4.setCaptionAsHtml(true);
+ String design = "<v-grid-layout><row>" //
+ + "<column expand=1>" + writeChild(b1) + "</column>" //
+ + "<column expand=3>" + writeChild(b2) + "</column>" //
+ + "</row><row>" //
+ + "<column>" + writeChild(b3) + "</column>" //
+ + "<column>" + writeChild(b4) + "</column>" //
+ + "</row></v-grid-layout>";
+ GridLayout gl = new GridLayout(2, 2);
+ gl.addComponent(b1);
+ gl.addComponent(b2);
+ gl.addComponent(b3);
+ gl.addComponent(b4);
+ gl.setColumnExpandRatio(0, 1.0f);
+ gl.setColumnExpandRatio(1, 3.0f);
+ testWrite(design, gl);
+ testRead(design, gl);
+ }
+
+ @Test
+ public void testOneBigComponentGridLayout() {
+ Button b1 = new Button("Button 0,0 -> 1,1");
+ b1.setCaptionAsHtml(true);
+ String design = "<v-grid-layout><row>" //
+ + "<column colspan=2 rowspan=2>" + writeChild(b1) + "</column>" //
+ + "</row><row expand=2>" //
+ + "</row></v-grid-layout>";
+ GridLayout gl = new GridLayout(2, 2);
+ gl.addComponent(b1, 0, 0, 1, 1);
+ gl.setRowExpandRatio(1, 2);
+ testWrite(design, gl);
+ testRead(design, gl);
+ }
+
+ @Test
+ public void testMultipleSpannedComponentsGridLayout() {
+ GridLayout gl = new GridLayout(5, 5);
+ Button b1 = new Button("Button 0,0 -> 0,2");
+ b1.setCaptionAsHtml(true);
+ gl.addComponent(b1, 0, 0, 2, 0);
+
+ Button b2 = new Button("Button 0,3 -> 3,3");
+ b2.setCaptionAsHtml(true);
+ gl.addComponent(b2, 3, 0, 3, 3);
+
+ Button b3 = new Button("Button 0,4 -> 1,4");
+ b3.setCaptionAsHtml(true);
+ gl.addComponent(b3, 4, 0, 4, 1);
+
+ Button b4 = new Button("Button 1,0 -> 3,1");
+ b4.setCaptionAsHtml(true);
+ gl.addComponent(b4, 0, 1, 1, 3);
+
+ Button b5 = new Button("Button 2,2");
+ b5.setCaptionAsHtml(true);
+ gl.addComponent(b5, 2, 2);
+
+ Button b6 = new Button("Button 3,4 -> 4,4");
+ b6.setCaptionAsHtml(true);
+ gl.addComponent(b6, 4, 3, 4, 4);
+
+ Button b7 = new Button("Button 4,1 -> 4,2");
+ b7.setCaptionAsHtml(true);
+ gl.addComponent(b7, 2, 4, 3, 4);
+
+ /*
+ * Buttons in the GridLayout
+ */
+
+ // 1 1 1 2 3
+ // 4 4 - 2 3
+ // 4 4 5 2 -
+ // 4 4 - 2 6
+ // - - 7 7 6
+
+ String design = "<v-grid-layout><row>" //
+ + "<column colspan=3>" + writeChild(b1) + "</column>" //
+ + "<column rowspan=4>" + writeChild(b2) + "</column>" //
+ + "<column rowspan=2>" + writeChild(b3) + "</column>" //
+ + "</row><row>" //
+ + "<column rowspan=3 colspan=2>" + writeChild(b4) + "</column>" //
+ + "</row><row>" //
+ + "<column>" + writeChild(b5) + "</column>" //
+ + "</row><row>" //
+ + "<column />" // Empty placeholder
+ + "<column rowspan=2>" + writeChild(b6) + "</column>" //
+ + "</row><row>" //
+ + "<column colspan=2 />" // Empty placeholder
+ + "<column colspan=2>" + writeChild(b7) + "</column>" //
+ + "</row></v-grid-layout>";
+ testWrite(design, gl);
+ testRead(design, gl);
+ }
+
+ @Test
+ public void testManyExtraGridLayoutSlots() {
+ GridLayout gl = new GridLayout(5, 5);
+ Button b1 = new Button("Button 0,4 -> 4,4");
+ b1.setCaptionAsHtml(true);
+ gl.addComponent(b1, 4, 0, 4, 4);
+ gl.setColumnExpandRatio(2, 2.0f);
+
+ String design = "<v-grid-layout><row>" //
+ + "<column colspan=4 rowspan=5 expand='0,0,2,0' />" //
+ + "<column rowspan=5>" + writeChild(b1) + "</column>" //
+ + "</row><row>" //
+ + "</row><row>" //
+ + "</row><row>" //
+ + "</row><row>" //
+ + "</row></v-grid-layout>";
+ testWrite(design, gl);
+ testRead(design, gl);
+ }
+
+ @Test
+ public void testManyEmptyColumnsWithOneExpand() {
+ GridLayout gl = new GridLayout(5, 5);
+ Button b1 = new Button("Button 0,4 -> 4,4");
+ b1.setCaptionAsHtml(true);
+ gl.addComponent(b1, 0, 0, 0, 4);
+ gl.setColumnExpandRatio(4, 2.0f);
+
+ String design = "<v-grid-layout><row>" //
+ + "<column rowspan=5>" + writeChild(b1) + "</column>" //
+ + "<column colspan=4 rowspan=5 expand='0,0,0,2' />" //
+ + "</row><row>" //
+ + "</row><row>" //
+ + "</row><row>" //
+ + "</row><row>" //
+ + "</row></v-grid-layout>";
+ testWrite(design, gl);
+ testRead(design, gl);
+ }
+
+ @Test
+ public void testEmptyGridLayout() {
+ GridLayout gl = new GridLayout();
+ String design = "<v-grid-layout />";
+ testWrite(design, gl);
+ testRead(design, gl);
+ }
+
+ private String writeChild(Component childComponent) {
+ return new DesignContext().createElement(childComponent).toString();
+ }
+
+ @Override
+ public GridLayout testRead(String design, GridLayout expected) {
+ expected.setCursorX(0);
+ expected.setCursorY(expected.getRows());
+
+ GridLayout result = super.testRead(design, expected);
+ for (int row = 0; row < expected.getRows(); ++row) {
+ Assert.assertTrue(Math.abs(expected.getRowExpandRatio(row)
+ - result.getRowExpandRatio(row)) < 0.00001);
+ }
+ for (int col = 0; col < expected.getColumns(); ++col) {
+ Assert.assertTrue(Math.abs(expected.getColumnExpandRatio(col)
+ - result.getColumnExpandRatio(col)) < 0.00001);
+ }
+ return result;
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/tree/TreeDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/tree/TreeDeclarativeTest.java
index b5e86d0835..3fb69a9257 100644
--- a/server/tests/src/com/vaadin/tests/server/component/tree/TreeDeclarativeTest.java
+++ b/server/tests/src/com/vaadin/tests/server/component/tree/TreeDeclarativeTest.java
@@ -17,7 +17,7 @@ package com.vaadin.tests.server.component.tree;
import org.junit.Test;
-import com.vaadin.shared.ui.MultiSelectMode;
+import com.vaadin.server.ExternalResource;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.Tree;
import com.vaadin.ui.Tree.TreeDragMode;
@@ -31,34 +31,51 @@ import com.vaadin.ui.Tree.TreeDragMode;
public class TreeDeclarativeTest extends DeclarativeTestBase<Tree> {
@Test
- public void testReadBasic() {
- testRead(getBasicDesign(), getBasicExpected());
- }
+ public void testDragMode() {
+ String design = "<v-tree drag-mode='node' />";
- @Test
- public void testWriteBasic() {
- testWrite(getBasicDesign(), getBasicExpected());
- }
+ Tree tree = new Tree();
+ tree.setDragMode(TreeDragMode.NODE);
- private String getBasicDesign() {
- return "<v-tree selectable='false' drag-mode='node' multiselect-mode='simple' />";
- }
-
- private Tree getBasicExpected() {
- Tree t = new Tree();
- t.setSelectable(false);
- t.setDragMode(TreeDragMode.NODE);
- t.setMultiselectMode(MultiSelectMode.SIMPLE);
- return t;
+ testRead(design, tree);
+ testWrite(design, tree);
}
@Test
- public void testReadEmpty() {
+ public void testEmpty() {
testRead("<v-tree />", new Tree());
+ testWrite("<v-tree />", new Tree());
}
@Test
- public void testWriteEmpty() {
- testWrite("<v-tree />", new Tree());
+ public void testNodes() {
+ String design = "<v-tree>" //
+ + " <node text='Node'/>" //
+ + " <node text='Parent'>" //
+ + " <node text='Child'>" //
+ + " <node text='Grandchild'/>" //
+ + " </node>" //
+ + " </node>" //
+ + " <node text='With icon' icon='http://example.com/icon.png'/>" //
+ + "</v-tree>";
+
+ Tree tree = new Tree();
+
+ tree.addItem("Node");
+
+ tree.addItem("Parent");
+
+ tree.addItem("Child");
+ tree.setParent("Child", "Parent");
+
+ tree.addItem("Grandchild");
+ tree.setParent("Grandchild", "Child");
+
+ tree.addItem("With icon");
+ tree.setItemIcon("With icon", new ExternalResource(
+ "http://example.com/icon.png"));
+
+ testRead(design, tree);
+ testWrite(design, tree, true);
}
}