aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java3
-rw-r--r--server/src/com/vaadin/ui/AbstractField.java2
-rw-r--r--server/src/com/vaadin/ui/AbstractOrderedLayout.java8
-rw-r--r--server/src/com/vaadin/ui/AbstractSplitPanel.java4
-rw-r--r--server/src/com/vaadin/ui/AbstractTextField.java4
-rw-r--r--server/src/com/vaadin/ui/Button.java2
-rw-r--r--server/src/com/vaadin/ui/Panel.java2
-rw-r--r--server/src/com/vaadin/ui/PasswordField.java4
-rw-r--r--server/src/com/vaadin/ui/TabSheet.java2
-rw-r--r--server/src/com/vaadin/ui/TextField.java4
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignContext.java63
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/MyChildDesign.java40
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/MyChildDesignCustomComponent.java25
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/MyDesignRoot.java38
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/MyExtendedChildDesign.java25
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/TestReadNestedTemplates.java62
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/TestWriteNestedTemplates.java89
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/mychilddesign.html12
-rw-r--r--server/tests/src/com/vaadin/tests/design/nested/mydesignroot.html10
19 files changed, 374 insertions, 25 deletions
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 0b9f8bd244..83833b75ce 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -1206,8 +1206,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
public void writeDesign(Element design, DesignContext designContext) {
// clear element contents
DesignAttributeHandler.clearElement(design);
- AbstractComponent def = designContext.getDefaultInstance(this
- .getClass());
+ AbstractComponent def = designContext.getDefaultInstance(this);
Attributes attr = design.attributes();
// handle default attributes
for (String attribute : getDefaultAttributes()) {
diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java
index c3e2036936..e40bdbde68 100644
--- a/server/src/com/vaadin/ui/AbstractField.java
+++ b/server/src/com/vaadin/ui/AbstractField.java
@@ -1803,7 +1803,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
- AbstractField def = designContext.getDefaultInstance(this.getClass());
+ AbstractField def = designContext.getDefaultInstance(this);
Attributes attr = design.attributes();
// handle readonly
DesignAttributeHandler.writeAttribute("readonly", attr,
diff --git a/server/src/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
index cd5609f091..b105d53fce 100644
--- a/server/src/com/vaadin/ui/AbstractOrderedLayout.java
+++ b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
@@ -533,13 +533,17 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
// synchronize default attributes
super.writeDesign(design, designContext);
// handle margin
- AbstractOrderedLayout def = designContext.getDefaultInstance(this
- .getClass());
+ AbstractOrderedLayout def = (AbstractOrderedLayout) designContext
+ .getDefaultInstance(this);
if (getMargin().getBitMask() != def.getMargin().getBitMask()) {
design.attr("margin", "");
}
// handle children
Element designElement = design;
+ if (!designContext.shouldWriteChildren(this, def)) {
+ return;
+ }
+
for (Component child : this) {
Element childNode = designContext.createNode(child);
designElement.appendChild(childNode);
diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java
index 9c33665c1c..4c85311075 100644
--- a/server/src/com/vaadin/ui/AbstractSplitPanel.java
+++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java
@@ -627,8 +627,8 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
super.writeDesign(design, designContext);
// handle custom attributes (write only if a value is not the
// default value)
- AbstractSplitPanel def = designContext.getDefaultInstance(this
- .getClass());
+ AbstractSplitPanel def = (AbstractSplitPanel) designContext
+ .getDefaultInstance(this);
if (getSplitPosition() != def.getSplitPosition()
|| !def.getSplitPositionUnit().equals(getSplitPositionUnit())) {
String splitPositionString = asString(getSplitPosition())
diff --git a/server/src/com/vaadin/ui/AbstractTextField.java b/server/src/com/vaadin/ui/AbstractTextField.java
index 8bca74936a..adeb1cb69f 100644
--- a/server/src/com/vaadin/ui/AbstractTextField.java
+++ b/server/src/com/vaadin/ui/AbstractTextField.java
@@ -803,8 +803,8 @@ public abstract class AbstractTextField extends AbstractField<String> implements
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
- AbstractTextField def = designContext.getDefaultInstance(this
- .getClass());
+ AbstractTextField def = (AbstractTextField) designContext
+ .getDefaultInstance(this);
Attributes attr = design.attributes();
DesignAttributeHandler.writeAttribute("maxlength", attr,
getMaxLength(), def.getMaxLength(), Integer.class);
diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java
index 9b50b5eebc..7063568f26 100644
--- a/server/src/com/vaadin/ui/Button.java
+++ b/server/src/com/vaadin/ui/Button.java
@@ -727,7 +727,7 @@ public class Button extends AbstractComponent implements
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
Attributes attr = design.attributes();
- Button def = designContext.getDefaultInstance(this.getClass());
+ Button def = (Button) designContext.getDefaultInstance(this);
String content = getCaption();
if (content != null) {
design.html(content);
diff --git a/server/src/com/vaadin/ui/Panel.java b/server/src/com/vaadin/ui/Panel.java
index b0242cc32d..0c2a3f580b 100644
--- a/server/src/com/vaadin/ui/Panel.java
+++ b/server/src/com/vaadin/ui/Panel.java
@@ -365,7 +365,7 @@ public class Panel extends AbstractSingleComponentContainer implements
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
// handle tabindex
- Panel def = designContext.getDefaultInstance(this.getClass());
+ Panel def = (Panel) designContext.getDefaultInstance(this);
DesignAttributeHandler.writeAttribute("tabindex", design.attributes(),
getTabIndex(), def.getTabIndex(), Integer.class);
}
diff --git a/server/src/com/vaadin/ui/PasswordField.java b/server/src/com/vaadin/ui/PasswordField.java
index 974a1c2c10..1894804775 100644
--- a/server/src/com/vaadin/ui/PasswordField.java
+++ b/server/src/com/vaadin/ui/PasswordField.java
@@ -107,8 +107,8 @@ public class PasswordField extends AbstractTextField {
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
- AbstractTextField def = designContext.getDefaultInstance(this
- .getClass());
+ AbstractTextField def = (AbstractTextField) designContext
+ .getDefaultInstance(this);
Attributes attr = design.attributes();
DesignAttributeHandler.writeAttribute("value", attr, getValue(),
def.getValue(), String.class);
diff --git a/server/src/com/vaadin/ui/TabSheet.java b/server/src/com/vaadin/ui/TabSheet.java
index 330acacfd0..a264692acb 100644
--- a/server/src/com/vaadin/ui/TabSheet.java
+++ b/server/src/com/vaadin/ui/TabSheet.java
@@ -1623,7 +1623,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
- TabSheet def = designContext.getDefaultInstance(this.getClass());
+ TabSheet def = (TabSheet) designContext.getDefaultInstance(this);
Attributes attr = design.attributes();
// handle tab index
DesignAttributeHandler.writeAttribute("tabindex", attr, getTabIndex(),
diff --git a/server/src/com/vaadin/ui/TextField.java b/server/src/com/vaadin/ui/TextField.java
index cd919ded9c..563810c76a 100644
--- a/server/src/com/vaadin/ui/TextField.java
+++ b/server/src/com/vaadin/ui/TextField.java
@@ -129,8 +129,8 @@ public class TextField extends AbstractTextField {
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
- AbstractTextField def = designContext.getDefaultInstance(this
- .getClass());
+ AbstractTextField def = (AbstractTextField) designContext
+ .getDefaultInstance(this);
Attributes attr = design.attributes();
DesignAttributeHandler.writeAttribute("value", attr, getValue(),
def.getValue(), String.class);
diff --git a/server/src/com/vaadin/ui/declarative/DesignContext.java b/server/src/com/vaadin/ui/declarative/DesignContext.java
index b196c84b02..214040b54d 100644
--- a/server/src/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/com/vaadin/ui/declarative/DesignContext.java
@@ -28,7 +28,10 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
+import com.vaadin.annotations.DesignRoot;
+import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Component;
+import com.vaadin.ui.HasComponents;
/**
* This class contains contextual information that is collected when a component
@@ -42,8 +45,8 @@ import com.vaadin.ui.Component;
public class DesignContext implements Serializable {
// cache for object instances
- private static Map<Class<?>, Object> instanceCache = Collections
- .synchronizedMap(new HashMap<Class<?>, Object>());
+ private static Map<Class<?>, Component> instanceCache = Collections
+ .synchronizedMap(new HashMap<Class<?>, Component>());
// The root component of the component hierarchy
private Component rootComponent = null;
@@ -254,22 +257,38 @@ public class DesignContext implements Serializable {
* Returns the default instance for the given class. The instance must not
* be modified by the caller.
*
- * @param instanceClass
+ * @param abstractComponent
* @return the default instance for the given class. The return value must
* not be modified by the caller
*/
- public <T> T getDefaultInstance(Class<T> instanceClass) {
- T instance = (T) instanceCache.get(instanceClass);
+ public <T> T getDefaultInstance(AbstractComponent abstractComponent) {
+ // If the root is a @DesignRoot component, it can't use itself as a
+ // reference or the written design will be empty
+
+ // If the root component in some other way initializes itself in the
+ // constructor
+ if (getRootComponent() == abstractComponent
+ && abstractComponent.getClass().isAnnotationPresent(
+ DesignRoot.class)) {
+ return (T) getDefaultInstance((Class<? extends Component>) abstractComponent
+ .getClass().getSuperclass());
+ }
+ return (T) getDefaultInstance(abstractComponent.getClass());
+ }
+
+ private Component getDefaultInstance(
+ Class<? extends Component> componentClass) {
+ Component instance = instanceCache.get(componentClass);
if (instance == null) {
try {
- instance = instanceClass.newInstance();
- instanceCache.put(instanceClass, instance);
+ instance = componentClass.newInstance();
+ instanceCache.put(componentClass, instance);
} catch (InstantiationException e) {
throw new RuntimeException("Could not instantiate "
- + instanceClass.getName());
+ + componentClass.getName());
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not instantiate "
- + instanceClass.getName());
+ + componentClass.getName());
}
}
return instance;
@@ -663,4 +682,30 @@ public class DesignContext implements Serializable {
}
}
+ /**
+ * Helper method for component write implementors to determine whether their
+ * children should be written out or not
+ *
+ * @param c
+ * The component being written
+ * @param defaultC
+ * The default instance for the component
+ * @return
+ */
+ public boolean shouldWriteChildren(Component c, Component defaultC) {
+ if (c == getRootComponent()) {
+ // The root component should always write its children - otherwise
+ // the result is empty
+ return true;
+ }
+
+ if (defaultC instanceof HasComponents
+ && ((HasComponents) defaultC).iterator().hasNext()) {
+ // Easy version which assumes that this is a custom component if the
+ // constructor adds children
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/MyChildDesign.java b/server/tests/src/com/vaadin/tests/design/nested/MyChildDesign.java
new file mode 100644
index 0000000000..e85c0aca5f
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/MyChildDesign.java
@@ -0,0 +1,40 @@
+/*
+ * 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.design.nested;
+
+import org.junit.Ignore;
+
+import com.vaadin.annotations.DesignRoot;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.declarative.Design;
+
+/**
+ * Child design component
+ *
+ * @author Vaadin Ltd
+ */
+@Ignore
+@DesignRoot("mychilddesign.html")
+public class MyChildDesign extends HorizontalLayout {
+ public Label childLabel;
+ public MyChildDesignCustomComponent childCustomComponent;
+
+ public MyChildDesign() {
+ Design.read(this);
+ childLabel.setDescription("added in constructor");
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/MyChildDesignCustomComponent.java b/server/tests/src/com/vaadin/tests/design/nested/MyChildDesignCustomComponent.java
new file mode 100644
index 0000000000..94e34baea2
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/MyChildDesignCustomComponent.java
@@ -0,0 +1,25 @@
+/*
+ * 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.design.nested;
+
+import org.junit.Ignore;
+
+import com.vaadin.ui.Button;
+
+@Ignore
+public class MyChildDesignCustomComponent extends Button {
+
+}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/MyDesignRoot.java b/server/tests/src/com/vaadin/tests/design/nested/MyDesignRoot.java
new file mode 100644
index 0000000000..5727322ce3
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/MyDesignRoot.java
@@ -0,0 +1,38 @@
+/*
+ * 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.design.nested;
+
+import org.junit.Ignore;
+
+import com.vaadin.annotations.DesignRoot;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.declarative.Design;
+
+/**
+ * Root design component
+ *
+ * @author Vaadin Ltd
+ */
+@Ignore
+@DesignRoot("mydesignroot.html")
+public class MyDesignRoot extends VerticalLayout {
+ // should be assigned automatically
+ public MyExtendedChildDesign childDesign;
+
+ public MyDesignRoot() {
+ Design.read(this);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/MyExtendedChildDesign.java b/server/tests/src/com/vaadin/tests/design/nested/MyExtendedChildDesign.java
new file mode 100644
index 0000000000..2012e4ec14
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/MyExtendedChildDesign.java
@@ -0,0 +1,25 @@
+/*
+ * 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.design.nested;
+
+import org.junit.Ignore;
+
+@Ignore
+public class MyExtendedChildDesign extends MyChildDesign {
+ public MyExtendedChildDesign() {
+ super();
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/TestReadNestedTemplates.java b/server/tests/src/com/vaadin/tests/design/nested/TestReadNestedTemplates.java
new file mode 100644
index 0000000000..c1483adc8a
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/TestReadNestedTemplates.java
@@ -0,0 +1,62 @@
+/*
+ * 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.design.nested;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for reading nested templates
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TestReadNestedTemplates extends TestCase {
+
+ private MyDesignRoot root;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ root = new MyDesignRoot();
+ }
+
+ public void testChildren() {
+ assertEquals("The root layout must contain one child", 1,
+ root.getComponentCount());
+ assertTrue(root.iterator().next() instanceof MyExtendedChildDesign);
+ }
+
+ public void testGrandChildren() {
+ assertEquals("The root layout must have two grandchildren", 2,
+ root.childDesign.getComponentCount());
+ }
+
+ public void testRootComponentFields() {
+ assertNotNull("The child component must not be null", root.childDesign);
+ }
+
+ public void testChildComponentFields() {
+ assertNotNull("Grandchildren must not be null",
+ root.childDesign.childLabel);
+ assertNotNull("Grandchildren must not be null",
+ root.childDesign.childCustomComponent);
+ assertEquals("child label caption must be read", "test content",
+ root.childDesign.childLabel.getValue());
+ assertEquals("child custom component caption must be read",
+ "custom content",
+ root.childDesign.childCustomComponent.getCaption());
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/TestWriteNestedTemplates.java b/server/tests/src/com/vaadin/tests/design/nested/TestWriteNestedTemplates.java
new file mode 100644
index 0000000000..7fe63baa73
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/TestWriteNestedTemplates.java
@@ -0,0 +1,89 @@
+/*
+ * 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.design.nested;
+
+import junit.framework.TestCase;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.parser.Tag;
+
+import com.vaadin.ui.declarative.DesignContext;
+
+/**
+ *
+ * Test case for writing nested templates
+ *
+ * @author Vaadin Ltd
+ */
+public class TestWriteNestedTemplates extends TestCase {
+
+ private MyDesignRoot root;
+ private Element design;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ root = new MyDesignRoot();
+ design = createDesign();
+ DesignContext designContext = new DesignContext();
+ designContext.setRootComponent(root);
+ root.writeDesign(design, designContext);
+ }
+
+ public void testChildRendered() {
+ assertEquals("Root layout must have one child", 1, design.children()
+ .size());
+ assertEquals("com_vaadin_tests_design_nested-my-extended-child-design",
+ design.child(0).tagName());
+ }
+
+ public void testRootCaptionWritten() {
+ assertTrue("Root layout caption must be written",
+ design.hasAttr("caption"));
+ assertEquals("Root layout caption must be written", "root caption",
+ design.attr("caption"));
+ }
+
+ public void testChildCaptionWritten() {
+ assertTrue("Child design caption must be written", design.child(0)
+ .hasAttr("caption"));
+ assertEquals("Child design caption must be written", "child caption",
+ design.child(0).attr("caption"));
+ }
+
+ // The default caption is read from child template
+ public void testDefaultCaptionShouldNotBeWritten() {
+ design = createDesign();
+ root.childDesign.setCaption("Default caption for child design");
+ DesignContext designContext = new DesignContext();
+ designContext.setRootComponent(root);
+ root.writeDesign(design, designContext);
+ assertFalse("Default caption must not be written", design.child(0)
+ .hasAttr("caption"));
+ }
+
+ public void testChildDesignChildrenNotWrittenInRootTemplate() {
+ assertEquals(
+ "Children of the child template must not be written to root template",
+ 0, design.child(0).children().size());
+ }
+
+ private Element createDesign() {
+ return new Element(Tag.valueOf("v-vertical-layout"), "",
+ new Attributes());
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/design/nested/mychilddesign.html b/server/tests/src/com/vaadin/tests/design/nested/mychilddesign.html
new file mode 100644
index 0000000000..c636033d2d
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/mychilddesign.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta name="package-mapping" content="x:com.vaadin.tests.design.nested"/>
+ </head>
+ <body>
+ <v-horizontal-layout caption="Default caption for child design">
+ <v-label _id="childLabel">test content</v-label>
+ <!-- Test some custom component in child template -->
+ <x-my-child-design-custom-component _id="childCustomComponent">custom content</x-my-child-design-custom-component>
+ </v-horizontal-layout>
+</body> \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/design/nested/mydesignroot.html b/server/tests/src/com/vaadin/tests/design/nested/mydesignroot.html
new file mode 100644
index 0000000000..55ac27c194
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/nested/mydesignroot.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta name="package-mapping" content="x:com.vaadin.tests.design.nested"/>
+ </head>
+ <body>
+ <v-vertical-layout caption="root caption">
+ <x-my-extended-child-design _id="childDesign" caption="child caption"/>
+ </v-vertical-layout>
+ </body> \ No newline at end of file