aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/ui/CustomLayout.java
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2009-05-11 09:19:03 +0000
committerHenri Sara <henri.sara@itmill.com>2009-05-11 09:19:03 +0000
commitadc8c0ad3573272c236040c3a76005b9e73a5737 (patch)
treea3860704dbd5b82dc6af38684b80f8ef79a32722 /src/com/vaadin/ui/CustomLayout.java
parent5abc870dda584d0c2fc47fd5eec4ae3de3fa240e (diff)
downloadvaadin-framework-adc8c0ad3573272c236040c3a76005b9e73a5737.tar.gz
vaadin-framework-adc8c0ad3573272c236040c3a76005b9e73a5737.zip
#2904: initial bulk rename "com.itmill.toolkit" -> "com.vaadin"
- com.itmill.toolkit.external not yet fully renamed svn changeset:7715/svn branch:6.0
Diffstat (limited to 'src/com/vaadin/ui/CustomLayout.java')
-rw-r--r--src/com/vaadin/ui/CustomLayout.java310
1 files changed, 310 insertions, 0 deletions
diff --git a/src/com/vaadin/ui/CustomLayout.java b/src/com/vaadin/ui/CustomLayout.java
new file mode 100644
index 0000000000..6ec7986a29
--- /dev/null
+++ b/src/com/vaadin/ui/CustomLayout.java
@@ -0,0 +1,310 @@
+/*
+@ITMillApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.vaadin.terminal.PaintException;
+import com.vaadin.terminal.PaintTarget;
+
+/**
+ * <p>
+ * A container component with freely designed layout and style. The layout
+ * consists of items with textually represented locations. Each item contains
+ * one sub-component, which can be any Toolkit component, such as a layout. The
+ * adapter and theme are responsible for rendering the layout with a given style
+ * by placing the items in the defined locations.
+ * </p>
+ *
+ * <p>
+ * The placement of the locations is not fixed - different themes can define the
+ * locations in a way that is suitable for them. One typical example would be to
+ * create visual design for a web site as a custom layout: the visual design
+ * would define locations for "menu", "body", and "title", for example. The
+ * layout would then be implemented as an XHTML template for each theme.
+ * </p>
+ *
+ * <p>
+ * The default theme handles the styles that are not defined by drawing the
+ * subcomponents just as in OrderedLayout.
+ * </p>
+ *
+ * @author IT Mill Ltd.
+ * @version
+ * @VERSION@
+ * @since 3.0
+ */
+@SuppressWarnings("serial")
+public class CustomLayout extends AbstractLayout {
+
+ private static final int BUFFER_SIZE = 10000;
+
+ /**
+ * Custom layout slots containing the components.
+ */
+ private final HashMap slots = new HashMap();
+
+ private String templateContents = null;
+
+ private String templateName = null;
+
+ /**
+ * Constructs a custom layout with the template given in the stream.
+ *
+ * @param templateStream
+ * Stream containing template data. Must be using UTF-8 encoding.
+ * To use a String as a template use for instance new
+ * ByteArrayInputStream("<template>".getBytes()).
+ * @param streamLength
+ * Length of the templateStream
+ * @throws IOException
+ */
+ public CustomLayout(InputStream templateStream) throws IOException {
+
+ InputStreamReader reader = new InputStreamReader(templateStream,
+ "UTF-8");
+ StringBuffer b = new StringBuffer(BUFFER_SIZE);
+
+ char[] cbuf = new char[BUFFER_SIZE];
+ int offset = 0;
+
+ while (true) {
+ int nrRead = reader.read(cbuf, offset, BUFFER_SIZE);
+ b.append(cbuf, 0, nrRead);
+ if (nrRead < BUFFER_SIZE) {
+ break;
+ }
+ }
+
+ templateContents = b.toString();
+ setWidth(100, UNITS_PERCENTAGE);
+ }
+
+ /**
+ * Constructor for custom layout with given template name. Template file is
+ * fetched from "<theme>/layout/<templateName>".
+ */
+ public CustomLayout(String template) {
+ templateName = template;
+ setWidth(100, UNITS_PERCENTAGE);
+ }
+
+ /**
+ * Gets the component UIDL tag.
+ *
+ * @return the Component UIDL tag as string.
+ */
+ @Override
+ public String getTag() {
+ return "customlayout";
+ }
+
+ /**
+ * Adds the component into this container to given location. If the location
+ * is already populated, the old component is removed.
+ *
+ * @param c
+ * the component to be added.
+ * @param location
+ * the location of the component.
+ */
+ public void addComponent(Component c, String location) {
+ final Component old = (Component) slots.get(location);
+ if (old != null) {
+ removeComponent(old);
+ }
+ slots.put(location, c);
+ c.setParent(this);
+ fireComponentAttachEvent(c);
+ requestRepaint();
+ }
+
+ /**
+ * Adds the component into this container. The component is added without
+ * specifying the location (empty string is then used as location). Only one
+ * component can be added to the default "" location and adding more
+ * components into that location overwrites the old components.
+ *
+ * @param c
+ * the component to be added.
+ */
+ @Override
+ public void addComponent(Component c) {
+ this.addComponent(c, "");
+ }
+
+ /**
+ * Removes the component from this container.
+ *
+ * @param c
+ * the component to be removed.
+ */
+ @Override
+ public void removeComponent(Component c) {
+ if (c == null) {
+ return;
+ }
+ slots.values().remove(c);
+ c.setParent(null);
+ fireComponentDetachEvent(c);
+ requestRepaint();
+ }
+
+ /**
+ * Removes the component from this container from given location.
+ *
+ * @param location
+ * the Location identifier of the component.
+ */
+ public void removeComponent(String location) {
+ this.removeComponent((Component) slots.get(location));
+ }
+
+ /**
+ * Gets the component container iterator for going trough all the components
+ * in the container.
+ *
+ * @return the Iterator of the components inside the container.
+ */
+ public Iterator getComponentIterator() {
+ return slots.values().iterator();
+ }
+
+ /**
+ * Gets the child-component by its location.
+ *
+ * @param location
+ * the name of the location where the requested component
+ * resides.
+ * @return the Component in the given location or null if not found.
+ */
+ public Component getComponent(String location) {
+ return (Component) slots.get(location);
+ }
+
+ /**
+ * Paints the content of this component.
+ *
+ * @param target
+ * @throws PaintException
+ * if the paint operation failed.
+ */
+ @Override
+ public void paintContent(PaintTarget target) throws PaintException {
+ super.paintContent(target);
+
+ if (templateName != null) {
+ target.addAttribute("template", templateName);
+ } else {
+ target.addAttribute("templateContents", templateContents);
+ }
+ // Adds all items in all the locations
+ for (final Iterator i = slots.keySet().iterator(); i.hasNext();) {
+ // Gets the (location,component)
+ final String location = (String) i.next();
+ final Component c = (Component) slots.get(location);
+ if (c != null) {
+ // Writes the item
+ target.startTag("location");
+ target.addAttribute("name", location);
+ c.paint(target);
+ target.endTag("location");
+ }
+ }
+ }
+
+ /* Documented in superclass */
+ public void replaceComponent(Component oldComponent, Component newComponent) {
+
+ // Gets the locations
+ String oldLocation = null;
+ String newLocation = null;
+ for (final Iterator i = slots.keySet().iterator(); i.hasNext();) {
+ final String location = (String) i.next();
+ final Component component = (Component) slots.get(location);
+ if (component == oldComponent) {
+ oldLocation = location;
+ }
+ if (component == newComponent) {
+ newLocation = location;
+ }
+ }
+
+ if (oldLocation == null) {
+ addComponent(newComponent);
+ } else if (newLocation == null) {
+ removeComponent(oldLocation);
+ addComponent(newComponent, oldLocation);
+ } else {
+ slots.put(newLocation, oldComponent);
+ slots.put(oldLocation, newComponent);
+ requestRepaint();
+ }
+ }
+
+ /**
+ * CustomLayout's template selecting was previously implemented with
+ * setStyle. Overriding to improve backwards compatibility.
+ *
+ * @param name
+ * template name
+ */
+ @Override
+ public void setStyle(String name) {
+ setTemplateName(name);
+ }
+
+ /** Get the name of the template */
+ public String getTemplateName() {
+ return templateName;
+ }
+
+ /**
+ * Set the name of the template used to draw custom layout.
+ *
+ * With GWT-adapter, the template with name 'templatename' is loaded from
+ * ITMILL/themes/themename/layouts/templatename.html. If the theme has not
+ * been set (with Application.setTheme()), themename is 'default'.
+ *
+ * @param templateName
+ */
+ public void setTemplateName(String templateName) {
+ this.templateName = templateName;
+ templateContents = null;
+ requestRepaint();
+ }
+
+ /**
+ * Although most layouts support margins, CustomLayout does not. The
+ * behaviour of this layout is determined almost completely by the actual
+ * template.
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public void setMargin(boolean enabled) {
+ throw new UnsupportedOperationException(
+ "CustomLayout does not support margins.");
+ }
+
+ /**
+ * Although most layouts support margins, CustomLayout does not. The
+ * behaviour of this layout is determined almost completely by the actual
+ * template.
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public void setMargin(boolean topEnabled, boolean rightEnabled,
+ boolean bottomEnabled, boolean leftEnabled) {
+ throw new UnsupportedOperationException(
+ "CustomLayout does not support margins.");
+ }
+
+}