diff options
author | Henri Sara <henri.sara@itmill.com> | 2009-05-11 09:19:03 +0000 |
---|---|---|
committer | Henri Sara <henri.sara@itmill.com> | 2009-05-11 09:19:03 +0000 |
commit | adc8c0ad3573272c236040c3a76005b9e73a5737 (patch) | |
tree | a3860704dbd5b82dc6af38684b80f8ef79a32722 /src/com/vaadin/ui/CustomLayout.java | |
parent | 5abc870dda584d0c2fc47fd5eec4ae3de3fa240e (diff) | |
download | vaadin-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.java | 310 |
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."); + } + +} |