]> source.dussan.org Git - vaadin-framework.git/commitdiff
Allow captions to contain HTML (#9426)
authorArtur Signell <artur@vaadin.com>
Thu, 4 Sep 2014 18:57:34 +0000 (21:57 +0300)
committerLeif Åstrand <leif@vaadin.com>
Thu, 18 Dec 2014 14:31:49 +0000 (14:31 +0000)
Change-Id: I4a0e580aef1a97ce69238ea0d476599883928d84

20 files changed:
client/src/com/vaadin/client/VCaption.java
client/src/com/vaadin/client/ui/VWindow.java
client/src/com/vaadin/client/ui/button/ButtonConnector.java
client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
client/src/com/vaadin/client/ui/colorpicker/ColorPickerAreaConnector.java
client/src/com/vaadin/client/ui/colorpicker/ColorPickerConnector.java
client/src/com/vaadin/client/ui/form/FormConnector.java
client/src/com/vaadin/client/ui/gridlayout/GridLayoutConnector.java
client/src/com/vaadin/client/ui/link/LinkConnector.java
client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java
client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
client/src/com/vaadin/client/ui/orderedlayout/Slot.java
server/src/com/vaadin/ui/AbstractColorPicker.java
server/src/com/vaadin/ui/AbstractComponent.java
server/src/com/vaadin/ui/Button.java
shared/src/com/vaadin/shared/AbstractComponentState.java
shared/src/com/vaadin/shared/ui/button/ButtonState.java
shared/src/com/vaadin/shared/ui/colorpicker/ColorPickerState.java
uitest/src/com/vaadin/tests/layouts/CaptionsInLayouts.java
uitest/src/com/vaadin/tests/layouts/HtmlInCaption.java [new file with mode: 0644]

index becc89ce1d8d46218f9c6ab1a336d6f9edaa6d88..eb19dedf8b9afb56eb843bf568121545a5f84bec 100644 (file)
@@ -22,6 +22,7 @@ import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHTML;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.ui.AbstractFieldConnector;
 import com.vaadin.client.ui.Icon;
@@ -60,6 +61,8 @@ public class VCaption extends HTML {
 
     private TooltipInfo tooltipInfo = null;
 
+    private boolean captionAsHtml = false;
+
     /**
      * Creates a caption that is not linked to a {@link ComponentConnector}.
      * 
@@ -213,7 +216,7 @@ public class VCaption extends HTML {
                     captionText.setInnerHTML("&nbsp;");
                 }
             } else {
-                DOM.setInnerText(captionText, c);
+                setCaptionText(captionText, owner.getState());
             }
 
         } else if (captionText != null) {
@@ -382,7 +385,11 @@ public class VCaption extends HTML {
                     captionText.setInnerHTML("&nbsp;");
                 }
             } else {
-                DOM.setInnerText(captionText, caption);
+                if (captionAsHtml) {
+                    captionText.setInnerHTML(caption);
+                } else {
+                    captionText.setInnerText(caption);
+                }
             }
 
         } else if (captionText != null) {
@@ -687,4 +694,74 @@ public class VCaption extends HTML {
         return el.vOwnerPid;
     }-*/;
 
+    /**
+     * Sets whether the caption is rendered as HTML.
+     * <p>
+     * Default is false
+     * 
+     * @param captionAsHtml
+     *            true if the captions are rendered as HTML, false if rendered
+     *            as plain text
+     */
+    public void setCaptionAsHtml(boolean captionAsHtml) {
+        this.captionAsHtml = captionAsHtml;
+    }
+
+    /**
+     * Checks whether captions are rendered as HTML.
+     * <p>
+     * Default is false
+     * 
+     * @return true if the captions are rendered as HTML, false if rendered as
+     *         plain text
+     */
+    public boolean isCaptionAsHtml() {
+        return captionAsHtml;
+    }
+
+    /**
+     * Sets the text of the given caption element to the caption found in the
+     * state.
+     * <p>
+     * Uses {@link AbstractComponentState#captionAsHtml} to determine whether to
+     * set the caption as html or plain text
+     * 
+     * @since 7.4
+     * @param captionElement
+     *            the target element
+     * @param state
+     *            the state from which to read the caption text and mode
+     */
+    public static void setCaptionText(Element captionElement,
+            AbstractComponentState state) {
+        if (state.captionAsHtml) {
+            captionElement.setInnerHTML(state.caption);
+        } else {
+            captionElement.setInnerText(state.caption);
+        }
+
+    }
+
+    /**
+     * Sets the text of the given widget to the caption found in the state.
+     * <p>
+     * Uses {@link AbstractComponentState#captionAsHtml} to determine whether to
+     * set the caption as html or plain text
+     * 
+     * @since 7.4
+     * @param widget
+     *            the target widget
+     * @param state
+     *            the state from which to read the caption text and mode
+     */
+    public static void setCaptionText(HasHTML widget,
+            AbstractComponentState state) {
+        if (state.captionAsHtml) {
+            widget.setHTML(state.caption);
+        } else {
+            widget.setText(state.caption);
+        }
+
+    }
+
 }
index 5c9a2ab47db4cbd01f341ab2897d0f26cacd7206..eb3c89beb06fa8f9d84f55b8523271a91517b384 100644 (file)
@@ -872,7 +872,14 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
     }
 
     public void setCaption(String c, String iconURL) {
-        String html = Util.escapeHTML(c);
+        setCaption(c, iconURL, false);
+    }
+
+    public void setCaption(String c, String iconURL, boolean asHtml) {
+        String html = c;
+        if (!asHtml) {
+            c = Util.escapeHTML(c);
+        }
 
         // Provide information to assistive device users that a sub window was
         // opened
index 4220c3f5d1134c68ce965ec5c7edb20eceebf539..2d13d62a914d772a81f9a6bc574e975a6424528f 100644 (file)
@@ -26,6 +26,7 @@ import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.vaadin.client.EventHelper;
 import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.VCaption;
 import com.vaadin.client.annotations.OnStateChange;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.ui.AbstractComponentConnector;
@@ -98,14 +99,9 @@ public class ButtonConnector extends AbstractComponentConnector implements
                 blurHandlerRegistration);
     }
 
