aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2015-04-15 13:36:18 +0300
committerVaadin Code Review <review@vaadin.com>2015-04-17 14:31:32 +0000
commited4bec15a1fbc53a1818192644cdb86e0e2e30ee (patch)
treeccb65d62e45ef155bfdfcc25908c76ff546bd99c
parent2d3ed921065acd7761df07b9b403d111bedf33d9 (diff)
downloadvaadin-framework-ed4bec15a1fbc53a1818192644cdb86e0e2e30ee.tar.gz
vaadin-framework-ed4bec15a1fbc53a1818192644cdb86e0e2e30ee.zip
Declarative read support for Table (#16367)
Change-Id: I2327af18b2e1e4d31a057b110eee9495f16d9633
-rw-r--r--server/src/com/vaadin/ui/AbstractSelect.java4
-rw-r--r--server/src/com/vaadin/ui/Table.java163
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java165
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTestBase.java52
4 files changed, 383 insertions, 1 deletions
diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java
index 6ac0dad5e4..0e3cfef4ce 100644
--- a/server/src/com/vaadin/ui/AbstractSelect.java
+++ b/server/src/com/vaadin/ui/AbstractSelect.java
@@ -2192,6 +2192,10 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
// handle default attributes
super.readDesign(design, context);
// handle children specifying selectable items (<option>)
+ readItems(design, context);
+ }
+
+ protected void readItems(Element design, DesignContext context) {
Set<String> selected = new HashSet<String>();
for (Element child : design.children()) {
readItem(child, selected, context);
diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java
index 347bb8fbff..202e58f0c9 100644
--- a/server/src/com/vaadin/ui/Table.java
+++ b/server/src/com/vaadin/ui/Table.java
@@ -34,6 +34,9 @@ import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
@@ -63,6 +66,9 @@ import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.MultiSelectMode;
import com.vaadin.shared.ui.table.TableConstants;
import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
/**
* <p>
@@ -3863,7 +3869,7 @@ public class Table extends AbstractSelect implements Action.Container,
/**
* Checks whether row headers are visible.
- *
+ *
* @return {@code false} if row headers are hidden, {@code true} otherwise
* @since 7.3.9
*/
@@ -6025,6 +6031,161 @@ public class Table extends AbstractSelect implements Action.Container,
return iterator();
}
+ @Override
+ public void readDesign(Element design, DesignContext context) {
+ super.readDesign(design, context);
+
+ if (design.hasAttr("sortable")) {
+ setSortEnabled(DesignAttributeHandler.readAttribute("sortable",
+ design.attributes(), boolean.class));
+ }
+
+ readColumns(design);
+ readHeader(design);
+ readBody(design);
+ readFooter(design);
+ }
+
+ private void readColumns(Element design) {
+ Element colgroup = design.select("> table > colgroup").first();
+
+ if (colgroup != null) {
+ int i = 0;
+ List<Object> pIds = new ArrayList<Object>();
+ for (Element col : colgroup.children()) {
+ if (!col.tagName().equals("col")) {
+ throw new DesignException("invalid column");
+ }
+
+ String id = DesignAttributeHandler.readAttribute("property-id",
+ col.attributes(), "property-" + i++, String.class);
+ pIds.add(id);
+
+ addContainerProperty(id, String.class, null);
+
+ if (col.hasAttr("width")) {
+ setColumnWidth(
+ id,
+ DesignAttributeHandler.readAttribute("width",
+ col.attributes(), Integer.class));
+ }
+ if (col.hasAttr("center")) {
+ setColumnAlignment(id, Align.CENTER);
+ } else if (col.hasAttr("right")) {
+ setColumnAlignment(id, Align.RIGHT);
+ }
+ if (col.hasAttr("expand")) {
+ if (col.attr("expand").isEmpty()) {
+ setColumnExpandRatio(id, 1);
+ } else {
+ setColumnExpandRatio(id,
+ DesignAttributeHandler.readAttribute("expand",
+ col.attributes(), float.class));
+ }
+ }
+ if (col.hasAttr("collapsible")) {
+ setColumnCollapsible(id,
+ DesignAttributeHandler.readAttribute("collapsible",
+ col.attributes(), boolean.class));
+ }
+ if (col.hasAttr("collapsed")) {
+ setColumnCollapsed(id,
+ DesignAttributeHandler.readAttribute("collapsed",
+ col.attributes(), boolean.class));
+ }
+ }
+ setVisibleColumns(pIds.toArray());
+ }
+ }
+
+ private void readFooter(Element design) {
+ readHeaderOrFooter(design, false);
+ }
+
+ private void readHeader(Element design) {
+ readHeaderOrFooter(design, true);
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ // Do nothing - header/footer and inline data must be handled after
+ // colgroup.
+ }
+
+ private void readHeaderOrFooter(Element design, boolean header) {
+ String selector = header ? "> table > thead" : "> table > tfoot";
+ Element elem = design.select(selector).first();
+ if (elem != null) {
+ if (!header) {
+ setFooterVisible(true);
+ }
+ if (elem.children().size() != 1) {
+ throw new DesignException(
+ "Table header and footer should contain exactly one <tr> element");
+ }
+ Element tr = elem.child(0);
+ Elements elems = tr.children();
+ Collection<?> propertyIds = visibleColumns;
+ if (elems.size() != propertyIds.size()) {
+ throw new DesignException(
+ "Table header and footer should contain as many items as there"
+ + " are columns in the Table.");
+ }
+ Iterator<?> propertyIt = propertyIds.iterator();
+ for (Element e : elems) {
+ String columnValue = e.html();
+ Object propertyId = propertyIt.next();
+ if (header) {
+ setColumnHeader(propertyId, columnValue);
+ if (e.hasAttr("icon")) {
+ setColumnIcon(
+ propertyId,
+ DesignAttributeHandler.readAttribute("icon",
+ e.attributes(), Resource.class));
+ }
+ } else {
+ setColumnFooter(propertyId, columnValue);
+ }
+ }
+ }
+ }
+
+ private void readBody(Element design) {
+ 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");
+ }
+ }
+ }
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("sortable");
+ result.add("sort-enabled");
+ result.add("sort-disabled");
+ result.add("footer-visible");
+ result.add("current-page-first-item-id");
+ result.add("current-page-first-item-index");
+ return result;
+ }
+
private final Logger getLogger() {
if (logger == null) {
logger = Logger.getLogger(Table.class.getName());
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
new file mode 100644
index 0000000000..27888dee14
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.table;
+
+import java.io.UnsupportedEncodingException;
+
+import org.junit.Test;
+
+import com.vaadin.server.ExternalResource;
+import com.vaadin.shared.ui.MultiSelectMode;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.Align;
+import com.vaadin.ui.Table.ColumnHeaderMode;
+import com.vaadin.ui.Table.RowHeaderMode;
+import com.vaadin.ui.Table.TableDragMode;
+
+/**
+ * Test declarative support for {@link Table}.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TableDeclarativeTest extends TableDeclarativeTestBase {
+
+ @Test
+ public void testBasicAttributes() {
+
+ String design = "<v-table page-length=30 cache-rate=3 selectable editable sortable=false "
+ + "drag-mode=row multi-select-mode=simple column-header-mode=id "
+ + "column-reordering-allowed column-collapsing-allowed sort-ascending=false "
+ + "row-header-mode=id sort-container-property-id=foo />";
+
+ Table table = new Table();
+ table.setPageLength(30);
+ table.setCacheRate(3);
+ table.setSelectable(true);
+ table.setEditable(true);
+ table.setSortEnabled(false);
+ table.setDragMode(TableDragMode.ROW);
+ table.setMultiSelectMode(MultiSelectMode.SIMPLE);
+ table.setColumnHeaderMode(ColumnHeaderMode.ID);
+ table.setRowHeaderMode(RowHeaderMode.ID);
+ table.setColumnReorderingAllowed(true);
+ table.setColumnCollapsingAllowed(true);
+ table.setSortAscending(false);
+ table.setSortContainerPropertyId("foo");
+
+ testRead(design, table);
+ // testWrite(design, table);
+ }
+
+ @Test
+ public void testColumns() {
+ String design = "<v-table column-collapsing-allowed=true>" //
+ + " <table>" //
+ + " <colgroup>"
+ + " <col property-id='foo'>"
+ + " <col property-id='bar' center expand=1 collapsible=false>"
+ + " <col property-id='baz' right expand=2 collapsed=true>"
+ + " </colgroup>" //
+ + " </table>" //
+ + "</v-table>";
+
+ Table table = new Table();
+ table.setColumnCollapsingAllowed(true);
+
+ table.addContainerProperty("foo", String.class, null);
+ table.setColumnAlignment("foo", Align.LEFT);
+ table.setColumnExpandRatio("foo", 0);
+
+ table.addContainerProperty("bar", String.class, null);
+ table.setColumnAlignment("bar", Align.CENTER);
+ table.setColumnExpandRatio("bar", 1);
+ table.setColumnCollapsible("bar", false);
+
+ table.addContainerProperty("baz", String.class, null);
+ table.setColumnAlignment("baz", Align.RIGHT);
+ table.setColumnExpandRatio("baz", 2);
+ table.setColumnCollapsed("baz", true);
+
+ testRead(design, table);
+ // testWrite(design, table);
+ }
+
+ @Test
+ public void testHeadersFooters() {
+ String design = "<v-table>" //
+ + " <table>" //
+ + " <colgroup><col property-id=foo><col property-id=bar></colgroup>" //
+ + " <thead>" //
+ + " <tr><th icon='http://example.com/icon.png'>FOO<th>BAR" //
+ + " </thead>" //
+ + " <tfoot>" //
+ + " <tr><td>foo<td>bar" //
+ + " </tfoot>" //
+ + " </table>" //
+ + "</v-table>";
+
+ Table table = new Table();
+ table.setFooterVisible(true);
+
+ table.addContainerProperty("foo", String.class, null);
+ table.setColumnHeader("foo", "FOO");
+ table.setColumnIcon("foo", new ExternalResource(
+ "http://example.com/icon.png"));
+ table.setColumnFooter("foo", "foo");
+
+ table.addContainerProperty("bar", String.class, null);
+ table.setColumnHeader("bar", "BAR");
+ table.setColumnFooter("bar", "bar");
+
+ testRead(design, table);
+ // testWrite(design, table);
+ }
+
+ @Test
+ public void testInlineData() throws UnsupportedEncodingException {
+ String design = "<v-table footer-visible=true> "//
+ + " <table>" //
+ + " <colgroup>"
+ + " <col property-id='foo' width=150 />"
+ + " <col property-id='bar' />"
+ + " <col property-id='baz' />" //
+ + " </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>" //
+ + " </tbody>" //
+ + " <tfoot>" //
+ + " <tr><td>F1<td>F2<td>F3</tr>" //
+ + " </tfoot>" //
+ + " </table>" //
+ + "</v-table>";
+ Table table = new Table();
+ table.addContainerProperty("foo", String.class, null);
+ table.addContainerProperty("bar", String.class, null);
+ table.addContainerProperty("baz", String.class, null);
+ table.setColumnHeaders("Description", "Milestone", "Status");
+ 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.setFooterVisible(true);
+ testRead(design, table);
+ // testWrite(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
new file mode 100644
index 0000000000..7f803c7f8b
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/table/TableDeclarativeTestBase.java
@@ -0,0 +1,52 @@
+/*
+ * 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.table;
+
+import static org.junit.Assert.assertTrue;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Table;
+
+public class TableDeclarativeTestBase extends DeclarativeTestBase<Table> {
+
+ @Override
+ public Table testRead(String design, Table expected) {
+ Table read = super.testRead(design, expected);
+ compareFooter(read, expected);
+ compareBody(read, expected);
+ return read;
+ }
+
+ private void compareBody(Table read, Table expected) {
+ assertEquals(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);
+ }
+ }
+ }
+
+ private void compareFooter(Table read, Table expected) {
+ for (Object pid : expected.getVisibleColumns()) {
+ assertEquals(expected.getColumnFooter(pid),
+ read.getColumnFooter(pid));
+ }
+ }
+}