diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-04-15 10:24:44 +0300 |
---|---|---|
committer | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-04-15 10:24:44 +0300 |
commit | 2c4e533c9f2aa68211329ea6ce4de0b577407863 (patch) | |
tree | 1d9c1cc8bb72678b0edb991947c6fc94112baf0f /server | |
parent | 93235f05c9dd4739cdccf87a4858a61904dbf4b5 (diff) | |
parent | 7cb23bc63f794a7549dd79c37da2f8bb8e88e20d (diff) | |
download | vaadin-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')
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); } } |