-    @OnStateChange({ "caption", "htmlContentAllowed" })
+    @OnStateChange({ "caption", "captionAsHtml" })
     void setCaption() {
-        String caption = getState().caption;
-        if (getState().htmlContentAllowed) {
-            getWidget().setHtml(caption);
-        } else {
-            getWidget().setText(caption);
-        }
+        VCaption.setCaptionText(getWidget().captionElement, getState());
     }
 
     @OnStateChange("iconAltText")
index 28f6beefa69ff3444b0f08dbe87f154283cbc392..63984ff2256ebf22c53f85d85cf414c253280b88 100644 (file)
@@ -27,6 +27,7 @@ import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.vaadin.client.EventHelper;
 import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.VCaption;
 import com.vaadin.client.VTooltip;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.ui.AbstractFieldConnector;
@@ -109,7 +110,8 @@ public class CheckBoxConnector extends AbstractFieldConnector implements
         }
 
         // Set text
-        getWidget().setText(getState().caption);
+        VCaption.setCaptionText(getWidget(), getState());
+
         getWidget().setValue(getState().checked);
         getWidget().immediate = getState().immediate;
     }
index 2237920cb8e89c399b03526ab2caea03cf1a45f7..355e70558168fce134f2426a5b12b482c6898486 100644 (file)
@@ -18,6 +18,7 @@ package com.vaadin.client.ui.colorpicker;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.VCaption;
 import com.vaadin.client.communication.RpcProxy;
 import com.vaadin.client.ui.VColorPickerArea;
 import com.vaadin.shared.ui.Connect;
