summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/server/SizeWithUnit.java127
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java59
-rw-r--r--server/src/com/vaadin/ui/AbstractSplitPanel.java139
-rw-r--r--server/tests/src/com/vaadin/tests/layoutparser/all-components.html15
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeFromDesign.java173
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeToDesign.java151
6 files changed, 606 insertions, 58 deletions
diff --git a/server/src/com/vaadin/server/SizeWithUnit.java b/server/src/com/vaadin/server/SizeWithUnit.java
new file mode 100644
index 0000000000..4c3c51eaec
--- /dev/null
+++ b/server/src/com/vaadin/server/SizeWithUnit.java
@@ -0,0 +1,127 @@
+/*
+ * 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.server;
+
+import java.io.Serializable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.vaadin.server.Sizeable.Unit;
+import com.vaadin.shared.util.SharedUtil;
+
+/**
+ * A class for representing a value-unit pair. Also contains utility methods for
+ * parsing such pairs from a string.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class SizeWithUnit implements Serializable {
+ private float size;
+ private Unit unit;
+ private static final Pattern sizePattern = Pattern
+ .compile(SharedUtil.SIZE_PATTERN);
+
+ /**
+ * Constructs a new SizeWithUnit object representing the pair (size, unit).
+ *
+ * @param size
+ * a numeric value
+ * @param unit
+ * a unit
+ */
+ public SizeWithUnit(float size, Unit unit) {
+ this.size = size;
+ this.unit = unit;
+ }
+
+ /**
+ * Returns the numeric value stored in this object.
+ *
+ * @return the value of this (value, unit) pair
+ */
+ public float getSize() {
+ return size;
+ }
+
+ /**
+ * Returns the unit stored in this object.
+ *
+ * @return the unit of this (value, unit) pair
+ */
+ public Unit getUnit() {
+ return unit;
+ }
+
+ /**
+ * Returns an object whose numeric value and unit are taken from the string
+ * s. If s does not specify a unit and defaultUnit is not null, defaultUnit
+ * is used as the unit. If defaultUnit is null and s is a nonempty string
+ * representing a unitless number, an exception is thrown. Null or empty
+ * string will produce {-1,Unit#PIXELS}.
+ *
+ * @param s
+ * the string to be parsed
+ * @param defaultUnit
+ * The unit to be used if s does not contain any unit. Use null
+ * for no default unit.
+ * @return an object containing the parsed value and unit
+ */
+ public static SizeWithUnit parseStringSize(String s, Unit defaultUnit) {
+ if (s == null) {
+ return null;
+ }
+ s = s.trim();
+ if ("".equals(s)) {
+ return null;
+ }
+ float size = 0;
+ Unit unit = null;
+ Matcher matcher = sizePattern.matcher(s);
+ if (matcher.find()) {
+ size = Float.parseFloat(matcher.group(1));
+ if (size < 0) {
+ size = -1;
+ unit = Unit.PIXELS;
+ } else {
+ String symbol = matcher.group(2);
+ if ((symbol != null && symbol.length() > 0)
+ || defaultUnit == null) {
+ unit = Unit.getUnitFromSymbol(symbol);
+ } else {
+ unit = defaultUnit;
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid size argument: \"" + s
+ + "\" (should match " + sizePattern.pattern() + ")");
+ }
+ return new SizeWithUnit(size, unit);
+ }
+
+ /**
+ * Returns an object whose numeric value and unit are taken from the string
+ * s. Null or empty string will produce {-1,Unit#PIXELS}. An exception is
+ * thrown if s specifies a number without a unit.
+ *
+ * @param s
+ * the string to be parsed
+ * @return an object containing the parsed value and unit
+ */
+ public static SizeWithUnit parseStringSize(String s) {
+ return parseStringSize(s, null);
+ }
+} \ No newline at end of file
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 18cd1f5fa4..1cda253b01 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -16,7 +16,6 @@
package com.vaadin.ui;
-import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,8 +27,6 @@ import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Attributes;
@@ -46,6 +43,7 @@ import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.Extension;
import com.vaadin.server.Resource;
import com.vaadin.server.Responsive;
+import com.vaadin.server.SizeWithUnit;
import com.vaadin.server.Sizeable;
import com.vaadin.server.UserError;
import com.vaadin.server.VaadinSession;
@@ -100,8 +98,6 @@ public abstract class AbstractComponent extends AbstractClientConnector
private float height = SIZE_UNDEFINED;
private Unit widthUnit = Unit.PIXELS;
private Unit heightUnit = Unit.PIXELS;
- private static final Pattern sizePattern = Pattern
- .compile(SharedUtil.SIZE_PATTERN);
/**
* Keeps track of the Actions added to this component; the actual
@@ -890,7 +886,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
*/
@Override
public void setWidth(String width) {
- Size size = parseStringSize(width);
+ SizeWithUnit size = SizeWithUnit.parseStringSize(width);
if (size != null) {
setWidth(size.getSize(), size.getUnit());
} else {
@@ -905,7 +901,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
*/
@Override
public void setHeight(String height) {
- Size size = parseStringSize(height);
+ SizeWithUnit size = SizeWithUnit.parseStringSize(height);
if (size != null) {
setHeight(size.getSize(), size.getUnit());
} else {
@@ -1251,55 +1247,6 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
/*
- * Returns array with size in index 0 unit in index 1. Null or empty string
- * will produce {-1,Unit#PIXELS}
- */
- private static Size parseStringSize(String s) {
- if (s == null) {
- return null;
- }
- s = s.trim();
- if ("".equals(s)) {
- return null;
- }
- float size = 0;
- Unit unit = null;
- Matcher matcher = sizePattern.matcher(s);
- if (matcher.find()) {
- size = Float.parseFloat(matcher.group(1));
- if (size < 0) {
- size = -1;
- unit = Unit.PIXELS;
- } else {
- String symbol = matcher.group(2);
- unit = Unit.getUnitFromSymbol(symbol);
- }
- } else {
- throw new IllegalArgumentException("Invalid size argument: \"" + s
- + "\" (should match " + sizePattern.pattern() + ")");
- }
- return new Size(size, unit);
- }
-
- private static class Size implements Serializable {
- float size;
- Unit unit;
-
- public Size(float size, Unit unit) {
- this.size = size;
- this.unit = unit;
- }
-
- public float getSize() {
- return size;
- }
-
- public Unit getUnit() {
- return unit;
- }
- }
-
- /*
* Actions
*/
diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java
index 09f881cf46..1400bcf092 100644
--- a/server/src/com/vaadin/ui/AbstractSplitPanel.java
+++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java
@@ -18,16 +18,23 @@ package com.vaadin.ui;
import java.io.Serializable;
import java.lang.reflect.Method;
+import java.util.Collection;
import java.util.Iterator;
+import org.jsoup.nodes.Element;
+
import com.vaadin.event.ConnectorEventListener;
import com.vaadin.event.MouseEvents.ClickEvent;
+import com.vaadin.server.SizeWithUnit;
import com.vaadin.server.Sizeable;
import com.vaadin.shared.EventId;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelRpc;
import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState;
import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState.SplitterState;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
import com.vaadin.util.ReflectTools;
/**
@@ -546,4 +553,136 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
private SplitterState getSplitterState(boolean markAsDirty) {
return ((AbstractSplitPanelState) super.getState(markAsDirty)).splitterState;
}
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.ui.AbstractComponent#synchronizeFromDesign(org.jsoup.nodes
+ * .Element, com.vaadin.ui.declarative.DesignContext)
+ */
+ @Override
+ public void synchronizeFromDesign(Element design,
+ DesignContext designContext) {
+ // handle default attributes
+ super.synchronizeFromDesign(design, designContext);
+ // handle custom attributes, use default values if no explicit value
+ // set
+ AbstractSplitPanel def = designContext.getDefaultInstance(this
+ .getClass());
+ // There is no setter for reversed, so it will be handled using
+ // setSplitPosition.
+ boolean reversed = DesignAttributeHandler.readAttribute("reversed",
+ design.attributes(), def.getSplitterState().positionReversed,
+ Boolean.class);
+ if (design.hasAttr("split-position")) {
+ SizeWithUnit splitPosition = SizeWithUnit.parseStringSize(
+ design.attr("split-position"), def.getSplitPositionUnit());
+ setSplitPosition(splitPosition.getSize(), splitPosition.getUnit(),
+ reversed);
+ } else { // default value for split position
+ setSplitPosition(def.getSplitPosition(),
+ def.getSplitPositionUnit(), reversed);
+ }
+ if (design.hasAttr("min-split-position")) {
+ SizeWithUnit minSplitPosition = SizeWithUnit.parseStringSize(
+ design.attr("min-split-position"),
+ def.getMinSplitPositionUnit());
+ setMinSplitPosition(minSplitPosition.getSize(),
+ minSplitPosition.getUnit());
+ } else { // default value for min-split-position
+ setMinSplitPosition(def.getMinSplitPosition(),
+ def.getMinSplitPositionUnit());
+ }
+ if (design.hasAttr("max-split-position")) {
+ SizeWithUnit maxSplitPosition = SizeWithUnit.parseStringSize(
+ design.attr("max-split-position"),
+ def.getMaxSplitPositionUnit());
+ setMaxSplitPosition(maxSplitPosition.getSize(),
+ maxSplitPosition.getUnit());
+ } else { // default value for max-split-position
+ setMaxSplitPosition(def.getMaxSplitPosition(),
+ def.getMaxSplitPositionUnit());
+ }
+ // remove current children
+ removeAllComponents();
+ // handle children
+ if (design.children().size() > 2) {
+ throw new DesignException(
+ "A split panel can contain at most two components.");
+ }
+ for (Element childElement : design.children()) {
+ Component childComponent = designContext.createChild(childElement);
+ if (childElement.hasAttr(":second")) {
+ setSecondComponent(childComponent);
+ } else {
+ addComponent(childComponent);
+ }
+ }
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> attributes = super.getCustomAttributes();
+ // the setters of the properties do not accept strings such as "20px"
+ attributes.add("split-position");
+ attributes.add("min-split-position");
+ attributes.add("max-split-position");
+ // no explicit setter for reversed
+ attributes.add("reversed");
+ return attributes;
+ }
+
+ @Override
+ public void synchronizeToDesign(Element design, DesignContext designContext) {
+ // handle default attributes (also clears children and attributes)
+ super.synchronizeToDesign(design, designContext);
+ // handle custom attributes (write only if a value is not the
+ // default value)
+ AbstractSplitPanel def = designContext.getDefaultInstance(this
+ .getClass());
+ if (getSplitPosition() != def.getSplitPosition()
+ || !def.getSplitPositionUnit().equals(getSplitPositionUnit())) {
+ String splitPositionString = asString(getSplitPosition())
+ + getSplitPositionUnit();
+ design.attr("split-position", splitPositionString);
+ }
+ if (getMinSplitPosition() != def.getMinSplitPosition()
+ || !def.getMinSplitPositionUnit().equals(
+ getMinSplitPositionUnit())) {
+ design.attr("min-split-position", asString(getMinSplitPosition())
+ + getMinSplitPositionUnit());
+ }
+ if (getMaxSplitPosition() != def.getMaxSplitPosition()
+ || !def.getMaxSplitPositionUnit().equals(
+ getMaxSplitPositionUnit())) {
+ design.attr("max-split-position", asString(getMaxSplitPosition())
+ + getMaxSplitPositionUnit());
+ }
+ if (getSplitterState().positionReversed) {
+ design.attr("reversed", "");
+ }
+ // handle child components
+ Component firstComponent = getFirstComponent();
+ Component secondComponent = getSecondComponent();
+ if (firstComponent != null) {
+ Element childElement = designContext.createNode(firstComponent);
+ design.appendChild(childElement);
+ }
+ if (secondComponent != null) {
+ Element childElement = designContext.createNode(secondComponent);
+ if (firstComponent == null) {
+ childElement.attr(":second", "");
+ }
+ design.appendChild(childElement);
+ }
+ }
+
+ private String asString(float number) {
+ int truncated = (int) number;
+ if (truncated == number) {
+ return "" + truncated;
+ }
+ return "" + number;
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/layoutparser/all-components.html b/server/tests/src/com/vaadin/tests/layoutparser/all-components.html
index 9b05f29f9c..71aeeeaa41 100644
--- a/server/tests/src/com/vaadin/tests/layoutparser/all-components.html
+++ b/server/tests/src/com/vaadin/tests/layoutparser/all-components.html
@@ -39,7 +39,7 @@
</v-css-layout>
<!-- panel -->
- <v-panel caption=”Hello world” tabindex=2 scroll-left="10" scroll-top="10">
+ <v-panel caption="Hello world" tabindex=2 scroll-left="10" scroll-top="10">
<v-table size-full />
</v-panel>
@@ -86,7 +86,18 @@
</tab>
</v-accordion>
-
+ <!-- abstract split panel -->
+ <v-horizontal-split-panel split-position="20px" min-split-position="0px" max-split-position="50px" locked>
+ <v-button>First slot</v-button>
+ </v-horizontal-split-panel>
+ <v-vertical-split-panel split-position="25%" reversed>
+ <v-button :second>Second slot</v-button>
+ </v-vertical-split-panel>
+ <v-horizontal-split-panel split-position="25%" reversed>
+ <v-button>First slot</v-button>
+ <v-button>Second slot</v-button>
+ </v-horizontal-split-panel>
+
</v-vertical-layout>
</body>
</html>
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeFromDesign.java b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeFromDesign.java
new file mode 100644
index 0000000000..b34e8fc3f0
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeFromDesign.java
@@ -0,0 +1,173 @@
+/*
+ * 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.abstractsplitpanel;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.parser.Tag;
+
+import com.vaadin.server.Sizeable.Unit;
+import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState.SplitterState;
+import com.vaadin.ui.AbstractSplitPanel;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.VerticalSplitPanel;
+import com.vaadin.ui.declarative.DesignContext;
+
+/**
+ * Tests synchronizing the attributes and children of horizontal and vertical
+ * split panels from a design.
+ *
+ * @author Vaadin Ltd
+ */
+public class TestSynchronizeFromDesign extends TestCase {
+ DesignContext ctx;
+
+ @Override
+ protected void setUp() {
+ ctx = new DesignContext();
+ }
+
+ public void testAttributes() throws Exception {
+ // Create a design with non-default attributes values.
+ Element design = createDesign(true, false, true, true);
+ HorizontalSplitPanel sp = new HorizontalSplitPanel();
+ sp.synchronizeFromDesign(design, ctx);
+ // Check that the attributes are correctly parsed.
+ assertEquals(20.5f, sp.getSplitPosition());
+ assertEquals(Unit.PERCENTAGE, sp.getSplitPositionUnit());
+ assertEquals(20f, sp.getMinSplitPosition());
+ assertEquals(Unit.PERCENTAGE, sp.getMinSplitPositionUnit());
+ assertEquals(50f, sp.getMaxSplitPosition());
+ assertEquals(Unit.PIXELS, sp.getMaxSplitPositionUnit());
+ assertEquals(true, sp.isLocked());
+ checkReversed(sp, true);
+ // check that the properties get the default values if the design
+ // does not have attributes corresponding to those properties
+ design = createDesign(true, true, true, true);
+ sp.synchronizeFromDesign(design, ctx);
+ HorizontalSplitPanel def = new HorizontalSplitPanel();
+ assertEquals(def.getSplitPosition(), sp.getSplitPosition());
+ assertEquals(def.getSplitPositionUnit(), sp.getSplitPositionUnit());
+ assertEquals(def.getMinSplitPosition(), sp.getMinSplitPosition());
+ assertEquals(def.getMinSplitPositionUnit(),
+ sp.getMinSplitPositionUnit());
+ assertEquals(def.getMaxSplitPosition(), sp.getMaxSplitPosition());
+ assertEquals(def.getMaxSplitPositionUnit(),
+ sp.getMaxSplitPositionUnit());
+ assertEquals(def.isLocked(), sp.isLocked());
+ checkReversed(sp, false);
+ }
+
+ public void testWithNoChildren() {
+ Element design = createDesign(true, false, false, false);
+ HorizontalSplitPanel sp = new HorizontalSplitPanel();
+ sp.synchronizeFromDesign(design, ctx);
+ assertEquals("Unexpected child count for the split panel.", 0,
+ sp.getComponentCount());
+ }
+
+ public void testWithFirstChild() {
+ Element design = createDesign(false, false, true, false);
+ VerticalSplitPanel sp = new VerticalSplitPanel();
+ sp.synchronizeFromDesign(design, ctx);
+ assertEquals("Unexpected child count for the split panel.", 1,
+ sp.getComponentCount());
+ Object obj = sp.getFirstComponent();
+ assertEquals("Wrong component in split panel.", Table.class,
+ obj.getClass());
+ }
+
+ public void testWithSecondChild() {
+ Element design = createDesign(true, false, false, true);
+ HorizontalSplitPanel sp = new HorizontalSplitPanel();
+ sp.synchronizeFromDesign(design, ctx);
+ assertEquals("Unexpected child count for the split panel.", 1,
+ sp.getComponentCount());
+ Object obj = sp.getSecondComponent();
+ assertEquals("Wrong component in split panel.", VerticalLayout.class,
+ obj.getClass());
+ }
+
+ public void testWithBothChildren() {
+ Element design = createDesign(false, false, true, true);
+ VerticalSplitPanel sp = new VerticalSplitPanel();
+ sp.synchronizeFromDesign(design, ctx);
+ assertEquals("Unexpected child count for the split panel.", 2,
+ sp.getComponentCount());
+ Object first = sp.getFirstComponent();
+ Object second = sp.getSecondComponent();
+ assertEquals("Wrong first component in split panel.", Table.class,
+ first.getClass());
+ assertEquals("Wrong second component in split panel.",
+ VerticalLayout.class, second.getClass());
+ }
+
+ /*
+ * Creates an html tree node structure representing a split panel and its
+ * contents. The parameters are used for controlling whether the split panel
+ * is horizontal or vertical, whether attributes are set for the design and
+ * whether the split panel should have the first and the second child
+ * component.
+ */
+ private Element createDesign(boolean horizontal,
+ boolean useDefaultAttributes, boolean hasFirstChild,
+ boolean hasSecondChild) {
+ Attributes attributes = new Attributes();
+ if (!useDefaultAttributes) {
+ attributes.put("split-position", "20.5%");
+ // The unitless number should correspond to 20%
+ attributes.put("min-split-position", "20");
+ attributes.put("max-split-position", "50px");
+ attributes.put("locked", "");
+ attributes.put("reversed", "");
+ }
+ String tagName = horizontal ? "v-horizontal-split-panel"
+ : "v-vertical-split-panel";
+ Element element = new Element(Tag.valueOf(tagName), "", attributes);
+ // Create the children
+ if (hasFirstChild) {
+ Element child = new Element(Tag.valueOf("v-table"), "");
+ element.appendChild(child);
+ }
+ if (hasSecondChild) {
+ Element child = new Element(Tag.valueOf("v-vertical-layout"), "");
+ if (!hasFirstChild) {
+ child.attr(":second", "");
+ }
+ element.appendChild(child);
+ }
+ return element;
+ }
+
+ /*
+ * Checks the reversed property of a split panel.
+ */
+ private void checkReversed(AbstractSplitPanel sp, boolean expected)
+ throws Exception {
+ Method getter = AbstractSplitPanel.class
+ .getDeclaredMethod("getSplitterState");
+ getter.setAccessible(true);
+ SplitterState state = (SplitterState) getter.invoke(sp);
+ assertEquals("Wrong value for split panel property reversed.",
+ expected, state.positionReversed);
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeToDesign.java b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeToDesign.java
new file mode 100644
index 0000000000..3e342a0c89
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractsplitpanel/TestSynchronizeToDesign.java
@@ -0,0 +1,151 @@
+/*
+ * 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.abstractsplitpanel;
+
+import junit.framework.TestCase;
+
+import org.jsoup.nodes.Element;
+
+import com.vaadin.server.Sizeable.Unit;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.VerticalSplitPanel;
+import com.vaadin.ui.declarative.DesignContext;
+
+/**
+ * Tests synchronizing the properties and child components of split panels to a
+ * design.
+ *
+ * @author Vaadin Ltd
+ */
+public class TestSynchronizeToDesign extends TestCase {
+ private DesignContext ctx;
+
+ @Override
+ public void setUp() {
+ ctx = new DesignContext();
+ }
+
+ public void testHorizontalWithDefaultValues() {
+ // no attributes or child elements should appear
+ HorizontalSplitPanel sp = new HorizontalSplitPanel();
+ Element e = ctx.createNode(sp);
+ assertEquals("Wrong tag name.", "v-horizontal-split-panel",
+ e.nodeName());
+ assertEquals("The split panel should not have attributes.", 0, e
+ .attributes().size());
+ assertEquals("The split panel should not have children.", 0, e
+ .children().size());
+ }
+
+ public void testVerticalWithAttributes() {
+ // All defined attributes should be output in the tree node. No child
+ // components are present in this test.
+ VerticalSplitPanel sp = new VerticalSplitPanel();
+ sp.setSplitPosition(27f, Unit.PIXELS, true);
+ sp.setMinSplitPosition(5.5f, Unit.PERCENTAGE);
+ sp.setMaxSplitPosition(95, Unit.PERCENTAGE);
+ sp.setLocked(true);
+ Element e = ctx.createNode(sp);
+ assertEquals("Wrong tag name.", "v-vertical-split-panel", e.nodeName());
+ assertEquals("Unexpected number of attributes.", 5, e.attributes()
+ .size());
+ assertEquals("Wrong split position.", "27px", e.attr("split-position"));
+ assertEquals("Wrong minimum split position.", "5.5%",
+ e.attr("min-split-position"));
+ assertEquals("Wrong maximum split position.", "95%",
+ e.attr("max-split-position"));
+ assertTrue("Unexpected value for locked: " + e.attr("locked"),
+ "true".equals(e.attr("locked")) || "".equals(e.attr("locked")));
+ assertTrue(
+ "Unexpected value for reversed: " + e.attr("reversed"),
+ "true".equals(e.attr("reversed"))
+ || "".equals(e.attr("reversed")));
+ }
+
+ public void testHorizontalWithFirstChild() {
+ // The split panel contains only the first child.
+ HorizontalSplitPanel sp = new HorizontalSplitPanel();
+ sp.setSplitPosition(25f);
+ sp.setFirstComponent(new Button("First slot"));
+ Element e = ctx.createNode(sp);
+ assertEquals("Wrong split position.", "25%", e.attr("split-position"));
+ assertEquals("Wrong number of child elements.", 1, e.children().size());
+ Element eb = e.children().get(0);
+ assertEquals("Wrong tag name of first child element.", "v-button",
+ eb.nodeName());
+ assertEquals("Wrong text in the button element.", "First slot",
+ eb.html());
+ }
+
+ public void testVerticalWithSecondChild() {
+ // The split panel contains only the second child.
+ VerticalSplitPanel sp = new VerticalSplitPanel();
+ sp.setMinSplitPosition(25f, Unit.PIXELS);
+ sp.setSecondComponent(new Label("Second slot"));
+ Element e = ctx.createNode(sp);
+ assertEquals("Wrong minimum split position.", "25px",
+ e.attr("min-split-position"));
+ assertEquals("Wrong number of child elements.", 1, e.children().size());
+ Element el = e.children().get(0);
+ assertEquals("Wrong tag name of child element.", "v-label",
+ el.nodeName());
+ assertEquals("Wrong text in the label element.", "Second slot",
+ el.html());
+ assertTrue("Missing attribute :second in the label element.",
+ el.hasAttr(":second"));
+ }
+
+ public void testVerticalWithBothChildren() {
+ // The split panel has both child components.
+ VerticalSplitPanel sp = new VerticalSplitPanel();
+ sp.setFirstComponent(new Button("First slot"));
+ sp.setSecondComponent(new Label("Second slot"));
+ Element e = ctx.createNode(sp);
+ assertEquals("Wrong number of child elements.", 2, e.children().size());
+ Element eb = e.children().get(0);
+ assertEquals("Wrong tag name of first child element.", "v-button",
+ eb.nodeName());
+ assertEquals("Wrong text in the button element.", "First slot",
+ eb.html());
+ Element el = e.children().get(1);
+ assertEquals("Wrong tag name of second child element.", "v-label",
+ el.nodeName());
+ assertEquals("Wrong text in the label element.", "Second slot",
+ el.html());
+ assertFalse(
+ "There should be no :second attribute when a split panel has both children.",
+ el.hasAttr(":second"));
+ }
+
+ public void testReSynchronize() {
+ // Test that old children and attributes are removed when an element is
+ // synchronized to a new component.
+ VerticalSplitPanel sp = new VerticalSplitPanel();
+ sp.setMinSplitPosition(5.5f, Unit.PERCENTAGE);
+ sp.setMaxSplitPosition(95, Unit.PERCENTAGE);
+ sp.setFirstComponent(new Button("First slot"));
+ sp.setSecondComponent(new Label("Second slot"));
+ Element e = ctx.createNode(sp);
+ sp = new VerticalSplitPanel();
+ sp.synchronizeToDesign(e, ctx);
+ assertTrue("There should be no attributes in the node.", e.attributes()
+ .size() == 0);
+ assertTrue("There should be no child elements.",
+ e.children().size() == 0);
+ }
+}