diff options
author | Teamcity <build@vaadin.com> | 2015-04-28 13:13:32 +0300 |
---|---|---|
committer | Teamcity <build@vaadin.com> | 2015-04-28 13:13:32 +0300 |
commit | 4b8bf66b923fd31556d383ca474cd44c214f0ffb (patch) | |
tree | d9e69ad44e9a5ced188eeb9427688f745e62a8b9 | |
parent | c2e39d0dc68d091c584ec1cbc145fb80230e041b (diff) | |
parent | 9f6bec29fae7cbdde914db342ca3f825bbd1b80f (diff) | |
download | vaadin-framework-4b8bf66b923fd31556d383ca474cd44c214f0ffb.tar.gz vaadin-framework-4b8bf66b923fd31556d383ca474cd44c214f0ffb.zip |
Merge branch 'refs/heads/master' into 'snapshot/7.5'
7 files changed, 323 insertions, 52 deletions
diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java index 0e3cfef4ce..237cdbddb6 100644 --- a/server/src/com/vaadin/ui/AbstractSelect.java +++ b/server/src/com/vaadin/ui/AbstractSelect.java @@ -2231,7 +2231,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements * if the tag name of the {@code child} element is not * {@code option}. */ - protected String readItem(Element child, Set<String> selected, + protected Object readItem(Element child, Set<String> selected, DesignContext context) { if (!"option".equals(child.tagName())) { throw new DesignException("Unrecognized child element in " diff --git a/server/src/com/vaadin/ui/OptionGroup.java b/server/src/com/vaadin/ui/OptionGroup.java index ff2e384285..10c263aca0 100644 --- a/server/src/com/vaadin/ui/OptionGroup.java +++ b/server/src/com/vaadin/ui/OptionGroup.java @@ -257,9 +257,9 @@ public class OptionGroup extends AbstractSelect implements } @Override - protected String readItem(Element child, Set<String> selected, + protected Object readItem(Element child, Set<String> selected, DesignContext context) { - String itemId = super.readItem(child, selected, context); + Object itemId = super.readItem(child, selected, context); if (child.hasAttr("disabled")) { setItemEnabled(itemId, false); diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index eb3d35be3e..cb61fa31ec 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -6042,7 +6042,7 @@ public class Table extends AbstractSelect implements Action.Container, readColumns(design); readHeader(design); - readBody(design); + readBody(design, context); readFooter(design); } @@ -6150,31 +6150,44 @@ public class Table extends AbstractSelect implements Action.Container, } } - private void readBody(Element design) { + protected void readBody(Element design, DesignContext context) { Element tbody = design.select("> table > tbody").first(); - if (tbody != null) { - for (Element row : tbody.children()) { - Elements cells = row.children(); - if (visibleColumns.size() != cells.size()) { - throw new DesignException( - "Wrong number of columns in a row of a Table. Expected " - + visibleColumns.size() + ", was " - + cells.size() + "."); - } - Object[] data = new String[cells.size()]; - for (int c = 0; c < cells.size(); ++c) { - data[c] = cells.get(c).html(); - } - Object itemId = addItem(data, null); - if (itemId == null) { - throw new DesignException( - "A row of a Table could not be read"); - } - } + if (tbody == null) { + return; + } + + Set<String> selected = new HashSet<String>(); + for (Element tr : tbody.children()) { + readItem(tr, selected, context); } } @Override + protected Object readItem(Element tr, Set<String> selected, + DesignContext context) { + Elements cells = tr.children(); + if (visibleColumns.size() != cells.size()) { + throw new DesignException( + "Wrong number of columns in a Table row. Expected " + + visibleColumns.size() + ", was " + cells.size() + + "."); + } + Object[] data = new String[cells.size()]; + for (int c = 0; c < cells.size(); ++c) { + data[c] = cells.get(c).html(); + } + + Object itemId = addItem(data, + tr.hasAttr("item-id") ? tr.attr("item-id") : null); + + if (itemId == null) { + throw new DesignException("Failed to add a Table row: " + data); + } + + return itemId; + } + + @Override public void writeDesign(Element design, DesignContext context) { Table def = context.getDefaultInstance(this); @@ -6260,6 +6273,9 @@ public class Table extends AbstractSelect implements Action.Container, @Override protected void writeItems(Element design, DesignContext context) { + if (getVisibleColumns().length == 0) { + return; + } Element tbody = design.child(0).appendElement("tbody"); super.writeItems(tbody, context); } @@ -6268,10 +6284,12 @@ public class Table extends AbstractSelect implements Action.Container, protected Element writeItem(Element tbody, Object itemId, DesignContext context) { Element tr = tbody.appendElement("tr"); + tr.attr("item-id", String.valueOf(itemId)); Item item = getItem(itemId); for (Object id : getVisibleColumns()) { Element td = tr.appendElement("td"); - td.html(item.getItemProperty(id).getValue().toString()); + Object value = item.getItemProperty(id).getValue(); + td.html(value != null ? value.toString() : ""); } return tr; } diff --git a/server/src/com/vaadin/ui/TreeTable.java b/server/src/com/vaadin/ui/TreeTable.java index 63b54a6ced..254d8774a9 100644 --- a/server/src/com/vaadin/ui/TreeTable.java +++ b/server/src/com/vaadin/ui/TreeTable.java @@ -23,9 +23,13 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; +import org.jsoup.nodes.Element; + import com.vaadin.data.Collapsible; import com.vaadin.data.Container; import com.vaadin.data.Container.Hierarchical; @@ -41,6 +45,9 @@ import com.vaadin.ui.Tree.CollapseEvent; import com.vaadin.ui.Tree.CollapseListener; import com.vaadin.ui.Tree.ExpandEvent; import com.vaadin.ui.Tree.ExpandListener; +import com.vaadin.ui.declarative.DesignAttributeHandler; +import com.vaadin.ui.declarative.DesignContext; +import com.vaadin.ui.declarative.DesignException; /** * TreeTable extends the {@link Table} component so that it can also visualize a @@ -888,4 +895,81 @@ public class TreeTable extends Table implements Hierarchical { } return itemIds; } + + @Override + protected void readBody(Element design, DesignContext context) { + Element tbody = design.select("> table > tbody").first(); + if (tbody == null) { + return; + } + + Set<String> selected = new HashSet<String>(); + Stack<Object> parents = new Stack<Object>(); + int lastDepth = -1; + + for (Element tr : tbody.children()) { + int depth = DesignAttributeHandler.readAttribute("depth", + tr.attributes(), 0, int.class); + + if (depth < 0 || depth > lastDepth + 1) { + throw new DesignException( + "Malformed TreeTable item hierarchy at " + tr + + ": last depth was " + lastDepth); + } else if (depth <= lastDepth) { + for (int d = depth; d <= lastDepth; d++) { + parents.pop(); + } + } + + Object itemId = readItem(tr, selected, context); + setParent(itemId, !parents.isEmpty() ? parents.peek() : null); + parents.push(itemId); + lastDepth = depth; + } + } + + @Override + protected Object readItem(Element tr, Set<String> selected, + DesignContext context) { + Object itemId = super.readItem(tr, selected, context); + + if (tr.hasAttr("collapsed")) { + boolean collapsed = DesignAttributeHandler.readAttribute( + "collapsed", tr.attributes(), boolean.class); + setCollapsed(itemId, collapsed); + } + + return itemId; + } + + @Override + protected void writeItems(Element design, DesignContext context) { + if (getVisibleColumns().length == 0) { + return; + } + Element tbody = design.child(0).appendElement("tbody"); + writeItems(tbody, rootItemIds(), 0, context); + } + + protected void writeItems(Element tbody, Collection<?> itemIds, int depth, + DesignContext context) { + for (Object itemId : itemIds) { + Element tr = writeItem(tbody, itemId, context); + DesignAttributeHandler.writeAttribute("depth", tr.attributes(), + depth, 0, int.class); + + if (getChildren(itemId) != null) { + writeItems(tbody, getChildren(itemId), depth + 1, context); + } + } + } + + @Override + protected Element writeItem(Element tbody, Object itemId, + DesignContext context) { + Element tr = super.writeItem(tbody, itemId, context); + DesignAttributeHandler.writeAttribute("collapsed", tr.attributes(), + isCollapsed(itemId), true, boolean.class); + return tr; + } } diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java index 796d30049e..c395d8501c 100644 --- a/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java @@ -36,12 +36,14 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase { @Test public void testBasicAttributes() { - String design = "<v-table page-length=30 cache-rate=3 selectable=true editable=true " + String design = "<" + + getTag() + + " page-length=30 cache-rate=3 selectable=true editable=true " + "sortable=false sort-ascending=false sort-container-property-id=foo " + "drag-mode=row multi-select-mode=simple column-header-mode=id row-header-mode=id " + "column-reordering-allowed=true column-collapsing-allowed=true />"; - Table table = new Table(); + Table table = getTable(); table.setPageLength(30); table.setCacheRate(3); table.setSelectable(true); @@ -65,17 +67,18 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase { @Test public void testColumns() { - String design = "<v-table column-collapsing-allowed=true>" // + String design = "<" + + getTag() + + " column-collapsing-allowed=true>" // + " <table>" // + " <colgroup>" + " <col property-id='foo' width=300>" + " <col property-id='bar' center expand=1 collapsible=false>" + " <col property-id='baz' right expand=2 collapsed=true>" + " </colgroup>" // - + " </table>" // - + "</v-table>"; + + " </table>"; - Table table = new Table(); + Table table = getTable(); table.setColumnCollapsingAllowed(true); table.addContainerProperty("foo", String.class, null); @@ -98,7 +101,8 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase { @Test public void testHeadersFooters() { - String design = "<v-table>" // + String design = "<" + getTag() + + ">" // + " <table>" // + " <colgroup><col property-id=foo><col property-id=bar></colgroup>" // + " <thead>" // @@ -107,10 +111,9 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase { + " <tfoot>" // + " <tr><td>foo<td>bar" // + " </tfoot>" // - + " </table>" // - + "</v-table>"; + + " </table>"; - Table table = new Table(); + Table table = getTable(); table.setFooterVisible(true); table.addContainerProperty("foo", String.class, null); @@ -129,27 +132,26 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase { @Test public void testInlineData() { - String design = "<v-table> "// + String design = "<" + + getTag() + + ">" // + " <table>" // + " <colgroup>" + " <col property-id='foo' />" + " <col property-id='bar' />" + " <col property-id='baz' />" // - + " </colgroup>" - + " <thead>" + + " </colgroup>" + " <thead>" + " <tr><th>Description<th>Milestone<th>Status</tr>" - + " </thead>" - + " <tbody>" - + " <tr><td>r1c1</td><td>r1c2</td><td>r1c3</td>" // - + " <tr><td>r2c1</td><td>r2c2</td><td>r2c3</td>" // + + " </thead>" + " <tbody>" + + " <tr item-id=1><td>r1c1</td><td>r1c2</td><td>r1c3</td>" // + + " <tr item-id=2><td>r2c1</td><td>r2c2</td><td>r2c3</td>" // + " </tbody>" // + " <tfoot>" // + " <tr><td>F1<td>F2<td>F3</tr>" // + " </tfoot>" // - + " </table>" // - + "</v-table>"; + + " </table>"; - Table table = new Table(); + Table table = getTable(); table.addContainerProperty("foo", String.class, null); table.addContainerProperty("bar", String.class, null); table.addContainerProperty("baz", String.class, null); @@ -157,8 +159,8 @@ public class TableDeclarativeTest extends TableDeclarativeTestBase { table.setColumnFooter("foo", "F1"); table.setColumnFooter("bar", "F2"); table.setColumnFooter("baz", "F3"); - table.addItem(new Object[] { "r1c1", "r1c2", "r1c3" }, null); - table.addItem(new Object[] { "r2c1", "r2c2", "r2c3" }, null); + table.addItem(new Object[] { "r1c1", "r1c2", "r1c3" }, "1"); + table.addItem(new Object[] { "r2c1", "r2c2", "r2c3" }, "2"); table.setFooterVisible(true); testRead(design, table); diff --git a/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTestBase.java b/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTestBase.java index 65c9475684..d909d98a36 100644 --- a/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTestBase.java +++ b/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTestBase.java @@ -20,7 +20,8 @@ import static org.junit.Assert.assertTrue; import com.vaadin.tests.design.DeclarativeTestBase; import com.vaadin.ui.Table; -public class TableDeclarativeTestBase extends DeclarativeTestBase<Table> { +public abstract class TableDeclarativeTestBase extends + DeclarativeTestBase<Table> { @Override public Table testRead(String design, Table expected) { @@ -30,20 +31,30 @@ public class TableDeclarativeTestBase extends DeclarativeTestBase<Table> { return read; } - private void compareBody(Table read, Table expected) { - assertEquals(expected.getItemIds().size(), read.getItemIds().size()); + protected Table getTable() { + return new Table(); + } + + protected String getTag() { + return "v-table"; + } + + protected void compareBody(Table read, Table expected) { + assertEquals("number of items", expected.getItemIds().size(), read + .getItemIds().size()); for (Object rowId : expected.getItemIds()) { assertTrue(read.containsId(rowId)); for (Object propertyId : read.getVisibleColumns()) { Object expectedItem = expected.getContainerProperty(rowId, propertyId); Object readItem = read.getContainerProperty(rowId, propertyId); - assertEquals(expectedItem, readItem); + assertEquals("property '" + propertyId + "'", expectedItem, + readItem); } } } - private void compareColumns(Table read, Table expected) { + protected void compareColumns(Table read, Table expected) { for (Object pid : expected.getVisibleColumns()) { String col = "column '" + pid + "'"; assertEquals(col + " width", expected.getColumnWidth(pid), diff --git a/server/tests/src/com/vaadin/tests/server/component/treetable/TreeTableDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/treetable/TreeTableDeclarativeTest.java new file mode 100644 index 0000000000..5f487aa021 --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/treetable/TreeTableDeclarativeTest.java @@ -0,0 +1,156 @@ +/* + * 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.treetable; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tests.server.component.table.TableDeclarativeTest; +import com.vaadin.ui.Table; +import com.vaadin.ui.TreeTable; +import com.vaadin.ui.declarative.DesignException; + +/** + * Test declarative support for {@link TreeTable}. + * + * @since + * @author Vaadin Ltd + */ +public class TreeTableDeclarativeTest extends TableDeclarativeTest { + + @Test + public void testAttributes() { + String design = "<v-tree-table animations-enabled=true>"; + TreeTable table = getTable(); + table.setAnimationsEnabled(true); + + testRead(design, table); + testWrite(design, table); + } + + @Test + public void testHierarchy() { + String design = "<v-tree-table>" // + + "<table>" // + + "<colgroup><col property-id=''></colgroup>" // + + "<tbody>" // + + " <tr item-id='1'><td></tr>" // + + " <tr depth=1 item-id='1.1'><td></tr>" // + + " <tr depth=1 item-id='1.2'><td></tr>" // + + " <tr depth=2 item-id='1.2.1'><td></tr>" // + + " <tr depth=3 item-id='1.2.1.1'><td></tr>" // + + " <tr depth=2 item-id='1.2.2'><td></tr>" // + + " <tr item-id='2'><td></tr>" // + + " <tr depth=1 item-id='2.1'><td></tr>" // + + "</tbody>" // + + "</table>" // + + "</v-tree-table>"; + + TreeTable table = getTable(); + table.addContainerProperty("", String.class, ""); + + table.addItem("1"); + table.addItem("1.1"); + table.setParent("1.1", "1"); + table.addItem("1.2"); + table.setParent("1.2", "1"); + table.addItem("1.2.1"); + table.setParent("1.2.1", "1.2"); + table.addItem("1.2.1.1"); + table.setParent("1.2.1.1", "1.2.1"); + table.addItem("1.2.2"); + table.setParent("1.2.2", "1.2"); + table.addItem("2"); + table.addItem("2.1"); + table.setParent("2.1", "2"); + + testRead(design, table); + testWrite(design, table, true); + } + + @Test + public void testCollapsed() { + String design = "<v-tree-table>" // + + " <table>" // + + " <colgroup><col property-id=''></colgroup>" // + + " <tbody>" // + + " <tr item-id='1' collapsed=false><td></tr>" // + + " <tr depth=1 item-id='1.1'><td></tr>" // + + " <tr depth=2 item-id='1.1.1'><td></tr>" // + + " </tbody>" // + + " </table>" // + + "</v-tree-table>"; + + TreeTable table = getTable(); + table.addContainerProperty("", String.class, ""); + + table.addItem("1"); + table.setCollapsed("1", false); + table.addItem("1.1"); + table.setParent("1.1", "1"); + table.addItem("1.1.1"); + table.setParent("1.1.1", "1.1"); + + testRead(design, table); + testWrite(design, table, true); + } + + @Test + public void testMalformedHierarchy() { + assertMalformed("<tr depth=-4><td>"); + assertMalformed("<tr depth=1><td>"); + assertMalformed("<tr><td><tr depth=3><td>"); + } + + protected void assertMalformed(String hierarchy) { + String design = "<v-tree-table>" // + + " <table>" // + + " <colgroup><col property-id=''></colgroup>" // + + " <tbody>" + hierarchy + "</tbody>" // + + " </table>" // + + "</v-tree-table>"; + + try { + read(design); + Assert.fail("Malformed hierarchy should fail: " + hierarchy); + } catch (DesignException expected) { + } + } + + @Override + protected void compareBody(Table read, Table expected) { + super.compareBody(read, expected); + + for (Object itemId : read.getItemIds()) { + Assert.assertEquals("parent of item " + itemId, + ((TreeTable) expected).getParent(itemId), + ((TreeTable) read).getParent(itemId)); + Assert.assertEquals("collapsed status of item " + itemId, + ((TreeTable) expected).isCollapsed(itemId), + ((TreeTable) read).isCollapsed(itemId)); + } + } + + @Override + protected TreeTable getTable() { + return new TreeTable(); + } + + @Override + protected String getTag() { + return "v-tree-table"; + } +} |