@@ -55,11 +56,7 @@ public class ColorPickerAreaConnector extends AbstractColorPickerConnector {
 
     @Override
     protected void setCaption(String caption) {
-        if (getState().htmlContentAllowed) {
-            getWidget().setHTML(caption);
-        } else {
-            getWidget().setText(caption);
-        }
+        VCaption.setCaptionText(getWidget(), getState());
     }
 
     @Override
index 237241fe81a83e5e1d390d921161699c6e20c542..2f0dbd5ce7ca4f48ca24519989d53ca7f85623d2 100644 (file)
@@ -55,7 +55,7 @@ public class ColorPickerConnector extends AbstractColorPickerConnector {
 
     @Override
     protected void setCaption(String caption) {
-        if (getState().htmlContentAllowed) {
+        if (getState().captionAsHtml) {
             getWidget().setHtml(caption);
         } else {
             getWidget().setText(caption);
index 25046f8b9ab70211b5244cacad2b027633b446e4..857c2bd40e861d4616b558816972b48a7988cf01 100644 (file)
@@ -26,6 +26,7 @@ import com.vaadin.client.LayoutManager;
 import com.vaadin.client.Paintable;
 import com.vaadin.client.TooltipInfo;
 import com.vaadin.client.UIDL;
+import com.vaadin.client.VCaption;
 import com.vaadin.client.ui.AbstractComponentContainerConnector;
 import com.vaadin.client.ui.ShortcutActionHandler;
 import com.vaadin.client.ui.VForm;
@@ -102,7 +103,7 @@ public class FormConnector extends AbstractComponentContainerConnector
 
         boolean legendEmpty = true;
         if (getState().caption != null) {
-            getWidget().caption.setInnerText(getState().caption);
+            VCaption.setCaptionText(getWidget().caption, getState());
             legendEmpty = false;
         } else {
             getWidget().caption.setInnerText("");
index 36262ef3d5a761f92ac8005afb8444800f7da3c8..3102af8da9e8202111c55b7fc80773d60aa7fc1d 100644 (file)
@@ -185,7 +185,6 @@ public class GridLayoutConnector extends AbstractComponentContainerConnector
             VCaption caption = layoutSlot.getCaption();
             if (caption == null) {
                 caption = new VCaption(childConnector, getConnection());
-
                 Widget widget = childConnector.getWidget();
 
                 layout.setCaption(widget, caption);
index 42c42cf06e2d85cefa235c0b925fc691b6810c83..5a1244565536f9d87e218e4a8df573fda638cfc5 100644 (file)
@@ -18,6 +18,7 @@ package com.vaadin.client.ui.link;
 
 import com.google.gwt.dom.client.Style.Display;
 import com.google.gwt.user.client.DOM;
+import com.vaadin.client.VCaption;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.ui.AbstractComponentConnector;
 import com.vaadin.client.ui.Icon;
@@ -72,7 +73,7 @@ public class LinkConnector extends AbstractComponentConnector {
         getWidget().targetHeight = getState().targetHeight;
 
         // Set link caption
-        getWidget().captionElement.setInnerText(getState().caption);
+        VCaption.setCaptionText(getWidget().captionElement, getState());
 
         // handle error
         if (null != getState().errorMessage) {
index 6968f5957474492294bb80e3a62d094c73f7d819..2aae9beae63710c55deb11b1c42bf387ac431859 100644 (file)
@@ -22,6 +22,7 @@ import com.google.gwt.event.dom.client.FocusHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.vaadin.client.EventHelper;
+import com.vaadin.client.VCaption;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.ui.AbstractComponentConnector;
 import com.vaadin.client.ui.Icon;
@@ -64,11 +65,7 @@ public class NativeButtonConnector extends AbstractComponentConnector implements
                 blurHandlerRegistration);
 
         // Set text
-        if (getState().htmlContentAllowed) {
-            getWidget().setHTML(getState().caption);
-        } else {
-            getWidget().setText(getState().caption);
-        }
+        VCaption.setCaptionText(getWidget(), getState());
 
         // handle error
         if (null != getState().errorMessage) {
index 0c09ae49c6f36e7e385fb63b19e2a88b31515a1b..c2157650a59829d528751ef4317e8b00d7c3b4fb 100644 (file)
@@ -276,7 +276,7 @@ public abstract class AbstractOrderedLayoutConnector extends
         }
 
         slot.setCaption(caption, icon, styles, error, showError, required,
-                enabled);
+                enabled, child.getState().captionAsHtml);
 
         AriaHelper.handleInputRequired(child.getWidget(), required);
         AriaHelper.handleInputInvalid(child.getWidget(), showError);
index b1d7dd280420a19e6e0a305be092777b35de1657..4b60f11ab4e9aea42398324130012fe62800a068 100644 (file)
@@ -440,7 +440,7 @@ public final class Slot extends SimplePanel {
     }
 
     /**
-     * Set the caption of the slot
+     * Set the caption of the slot as text
      * 
      * @param captionText
      *            The text of the caption
@@ -459,6 +459,34 @@ public final class Slot extends SimplePanel {
      */
     public void setCaption(String captionText, Icon icon, List<String> styles,
             String error, boolean showError, boolean required, boolean enabled) {
+        setCaption(captionText, icon, styles, error, showError, required,
+                enabled, false);
+    }
+
+    /**
+     * Set the caption of the slot
+     * 
+     * @param captionText
+     *            The text of the caption
+     * @param icon
+     *            The icon
+     * @param styles
+     *            The style names
+     * @param error
+     *            The error message
+     * @param showError
+     *            Should the error message be shown
+     * @param required
+     *            Is the (field) required
+     * @param enabled
+     *            Is the component enabled
+     * @param captionAsHtml
+     *            true if the caption should be rendered as HTML, false
+     *            otherwise
+     */
+    public void setCaption(String captionText, Icon icon, List<String> styles,
+            String error, boolean showError, boolean required, boolean enabled,
+            boolean captionAsHtml) {
 
         // TODO place for optimization: check if any of these have changed
         // since last time, and only run those changes
@@ -507,7 +535,11 @@ public final class Slot extends SimplePanel {
             if (captionText.trim().equals("")) {
                 this.captionText.setInnerHTML("&nbsp;");
             } else {
-                this.captionText.setInnerText(captionText);
+                if (captionAsHtml) {
+                    this.captionText.setInnerHTML(captionText);
+                } else {
+                    this.captionText.setInnerText(captionText);
+                }
             }
         } else if (this.captionText != null) {
             this.captionText.removeFromParent();
index acf3b2c042c64f4452dbc600a8f8835fc66f9749..608a42d33bbf7b8b8383a09e400e41205c50a64b 100644 (file)
@@ -455,9 +455,11 @@ public abstract class AbstractColorPicker extends AbstractComponent implements
      * @param htmlContentAllowed
      *            <code>true</code> if caption is rendered as HTML,
      *            <code>false</code> otherwise
+     * @deprecated as of , use {@link #setCaptionAsHtml(boolean)} instead
      */
+    @Deprecated
     public void setHtmlContentAllowed(boolean htmlContentAllowed) {
-        getState().htmlContentAllowed = htmlContentAllowed;
+        setCaptionAsHtml(htmlContentAllowed);
     }
 
     /**
@@ -465,8 +467,10 @@ public abstract class AbstractColorPicker extends AbstractComponent implements
      * 
      * @return <code>true</code> if the caption text is to be rendered as HTML,
      *         <code>false</code> otherwise
+     * @deprecated as of , use {@link #isCaptionAsHtml()} instead
      */
+    @Deprecated
     public boolean isHtmlContentAllowed() {
-        return getState(false).htmlContentAllowed;
+        return isCaptionAsHtml();
     }
 }
index 735fb15fd8c4c0237048df931f4c10450961418b..9ff6dff21e74a60cded0fea5807f2d50f5e434a4 100644 (file)
@@ -265,6 +265,35 @@ public abstract class AbstractComponent extends AbstractClientConnector
         getState().caption = caption;
     }
 
+    /**
+     * Sets whether the caption is rendered as HTML.
+     * <p>
+     * If set to true, the captions are rendered in the browser as HTML and the
+     * developer is responsible for ensuring no harmful HTML is used. If set to
+     * false, the caption is rendered in the browser as plain text.
+     * <p>
+     * The default is false, i.e. to render that caption as plain text.
+     * 
+     * @param captionAsHtml
+     *            true if the captions are rendered as HTML, false if rendered
+     *            as plain text
+     */
+    public void setCaptionAsHtml(boolean captionAsHtml) {
+        getState().captionAsHtml = captionAsHtml;
+    }
+
+    /**
+     * Checks whether captions are rendered as HTML
+     * <p>
+     * The default is false, i.e. to render that caption as plain text.
+     * 
+     * @return true if the captions are rendered as HTML, false if rendered as
+     *         plain text
+     */
+    public boolean isCaptionAsHtml() {
+        return getState(false).captionAsHtml;
+    }
+
     /*
      * Don't add a JavaDoc comment here, we use the default documentation from
      * implemented interface.
index c102157bf17dcbd6b76759a7273df6aeca0c2787..677f29ba13b9651b9cde3e084b5a08cb4ffb1433 100644 (file)
@@ -642,7 +642,7 @@ public class Button extends AbstractComponent implements
 
     /**
      * Set whether the caption text is rendered as HTML or not. You might need
-     * to retheme button to allow higher content than the original text style.
+     * to re-theme button to allow higher content than the original text style.
      * 
      * If set to true, the captions are passed to the browser as html and the
      * developer is responsible for ensuring no harmful html is used. If set to
@@ -653,7 +653,7 @@ public class Button extends AbstractComponent implements
      *            <code>false</code> otherwise
      */
     public void setHtmlContentAllowed(boolean htmlContentAllowed) {
-        getState().htmlContentAllowed = htmlContentAllowed;
+        getState().captionAsHtml = htmlContentAllowed;
     }
 
     /**
@@ -663,7 +663,7 @@ public class Button extends AbstractComponent implements
      *         <code>false</code> otherwise
      */
     public boolean isHtmlContentAllowed() {
-        return getState(false).htmlContentAllowed;
+        return getState(false).captionAsHtml;
     }
 
     /*
@@ -711,6 +711,7 @@ public class Button extends AbstractComponent implements
         result.add("icon-alternate-text");
         result.add("click-shortcut");
         result.add("html-content-allowed");
+        result.add("caption-as-html");
         return result;
     }
 
index 816af978cf023ab0b1f7d765cc1f12f6a6414bd9..9e21954f3ed480662c44097305b3470faa060b07 100644 (file)
@@ -44,4 +44,5 @@ public class AbstractComponentState extends SharedState {
     // TODO this could be an object with more information, but currently the UI
     // only uses the message
     public String errorMessage = null;
+    public boolean captionAsHtml = false;
 }
index a12136870ccea27c673c70b5b81bc43df3634c7c..5b099572df0d61cec52d40b00f6610f733f6cbc5 100644 (file)
@@ -33,9 +33,5 @@ public class ButtonState extends TabIndexState {
     }
     public boolean disableOnClick = false;
     public int clickShortcutKeyCode = 0;
-    /**
-     * If caption should be rendered in HTML
-     */
-    public boolean htmlContentAllowed = false;
     public String iconAltText = "";
 }
index 978b9a8417976b9b05156687234a0036818a43fe..3fdce20ce7b7851fc2f817184dc8f1a746168178 100644 (file)
@@ -36,5 +36,4 @@ public class ColorPickerState extends AbstractComponentState {
 
     public boolean showDefaultCaption;
 
-    public boolean htmlContentAllowed;
 }
index 03c3c43ccd9fa5107ee2bade70e2fc032b4c5c3f..74cfe12ad7bcd7e0ed16cb3cac136011cfa28820 100644 (file)
@@ -8,7 +8,8 @@ import com.vaadin.data.Property.ValueChangeEvent;
 import com.vaadin.data.Property.ValueChangeListener;
 import com.vaadin.server.ThemeResource;
 import com.vaadin.server.UserError;
-import com.vaadin.tests.components.TestBase;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
 import com.vaadin.ui.AbstractField;
 import com.vaadin.ui.Button;
 import com.vaadin.ui.Button.ClickEvent;
@@ -25,7 +26,7 @@ import com.vaadin.ui.NativeSelect;
 import com.vaadin.ui.TextField;
 import com.vaadin.ui.VerticalLayout;
 
-public class CaptionsInLayouts extends TestBase {
+public class CaptionsInLayouts extends AbstractTestUI {
 
     private static final Object CAPTION = "CAPTION";
     private static final Object CLASS = "C";
@@ -42,7 +43,7 @@ public class CaptionsInLayouts extends TestBase {
     private HorizontalLayout layoutParent = new HorizontalLayout();
 
     @Override
-    protected void setup() {
+    protected void setup(VaadinRequest request) {
         // setTheme("tests-tickets");
         addComponent(createLayoutSelect());
         addComponent(toggleRequired());
@@ -270,7 +271,7 @@ public class CaptionsInLayouts extends TestBase {
     }
 
     @Override
-    protected String getDescription() {
+    protected String getTestDescription() {
         return "Tests what happens when the caption changes in various layouts. Behavior should be consistent.";
     }
 
diff --git a/uitest/src/com/vaadin/tests/layouts/HtmlInCaption.java b/uitest/src/com/vaadin/tests/layouts/HtmlInCaption.java
new file mode 100644 (file)
index 0000000..830b96b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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.layouts;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.ColorPicker;
+import com.vaadin.ui.ColorPickerArea;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.Form;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Link;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+/**
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public class HtmlInCaption extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        HorizontalLayout main = new HorizontalLayout();
+        addComponent(main);
+        VerticalLayout components = new VerticalLayout();
+        components.setId("components");
+        VerticalLayout layouts = new VerticalLayout();
+        layouts.setId("layouts");
+        main.addComponent(layouts);
+        main.addComponent(components);
+
+        createComponents(components);
+        createLayouts(layouts);
+
+        Window w = new Window();
+        w.setCaption(getTextCaption("Window"));
+        w.setPositionX(600);
+        addWindow(w);
+
+        w = new Window();
+        w.setCaptionAsHtml(true);
+        w.setCaption(getHtmlCaption("Window"));
+        w.setPositionX(600);
+        w.setPositionY(100);
+        addWindow(w);
+    }
+
+    private void createLayouts(VerticalLayout layouts) {
+        VerticalLayout vl = new VerticalLayout(tf(false), tf(true));
+        vl.setCaption("VerticalLayout");
+        layouts.addComponent(vl);
+
+        HorizontalLayout hl = new HorizontalLayout(tf(false), tf(true));
+        hl.setCaption("HorizontalLayout");
+        layouts.addComponent(hl);
+
+        GridLayout gl = new GridLayout(2, 1);
+        gl.setCaption("GridLayout");
+        gl.addComponents(tf(false), tf(true));
+        layouts.addComponent(gl);
+
+        CssLayout cl = new CssLayout();
+        cl.setCaption("CssLayout");
+        cl.addComponents(tf(false), tf(true));
+        layouts.addComponent(cl);
+
+        AbsoluteLayout al = new AbsoluteLayout();
+        al.setCaption("AbsoluteLayout");
+        al.setWidth("300px");
+        al.setHeight("200px");
+        al.addComponent(tf(false), "top:30px");
+        al.addComponent(tf(true), "top: 100px");
+        layouts.addComponent(al);
+    }
+
+    private void createComponents(VerticalLayout components) {
+        createComponent(components, Button.class);
+        createComponent(components, NativeButton.class);
+        createComponent(components, CheckBox.class);
+        createComponent(components, Link.class);
+
+        createComponent(components, Panel.class);
+        createComponent(components, ColorPicker.class);
+        createComponent(components, ColorPickerArea.class);
+        createComponent(components, Form.class);
+
+    }
+
+    private void createComponent(VerticalLayout components,
+            Class<? extends AbstractComponent> class1) {
+        AbstractComponent ac;
+        try {
+            ac = class1.newInstance();
+            ac.setCaption(getTextCaption(class1.getSimpleName()));
+            components.addComponent(ac);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        try {
+            ac = class1.newInstance();
+            ac.setCaption(getHtmlCaption(class1.getSimpleName()));
+            ac.setCaptionAsHtml(true);
+            components.addComponent(ac);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    private Component tf(boolean htmlCaption) {
+        TextField tf = new TextField();
+        if (htmlCaption) {
+            tf.setCaptionAsHtml(htmlCaption);
+            tf.setCaption(getHtmlCaption(""));
+        } else {
+            tf.setCaption(getTextCaption(""));
+        }
+        return tf;
+    }
+
+    private String getTextCaption(String string) {
+        return "<b>Plain text " + string + "</b>";
+    }
+
+    private String getHtmlCaption(String string) {
+        return "<b><font color='red'>HTML " + string + "</font></b>";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 9426;
+    }
+
+}