]> source.dussan.org Git - vaadin-framework.git/commitdiff
Integrated filter select features. Fixed #41
authorJoonas Lehtinen <joonas.lehtinen@itmill.com>
Wed, 31 Jan 2007 18:54:58 +0000 (18:54 +0000)
committerJoonas Lehtinen <joonas.lehtinen@itmill.com>
Wed, 31 Jan 2007 18:54:58 +0000 (18:54 +0000)
svn changeset:393/svn branch:toolkit

src/com/itmill/toolkit/demo/features/FeatureSelect.java
src/com/itmill/toolkit/demo/features/PropertyPanel.java
src/com/itmill/toolkit/ui/Select.java
src/com/itmill/toolkit/ui/Table.java
src/com/itmill/toolkit/ui/Tree.java

index 721b833503a5631a4d95cf179962da37dfdf144b..463cb06b1164f9f87224e938f96aea2f78674e64 100644 (file)
@@ -32,6 +32,45 @@ import com.itmill.toolkit.ui.*;
 
 public class FeatureSelect extends Feature {
 
+       private static final String[] firstnames =
+               new String[] {
+                       "John",
+                       "Mary",
+                       "Joe",
+                       "Sarah",
+                       "Jeff",
+                       "Jane",
+                       "Peter",
+                       "Marc",
+                       "Robert",
+                       "Paula",
+                       "Lenny",
+                       "Kenny",
+                       "Nathan",
+                       "Nicole",
+                       "Laura",
+                       "Jos\8e",
+                       "Josie",
+                       "Linus" };
+       private static final String[] lastnames =
+               new String[] {
+                       "Torvalds",
+                       "Smith",
+                       "Adams",
+                       "Black",
+                       "Wilson",
+                       "Richards",
+                       "Thompson",
+                       "McGoff",
+                       "Halas",
+                       "Jones",
+                       "Beck",
+                       "Sheridan",
+                       "Picard",
+                       "Hill",
+                       "Fielding",
+                       "Einstein" };
+       
        public FeatureSelect() {
                super();
        }
@@ -42,11 +81,10 @@ public class FeatureSelect extends Feature {
 
                // Example panel
                Panel show = new Panel("Select component");
-               Select s = new Select("Select Car");
-               s.addItem("Audi");
-               s.addItem("BMW");
-               s.addItem("Chrysler");
-               s.addItem("Volvo");
+               Select s = new Select("Select Person");
+               for (int i=0; i<1000; i++)
+                       s.addItem(firstnames[(int) (Math.random() * (firstnames.length-1))] + " " +
+                                       lastnames[(int) (Math.random() * (lastnames.length-1))]);
                show.addComponent(s);
                l.addComponent(show);
 
@@ -62,7 +100,7 @@ public class FeatureSelect extends Feature {
                        .getItemProperty(themes.getItemCaptionPropertyId())
                        .setValue("twincol");
                l.addComponent(p);
-
+               
                return l;
        }
 
index ade6effe54242ebb13a1b55f9d289268594d1116..e7f60996175d979d798c75c4997cf1613471c559 100644 (file)
@@ -38,6 +38,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 
 import com.itmill.toolkit.data.*;
+import com.itmill.toolkit.data.Property.ValueChangeListener;
 import com.itmill.toolkit.data.util.*;
 import com.itmill.toolkit.terminal.*;
 import com.itmill.toolkit.ui.*;
@@ -300,7 +301,7 @@ public class PropertyPanel
        private void addSelectProperties() {
                Form set =
                        createBeanPropertySet(
-                               new String[] { "multiSelect", "newItemsAllowed" });
+                               new String[] {  "newItemsAllowed", "lazyLoading" ,"multiSelect"});
                addProperties("Select Properties", set);
 
                set.getField("multiSelect").setDescription(
@@ -309,9 +310,19 @@ public class PropertyPanel
                        "Select component (but not Tree or Table) can allow the user to directly "
                                + "add new items to set of options. The new items are constrained to be "
                                + "strings and thus feature only applies to simple lists.");
+               Button ll = (Button) set.getField("lazyLoading");
+               ll.setDescription("In Ajax rendering mode select supports lazy loading and filtering of options.");
+               ll.addListener((ValueChangeListener)this);
+               ll.setImmediate(true);
+               if (((Boolean)ll.getValue()).booleanValue()) {
+                       set.getField("multiSelect").setVisible(false);
+                       set.getField("newItemsAllowed").setVisible(false);
+               }
                if (objectToConfigure instanceof Tree
-                       || objectToConfigure instanceof Table)
-                       set.removeItemProperty("newItemsAllowed");
+                               || objectToConfigure instanceof Table) {
+                               set.removeItemProperty("newItemsAllowed");
+                               set.removeItemProperty("lazyLoading");
+               }
        }
 
        /** Field special properties */
@@ -415,6 +426,19 @@ public class PropertyPanel
 
                                addComponent.setValue(null);
                        }
+               } else if (event.getProperty() == getField("lazyLoading")) {
+                       boolean newValue = ((Boolean)event.getProperty().getValue()).booleanValue();
+                       Field multiselect = getField("multiSelect");
+                       Field newitems = getField("newItemsAllowed");
+                       if (newValue) {
+                               newitems.setValue(Boolean.FALSE);
+                               newitems.setVisible(false);
+                               multiselect.setValue(Boolean.FALSE);
+                               multiselect.setVisible(false);
+                       } else {
+                               newitems.setVisible(true);
+                               multiselect.setVisible(true);
+                       }
                }
        }
 
index ac1b5221bab9000f66cb5ce7031012b71c6692a6..dc8a41e7cc89b29454d78a29a3c49c1b0ce91979 100644 (file)
@@ -1,33 +1,42 @@
 /* *************************************************************************
  
                              IT Mill Toolkit 
+ IT Mill Toolkit 
 
              Development of Browser User Interfaces Made Easy
+ Development of Browser User Interfaces Made Easy
 
                   Copyright (C) 2000-2006 IT Mill Ltd
-                     
  *************************************************************************
+ Copyright (C) 2000-2006 IT Mill Ltd
+ *************************************************************************
 
  This product is distributed under commercial license that can be found
  from the product package on license.pdf. Use of this product might 
  require purchasing a commercial license from IT Mill Ltd. For guidelines 
  on usage, see licensing-guidelines.html
+ This product is distributed under commercial license that can be found
+ from the product package on license.pdf. Use of this product might 
+ require purchasing a commercial license from IT Mill Ltd. For guidelines 
+ on usage, see licensing-guidelines.html
 
  *************************************************************************
-   
  For more information, contact:
-   
  IT Mill Ltd                           phone: +358 2 4802 7180
  Ruukinkatu 2-4                        fax:   +358 2 4802 7181
  20540, Turku                          email:  info@itmill.com
  Finland                               company www: www.itmill.com
-   
  Primary source for information and releases: www.itmill.com
+ *************************************************************************
+ For more information, contact:
+ IT Mill Ltd                           phone: +358 2 4802 7180
+ Ruukinkatu 2-4                        fax:   +358 2 4802 7181
+ 20540, Turku                          email:  info@itmill.com
+ Finland                               company www: www.itmill.com
+ Primary source for information and releases: www.itmill.com
 
  ********************************************************************** */
+ ********************************************************************** */
 
 package com.itmill.toolkit.ui;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -41,66 +50,75 @@ import com.itmill.toolkit.data.Container;
 import com.itmill.toolkit.data.Item;
 import com.itmill.toolkit.data.Property;
 import com.itmill.toolkit.data.util.IndexedContainer;
+import com.itmill.toolkit.terminal.DownloadStream;
 import com.itmill.toolkit.terminal.KeyMapper;
 import com.itmill.toolkit.terminal.PaintException;
 import com.itmill.toolkit.terminal.PaintTarget;
 import com.itmill.toolkit.terminal.Resource;
-
-/** <p>A class representing a selection of items the user has selected in a
- * UI. The set of choices is presented as a set of
- * {@link com.itmill.toolkit.data.Item}s in a 
- * {@link com.itmill.toolkit.data.Container}.</p>
+import com.itmill.toolkit.terminal.URIHandler;
+
+/**
+ * <p>
+ * A class representing a selection of items the user has selected in a UI. The
+ * set of choices is presented as a set of {@link com.itmill.toolkit.data.Item}s
+ * in a {@link com.itmill.toolkit.data.Container}.
+ * </p>
  * 
- * <p>A <code>Select</code> component may be in single- or multiselect mode.
+ * <p>
+ * A <code>Select</code> component may be in single- or multiselect mode.
  * Multiselect mode means that more than one item can be selected
- * simultaneously.</p>
- *
+ * simultaneously.
+ * </p>
+ * 
  * @author IT Mill Ltd.
- * @version @VERSION@
+ * @version
+ * @VERSION@
  * @since 3.0
  */
-public class Select
-       extends AbstractField
-       implements
-               Container,
-               Container.Viewer,
-               Container.PropertySetChangeListener,
-               Container.PropertySetChangeNotifier,
-               Container.ItemSetChangeNotifier,
+public class Select extends AbstractField implements Container,
+               Container.Viewer, Container.PropertySetChangeListener,
+               Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier,
                Container.ItemSetChangeListener {
 
-       /** Item caption mode: Item's ID's <code>String</code> representation
-        * is used as caption.
+       /**
+        * Item caption mode: Item's ID's <code>String</code> representation is
+        * used as caption.
         */
        public static final int ITEM_CAPTION_MODE_ID = 0;
 
-       /** Item caption mode: Item's <code>String</code> representation is
-        * used as caption.
+       /**
+        * Item caption mode: Item's <code>String</code> representation is used as
+        * caption.
         */
        public static final int ITEM_CAPTION_MODE_ITEM = 1;
 
-       /** Item caption mode: Index of the item is used as caption. The
-        * index mode can only be used with the containers implementing the
+       /**
+        * Item caption mode: Index of the item is used as caption. The index mode
+        * can only be used with the containers implementing the
         * {@link com.itmill.toolkit.data.Container.Indexed} interface.
         */
        public static final int ITEM_CAPTION_MODE_INDEX = 2;
 
-       /** Item caption mode: If an Item has a caption it's used, if not,
-        * Item's ID's <code>String</code> representation is used as caption.
-        * <b>This is the default</b>.
+       /**
+        * Item caption mode: If an Item has a caption it's used, if not, Item's
+        * ID's <code>String</code> representation is used as caption. <b>This is
+        * the default</b>.
         */
        public static final int ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID = 3;
 
-       /** Item caption mode: Captions must be explicitly specified.
+       /**
+        * Item caption mode: Captions must be explicitly specified.
         */
        public static final int ITEM_CAPTION_MODE_EXPLICIT = 4;
 
-       /** Item caption mode: Only icons are shown, captions are hidden.
+       /**
+        * Item caption mode: Only icons are shown, captions are hidden.
         */
        public static final int ITEM_CAPTION_MODE_ICON_ONLY = 5;
 
-       /** Item caption mode: Item captions are read from property specified 
-        * with <code>setItemCaptionPropertyId</code>.
+       /**
+        * Item caption mode: Item captions are read from property specified with
+        * <code>setItemCaptionPropertyId</code>.
         */
        public static final int ITEM_CAPTION_MODE_PROPERTY = 6;
 
@@ -137,44 +155,66 @@ public class Select
        /** List of item set change event listeners */
        private LinkedList itemSetEventListeners = null;
 
-       /** Item id that represents null selection of this select.
+       /**
+        * Item id that represents null selection of this select.
         * 
-        * <p>Data interface does not support nulls as item ids. Selecting the item idetified 
-        * by this id is the same as selecting no items at all. This setting only affects the
-        * single select mode.</p>
+        * <p>
+        * Data interface does not support nulls as item ids. Selecting the item
+        * idetified by this id is the same as selecting no items at all. This
+        * setting only affects the single select mode.
+        * </p>
         */
        private Object nullSelectionItemId = null;
 
+       /** Mechanism for streaming select options outside of the UIDL.
+        * 
+        * By default streaming is not enabled and this is null. Streaming can 
+        * be enabled with setOptionsLoadingLazy(true). 
+        *  
+        */
+       private OptionsStream optionsStream = null;
+
        /* Constructors ********************************************************* */
 
-       /** Creates an empty Select.
-        * The caption is not used.
+       /**
+        * Creates an empty Select. The caption is not used.
         */
        public Select() {
                setContainerDataSource(new IndexedContainer());
        }
 
-       /** Creates an empty Select with caption.
+       /**
+        * Creates an empty Select with caption.
         */
        public Select(String caption) {
                setContainerDataSource(new IndexedContainer());
                setCaption(caption);
        }
 
-       /** Creates a new select wthat is connected to a data-source.
-        * @param dataSource Container datasource to be selected from by this select.
-        * @param caption Caption of the component.
-        * @param selected Selected item id or null, if none selected.
+       /**
+        * Creates a new select wthat is connected to a data-source.
+        * 
+        * @param dataSource
+        *            Container datasource to be selected from by this select.
+        * @param caption
+        *            Caption of the component.
+        * @param selected
+        *            Selected item id or null, if none selected.
         */
        public Select(String caption, Container dataSource) {
                setCaption(caption);
                setContainerDataSource(dataSource);
        }
 
-       /** Creates a new select that is filled from a collection of option values.
-        * @param caption Caption of this field.
-        * @param options Collection containing the options.
-        * @param selected Selected option or null, if none selected.
+       /**
+        * Creates a new select that is filled from a collection of option values.
+        * 
+        * @param caption
+        *            Caption of this field.
+        * @param options
+        *            Collection containing the options.
+        * @param selected
+        *            Selected option or null, if none selected.
         */
        public Select(String caption, Collection options) {
 
@@ -190,9 +230,13 @@ public class Select
 
        /* Component methods **************************************************** */
 
-       /** Paint the content of this component.
-        * @param event PaintEvent.
-        * @throws PaintException The paint operation failed.
+       /**
+        * Paint the content of this component.
+        * 
+        * @param event
+        *            PaintEvent.
+        * @throws PaintException
+        *             The paint operation failed.
         */
        public void paintContent(PaintTarget target) throws PaintException {
 
@@ -205,65 +249,78 @@ public class Select
                if (isNewItemsAllowed())
                        target.addAttribute("allownewitem", true);
 
-               // Paint options and create array of selected id keys
+               // Construct selected keys array
                String[] selectedKeys;
                if (isMultiSelect())
                        selectedKeys = new String[((Set) getValue()).size()];
                else
-                       selectedKeys =
-                               new String[(
-                                       getValue() == null
-                                               && getNullSelectionItemId() == null ? 0 : 1)];
-               int keyIndex = 0;
+                       selectedKeys = new String[(getValue() == null
+                                       && getNullSelectionItemId() == null ? 0 : 1)];
+               String[] selectedCaptions;
+               selectedCaptions = new String[selectedKeys.length];
+               
+               // Paint options and create array of selected id keys
                target.startTag("options");
-
-               // Support for external null selection item id
-               Collection ids = getItemIds();
-               if (getNullSelectionItemId() != null
-                       && (!ids.contains(getNullSelectionItemId()))) {
-                               
-                       // Get the option attribute values
-                       Object id = getNullSelectionItemId();
-                       String key = itemIdMapper.key(id);
-                       String caption = getItemCaption(id);
-                       Resource icon = getItemIcon(id);
-
-                       // Paint option
-                       target.startTag("so");
-                       if (icon != null)
-                               target.addAttribute("icon", icon);
-                       target.addAttribute("caption", caption);
-                       target.addAttribute("nullselection", true);
-                       target.addAttribute("key", key);
-                       if (isSelected(id)) {
-                               target.addAttribute("selected", true);
-                               selectedKeys[keyIndex++] = key;
+               if (!isLazyLoading()) {
+                       int keyIndex = 0;
+
+                       // Support for external null selection item id
+                       Collection ids = getItemIds();
+                       if (getNullSelectionItemId() != null
+                                       && (!ids.contains(getNullSelectionItemId()))) {
+
+                               // Get the option attribute values
+                               Object id = getNullSelectionItemId();
+                               String key = itemIdMapper.key(id);
+                               String caption = getItemCaption(id);
+                               Resource icon = getItemIcon(id);
+
+                               // Paint option
+                               target.startTag("so");
+                               if (icon != null)
+                                       target.addAttribute("icon", icon);
+                               target.addAttribute("caption", caption);
+                               target.addAttribute("nullselection", true);
+                               target.addAttribute("key", key);
+                               if (isSelected(id)) {
+                                       target.addAttribute("selected", true);
+                                       selectedKeys[keyIndex++] = key;
+                               }
+                               target.endTag("so");
                        }
-                       target.endTag("so");
-               }
 
-               // Paint available selection options from data source
-               for (Iterator i = getItemIds().iterator(); i.hasNext();) {
-
-                       // Get the option attribute values
-                       Object id = i.next();
-                       String key = itemIdMapper.key(id);
-                       String caption = getItemCaption(id);
-                       Resource icon = getItemIcon(id);
-
-                       // Paint option
-                       target.startTag("so");
-                       if (icon != null)
-                               target.addAttribute("icon", icon);
-                       target.addAttribute("caption", caption);
-                       if (id != null && id.equals(getNullSelectionItemId()))
-                               target.addAttribute("nullselection", true);
-                       target.addAttribute("key", key);
-                       if (isSelected(id) && keyIndex < selectedKeys.length) {
-                               target.addAttribute("selected", true);
-                               selectedKeys[keyIndex++] = key;
+                       // Paint available selection options from data source
+                       for (Iterator i = getItemIds().iterator(); i.hasNext();) {
+
+                               // Get the option attribute values
+                               Object id = i.next();
+                               String key = itemIdMapper.key(id);
+                               String caption = getItemCaption(id);
+                               Resource icon = getItemIcon(id);
+
+                               // Paint option
+                               target.startTag("so");
+                               if (icon != null)
+                                       target.addAttribute("icon", icon);
+                               target.addAttribute("caption", caption);
+                               if (id != null && id.equals(getNullSelectionItemId()))
+                                       target.addAttribute("nullselection", true);
+                               target.addAttribute("key", key);
+                               if (isSelected(id) && keyIndex < selectedKeys.length) {
+                                       target.addAttribute("selected", true);
+                                       selectedKeys[keyIndex++] = key;
+                               }
+                               target.endTag("so");
                        }
-                       target.endTag("so");
+               } else {
+
+                       // Lazy options loading
+                       target.addAttribute("loadfrom", getApplication().getURL().toString()
+                                       + optionsStream.uri);
+                       target.addAttribute("total", (getItemIds() != null) ? getItemIds()
+                                       .size() : 0);
+                       target.addAttribute("initial", optionsStream.getJSON(20,0,""));
+                       target.addAttribute("selectedValue", toString() == null ? "" : toString());
                }
                target.endTag("options");
 
@@ -273,9 +330,12 @@ public class Select
                        target.addVariable(this, "newitem", "");
        }
 
-       /** Invoked when the value of a variable has changed.
-        * @param event Variable change event containing the information about
-        * the changed variable.
+       /**
+        * Invoked when the value of a variable has changed.
+        * 
+        * @param event
+        *            Variable change event containing the information about the
+        *            changed variable.
         */
        public void changeVariables(Object source, Map variables) {
 
@@ -295,13 +355,12 @@ public class Select
                                // Set the caption property, if used
                                if (getItemCaptionPropertyId() != null)
                                        try {
-                                               getContainerProperty(
-                                                       newitem,
-                                                       getItemCaptionPropertyId()).setValue(
-                                                       newitem);
+                                               getContainerProperty(newitem,
+                                                               getItemCaptionPropertyId()).setValue(newitem);
                                        } catch (Property.ConversionException ignored) {
-                                               // The conversion exception is safely ignored, the caption is
-                                               // just missing 
+                                               // The conversion exception is safely ignored, the
+                                               // caption is
+                                               // just missing
                                        }
                        }
                }
@@ -319,9 +378,7 @@ public class Select
                                        Object id = itemIdMapper.get(ka[i]);
                                        if (id != null && containsId(id))
                                                s.add(id);
-                                       else if (
-                                               itemIdMapper.isNewIdKey(ka[i])
-                                                       && newitem != null
+                                       else if (itemIdMapper.isNewIdKey(ka[i]) && newitem != null
                                                        && newitem.length() > 0)
                                                s.add(newitem);
                                }
@@ -363,15 +420,18 @@ public class Select
                }
        }
 
-       /** Get component UIDL tag.
+       /**
+        * Get component UIDL tag.
+        * 
         * @return Component UIDL tag as string.
         */
        public String getTag() {
                return "select";
        }
 
-       /** Get the visible item ids. In Select, this returns list of all item ids, 
-        * but can be overriden in subclasses if they paint only part of the items 
+       /**
+        * Get the visible item ids. In Select, this returns list of all item ids,
+        * but can be overriden in subclasses if they paint only part of the items
         * to the terminal or null if no items is visible.
         */
        public Collection getVisibleItemIds() {
@@ -382,10 +442,12 @@ public class Select
 
        /* Property methods ***************************************************** */
 
-       /** Return the type of the property.
-        * getValue and setValue functions must be compatible with this type:
-        * one can safely cast getValue() to given type and pass any variable
-        * assignable to this type as a parameter to setValue().
+       /**
+        * Return the type of the property. getValue and setValue functions must be
+        * compatible with this type: one can safely cast getValue() to given type
+        * and pass any variable assignable to this type as a parameter to
+        * setValue().
+        * 
         * @return type Type of the property.
         */
        public Class getType() {
@@ -395,7 +457,8 @@ public class Select
                        return Object.class;
        }
 
-       /** Get the selected item id or in multiselect mode a set of selected ids.
+       /**
+        * Get the selected item id or in multiselect mode a set of selected ids.
         */
        public Object getValue() {
                Object retValue = super.getValue();
@@ -406,9 +469,9 @@ public class Select
                        if (retValue == null)
                                return new HashSet();
                        if (retValue instanceof Set) {
-                               return Collections.unmodifiableSet((Set) retValue);                                                             
+                               return Collections.unmodifiableSet((Set) retValue);
                        } else if (retValue instanceof Collection) {
-                                       return new HashSet((Collection)retValue);                                                               
+                               return new HashSet((Collection) retValue);
                        } else {
                                Set s = new HashSet();
                                if (items.containsId(retValue))
@@ -420,16 +483,20 @@ public class Select
                        return retValue;
        }
 
-       /** Set the visible value of the property.
-        *
-        * <p>The value of the select is the selected item id. If the select is in 
-        * multiselect-mode, the value is a set of selected item keys. In multiselect
-        * mode all collections of id:s can be assigned.</p>
+       /**
+        * Set the visible value of the property.
         * 
-        * @param newValue New selected item or collection of selected items.
+        * <p>
+        * The value of the select is the selected item id. If the select is in
+        * multiselect-mode, the value is a set of selected item keys. In
+        * multiselect mode all collections of id:s can be assigned.
+        * </p>
+        * 
+        * @param newValue
+        *            New selected item or collection of selected items.
         */
-       public void setValue(Object newValue)
-               throws Property.ReadOnlyException, Property.ConversionException {
+       public void setValue(Object newValue) throws Property.ReadOnlyException,
+                       Property.ConversionException {
 
                if (isMultiSelect()) {
                        if (newValue == null)
@@ -442,43 +509,56 @@ public class Select
 
        /* Container methods **************************************************** */
 
-       /** Get the item from the container with given id.
-        * If the container does not contain the requested item, null is returned.
+       /**
+        * Get the item from the container with given id. If the container does not
+        * contain the requested item, null is returned.
         */
        public Item getItem(Object itemId) {
                return items.getItem(itemId);
        }
 
-       /** Get item Id collection from the container.
+       /**
+        * Get item Id collection from the container.
+        * 
         * @return Collection of item ids.
         */
        public Collection getItemIds() {
                return items.getItemIds();
        }
 
-       /** Get property Id collection from the container.
+       /**
+        * Get property Id collection from the container.
+        * 
         * @return Collection of property ids.
         */
        public Collection getContainerPropertyIds() {
                return items.getContainerPropertyIds();
        }
 
-       /** Get property type.
-        * @param id Id identifying the of the property.
+       /**
+        * Get property type.
+        * 
+        * @param id
+        *            Id identifying the of the property.
         */
        public Class getType(Object propertyId) {
                return items.getType(propertyId);
        }
 
-       /** Get the number of items in the container.
+       /**
+        * Get the number of items in the container.
+        * 
         * @return Number of items in the container.
         */
        public int size() {
                return items.size();
        }
 
-       /** Test, if the collection contains an item with given id.
-        * @param itemId Id the of item to be tested.
+       /**
+        * Test, if the collection contains an item with given id.
+        * 
+        * @param itemId
+        *            Id the of item to be tested.
         */
        public boolean containsId(Object itemId) {
                if (itemId != null)
@@ -488,7 +568,8 @@ public class Select
        }
 
        /**
-        * @see com.itmill.toolkit.data.Container#getContainerProperty(Object, Object)
+        * @see com.itmill.toolkit.data.Container#getContainerProperty(Object,
+        *      Object)
         */
        public Property getContainerProperty(Object itemId, Object propertyId) {
                return items.getContainerProperty(itemId, propertyId);
@@ -496,35 +577,32 @@ public class Select
 
        /* Container.Managed methods ******************************************** */
 
-       /** Add new property to all items.
-        * Adds a property with given id, type and default value to all items
-        * in the container.
-        *
+       /**
+        * Add new property to all items. Adds a property with given id, type and
+        * default value to all items in the container.
+        * 
         * This functionality is optional. If the function is unsupported, it always
         * returns false.
-        *
+        * 
         * @return True iff the operation succeeded.
         */
-       public boolean addContainerProperty(
-               Object propertyId,
-               Class type,
-               Object defaultValue)
-               throws UnsupportedOperationException {
-
-               boolean retval =
-                       items.addContainerProperty(propertyId, type, defaultValue);
-               if (retval
-                       && !(items instanceof Container.PropertySetChangeNotifier)) {
+       public boolean addContainerProperty(Object propertyId, Class type,
+                       Object defaultValue) throws UnsupportedOperationException {
+
+               boolean retval = items.addContainerProperty(propertyId, type,
+                               defaultValue);
+               if (retval && !(items instanceof Container.PropertySetChangeNotifier)) {
                        firePropertySetChange();
                }
                return retval;
        }
 
-       /** Remove all items from the container.
-        *
+       /**
+        * Remove all items from the container.
+        * 
         * This functionality is optional. If the function is unsupported, it always
         * returns false.
-        *
+        * 
         * @return True iff the operation succeeded.
         */
        public boolean removeAllItems() throws UnsupportedOperationException {
@@ -539,50 +617,53 @@ public class Select
                return retval;
        }
 
-       /** Create a new item into container with container managed id.
-        * The id of the created new item is returned. The item can be fetched with
-        * getItem() method.
-        * if the creation fails, null is returned.
-        *
+       /**
+        * Create a new item into container with container managed id. The id of the
+        * created new item is returned. The item can be fetched with getItem()
+        * method. if the creation fails, null is returned.
+        * 
         * @return Id of the created item or null in case of failure.
         */
        public Object addItem() throws UnsupportedOperationException {
 
                Object retval = items.addItem();
                if (retval != null
-                       && !(items instanceof Container.ItemSetChangeNotifier))
+                               && !(items instanceof Container.ItemSetChangeNotifier))
                        fireItemSetChange();
                return retval;
        }
 
-       /** Create a new item into container.
-        * The created new item is returned and ready for setting property values.
-        * if the creation fails, null is returned. In case the container already
-        * contains the item, null is returned.
-        *
+       /**
+        * Create a new item into container. The created new item is returned and
+        * ready for setting property values. if the creation fails, null is
+        * returned. In case the container already contains the item, null is
+        * returned.
+        * 
         * This functionality is optional. If the function is unsupported, it always
         * returns null.
-        *
-        * @param itemId Identification of the item to be created.
+        * 
+        * @param itemId
+        *            Identification of the item to be created.
         * @return Created item with the given id, or null in case of failure.
         */
        public Item addItem(Object itemId) throws UnsupportedOperationException {
 
                Item retval = items.addItem(itemId);
                if (retval != null
-                       && !(items instanceof Container.ItemSetChangeNotifier))
+                               && !(items instanceof Container.ItemSetChangeNotifier))
                        fireItemSetChange();
                return retval;
        }
 
-       /** Remove item identified by Id from the container.
-        * This functionality is optional. If the function is not implemented,
-        * the functions allways returns false.
-        *
+       /**
+        * Remove item identified by Id from the container. This functionality is
+        * optional. If the function is not implemented, the functions allways
+        * returns false.
+        * 
         * @return True iff the operation succeeded.
         */
        public boolean removeItem(Object itemId)
-               throws UnsupportedOperationException {
+                       throws UnsupportedOperationException {
 
                unselect(itemId);
                boolean retval = items.removeItem(itemId);
@@ -592,16 +673,17 @@ public class Select
                return retval;
        }
 
-       /** Remove property from all items.
-        * Removes a property with given id from all the items in the container.
-        *
+       /**
+        * Remove property from all items. Removes a property with given id from all
+        * the items in the container.
+        * 
         * This functionality is optional. If the function is unsupported, it always
         * returns false.
-        *
+        * 
         * @return True iff the operation succeeded.
         */
        public boolean removeContainerProperty(Object propertyId)
-               throws UnsupportedOperationException {
+                       throws UnsupportedOperationException {
 
                boolean retval = items.removeContainerProperty(propertyId);
                if (retval && !(items instanceof Container.PropertySetChangeNotifier))
@@ -611,7 +693,7 @@ public class Select
 
        /* Container.Viewer methods ********************************************* */
 
-       /** Set the container as data-source for viewing.  */
+       /** Set the container as data-source for viewing. */
        public void setContainerDataSource(Container newDataSource) {
                if (newDataSource == null)
                        newDataSource = new IndexedContainer();
@@ -621,18 +703,14 @@ public class Select
                        // Remove listeners from the old datasource
                        if (items != null) {
                                try {
-                                       ((Container.ItemSetChangeNotifier) items).removeListener(
-                                               (Container.ItemSetChangeListener) this);
+                                       ((Container.ItemSetChangeNotifier) items)
+                                                       .removeListener((Container.ItemSetChangeListener) this);
                                } catch (ClassCastException ignored) {
                                        // Ignored
                                }
                                try {
-                                       (
-                                               (
-                                                       Container
-                                                               .PropertySetChangeNotifier) items)
-                                                               .removeListener(
-                                               (Container.PropertySetChangeListener) this);
+                                       ((Container.PropertySetChangeNotifier) items)
+                                                       .removeListener((Container.PropertySetChangeListener) this);
                                } catch (ClassCastException ignored) {
                                        // Ignored
                                }
@@ -643,53 +721,56 @@ public class Select
 
                        // Clear itemIdMapper also
                        this.itemIdMapper.removeAll();
-                       
+
                        // Add listeners
                        if (items != null) {
                                try {
-                                       ((Container.ItemSetChangeNotifier) items).addListener(
-                                               (Container.ItemSetChangeListener) this);
+                                       ((Container.ItemSetChangeNotifier) items)
+                                                       .addListener((Container.ItemSetChangeListener) this);
                                } catch (ClassCastException ignored) {
                                        // Ignored
                                }
                                try {
-                                       ((Container.PropertySetChangeNotifier) items).addListener(
-                                               (Container.PropertySetChangeListener) this);
+                                       ((Container.PropertySetChangeNotifier) items)
+                                                       .addListener((Container.PropertySetChangeListener) this);
                                } catch (ClassCastException ignored) {
                                        // Ignored
                                }
                        }
-                       //TODO: This should be conditional
+                       // TODO: This should be conditional
                        fireValueChange();
                }
        }
 
-       /** Get viewing data-source container.  */
+       /** Get viewing data-source container. */
        public Container getContainerDataSource() {
                return items;
        }
 
        /* Select attributes **************************************************** */
 
-       /** Is the select in multiselect mode? In multiselect mode
+       /**
+        * Is the select in multiselect mode? In multiselect mode
+        * 
         * @return Value of property multiSelect.
         */
        public boolean isMultiSelect() {
                return this.multiSelect;
        }
 
-       /** Set the multiselect mode.
-        * Setting multiselect mode false may loose selection information: if
-        * selected items set contains one or more selected items, only one of the
-        * selected items is kept as selected.
-        *
-        * @param multiSelect New value of property multiSelect.
+       /**
+        * Set the multiselect mode. Setting multiselect mode false may loose
+        * selection information: if selected items set contains one or more
+        * selected items, only one of the selected items is kept as selected.
+        * 
+        * @param multiSelect
+        *            New value of property multiSelect.
         */
        public void setMultiSelect(boolean multiSelect) {
 
                if (multiSelect != this.multiSelect) {
 
-                       // Selection before mode change         
+                       // Selection before mode change
                        Object oldValue = getValue();
 
                        this.multiSelect = multiSelect;
@@ -706,7 +787,7 @@ public class Select
                                        setValue(null);
                                else
 
-                                       // Set the single select to contain only the first 
+                                       // Set the single select to contain only the first
                                        // selected value in the multiselect
                                        setValue(s.iterator().next());
                        }
@@ -715,10 +796,12 @@ public class Select
                }
        }
 
-       /** Does the select allow adding new options by the user.
-        * If true, the new options can be added to the Container. The text entered
-        * by the user is used as id. No that data-source must allow adding new
-        * items (it must implement Container.Managed).
+       /**
+        * Does the select allow adding new options by the user. If true, the new
+        * options can be added to the Container. The text entered by the user is
+        * used as id. No that data-source must allow adding new items (it must
+        * implement Container.Managed).
+        * 
         * @return True iff additions are allowed.
         */
        public boolean isNewItemsAllowed() {
@@ -726,8 +809,11 @@ public class Select
                return this.allowNewOptions;
        }
 
-       /** Enable or disable possibility to add new options by the user.
-        * @param allowNewOptions New value of property allowNewOptions.
+       /**
+        * Enable or disable possibility to add new options by the user.
+        * 
+        * @param allowNewOptions
+        *            New value of property allowNewOptions.
         */
        public void setNewItemsAllowed(boolean allowNewOptions) {
 
@@ -740,11 +826,14 @@ public class Select
                }
        }
 
-       /** Override the caption of an item.
-        * Setting caption explicitly overrides id, item and index captions.
-        *
-        * @param itemId The id of the item to be recaptioned.
-        * @param caption New caption.
+       /**
+        * Override the caption of an item. Setting caption explicitly overrides id,
+        * item and index captions.
+        * 
+        * @param itemId
+        *            The id of the item to be recaptioned.
+        * @param caption
+        *            New caption.
         */
        public void setItemCaption(Object itemId, String caption) {
                if (itemId != null) {
@@ -753,11 +842,13 @@ public class Select
                }
        }
 
-       /** Get the caption of an item.
-        * The caption is generated as specified by the item caption mode. See
-        * <code>setItemCaptionMode()</code> for more details.
-        *
-        * @param itemId The id of the item to be queried.
+       /**
+        * Get the caption of an item. The caption is generated as specified by the
+        * item caption mode. See <code>setItemCaptionMode()</code> for more
+        * details.
+        * 
+        * @param itemId
+        *            The id of the item to be queried.
         * @return caption for specified item.
         */
        public String getItemCaption(Object itemId) {
@@ -770,51 +861,53 @@ public class Select
 
                switch (getItemCaptionMode()) {
 
-                       case ITEM_CAPTION_MODE_ID :
-                               caption = itemId.toString();
-                               break;
+               case ITEM_CAPTION_MODE_ID:
+                       caption = itemId.toString();
+                       break;
 
-                       case ITEM_CAPTION_MODE_INDEX :
-                               try {
-                                       caption =
-                                               String.valueOf(
-                                                       ((Container.Indexed) items).indexOfId(itemId));
-                               } catch (ClassCastException ignored) {
-                               }
-                               break;
-
-                       case ITEM_CAPTION_MODE_ITEM :
-                               Item i = getItem(itemId);
-                               if (i != null)
-                                       caption = i.toString();
-                               break;
-
-                       case ITEM_CAPTION_MODE_EXPLICIT :
-                               caption = (String) itemCaptions.get(itemId);
-                               break;
-
-                       case ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID :
-                               caption = (String) itemCaptions.get(itemId);
-                               if (caption == null)
-                                       caption = itemId.toString();
-                               break;
-
-                       case ITEM_CAPTION_MODE_PROPERTY :
-                               Property p =
-                                       getContainerProperty(itemId, getItemCaptionPropertyId());
-                               if (p != null)
-                                       caption = p.toString();
-                               break;
+               case ITEM_CAPTION_MODE_INDEX:
+                       try {
+                               caption = String.valueOf(((Container.Indexed) items)
+                                               .indexOfId(itemId));
+                       } catch (ClassCastException ignored) {
+                       }
+                       break;
+
+               case ITEM_CAPTION_MODE_ITEM:
+                       Item i = getItem(itemId);
+                       if (i != null)
+                               caption = i.toString();
+                       break;
+
+               case ITEM_CAPTION_MODE_EXPLICIT:
+                       caption = (String) itemCaptions.get(itemId);
+                       break;
+
+               case ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID:
+                       caption = (String) itemCaptions.get(itemId);
+                       if (caption == null)
+                               caption = itemId.toString();
+                       break;
+
+               case ITEM_CAPTION_MODE_PROPERTY:
+                       Property p = getContainerProperty(itemId,
+                                       getItemCaptionPropertyId());
+                       if (p != null)
+                               caption = p.toString();
+                       break;
                }
 
                // All items must have some captions
                return caption != null ? caption : "";
        }
 
-       /** Set icon for an item.
-        *
-        * @param itemId The id of the item to be assigned an icon.
-        * @param icon New icon.
+       /**
+        * Set icon for an item.
+        * 
+        * @param itemId
+        *            The id of the item to be assigned an icon.
+        * @param icon
+        *            New icon.
         */
        public void setItemIcon(Object itemId, Resource icon) {
                if (itemId != null) {
@@ -826,9 +919,11 @@ public class Select
                }
        }
 
-       /** Get the item icon.
-        *
-        * @param itemId The id of the item to be assigned an icon.
+       /**
+        * Get the item icon.
+        * 
+        * @param itemId
+        *            The id of the item to be assigned an icon.
         * @return Icon for the item or null, if not specified.
         */
        public Resource getItemIcon(Object itemId) {
@@ -849,82 +944,89 @@ public class Select
                return null;
        }
 
-       /** Set the item caption mode.
-        *
-        * <p>The mode can be one of the following ones:
+       /**
+        * Set the item caption mode.
+        * 
+        * <p>
+        * The mode can be one of the following ones:
         * <ul>
-        *  <li><code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> : Items
-        *      Id-objects <code>toString()</code> is used as item caption. If
-        *      caption is explicitly specified, it overrides the id-caption.
-        *  <li><code>ITEM_CAPTION_MODE_ID</code> : Items Id-objects
-        *      <code>toString()</code> is used as item caption.</li>
-        *   <li><code>ITEM_CAPTION_MODE_ITEM</code> : Item-objects
-        *      <code>toString()</code> is used as item caption.</li>
-        *   <li><code>ITEM_CAPTION_MODE_INDEX</code> : The index of the item is
-        *      used as item caption. The index mode can
-        *      only be used with the containers implementing
-        *      <code>Container.Indexed</code> interface.</li>
-        *   <li><code>ITEM_CAPTION_MODE_EXPLICIT</code> : The item captions
-        *       must be explicitly specified.</li>
-        *   <li><code>ITEM_CAPTION_MODE_PROPERTY</code> : The item captions
-        *       are read from property, that must be specified with 
-        *       <code>setItemCaptionPropertyId()</code>.</li>
+        * <li><code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> : Items
+        * Id-objects <code>toString()</code> is used as item caption. If caption
+        * is explicitly specified, it overrides the id-caption.
+        * <li><code>ITEM_CAPTION_MODE_ID</code> : Items Id-objects
+        * <code>toString()</code> is used as item caption.</li>
+        * <li><code>ITEM_CAPTION_MODE_ITEM</code> : Item-objects
+        * <code>toString()</code> is used as item caption.</li>
+        * <li><code>ITEM_CAPTION_MODE_INDEX</code> : The index of the item is
+        * used as item caption. The index mode can only be used with the containers
+        * implementing <code>Container.Indexed</code> interface.</li>
+        * <li><code>ITEM_CAPTION_MODE_EXPLICIT</code> : The item captions must
+        * be explicitly specified.</li>
+        * <li><code>ITEM_CAPTION_MODE_PROPERTY</code> : The item captions are
+        * read from property, that must be specified with
+        * <code>setItemCaptionPropertyId()</code>.</li>
         * </ul>
         * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default
         * mode.
         * </p>
-        *
-        * @param mode One of the modes listed above.
+        * 
+        * @param mode
+        *            One of the modes listed above.
         */
        public void setItemCaptionMode(int mode) {
-               if (ITEM_CAPTION_MODE_ID <= mode
-                       && mode <= ITEM_CAPTION_MODE_PROPERTY) {
+               if (ITEM_CAPTION_MODE_ID <= mode && mode <= ITEM_CAPTION_MODE_PROPERTY) {
                        itemCaptionMode = mode;
                        requestRepaint();
                }
        }
 
-       /** Get the item caption mode.
-        *
-        * <p>The mode can be one of the following ones:
+       /**
+        * Get the item caption mode.
+        * 
+        * <p>
+        * The mode can be one of the following ones:
         * <ul>
-        *  <li><code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> : Items
-        *      Id-objects <code>toString()</code> is used as item caption. If
-        *      caption is explicitly specified, it overrides the id-caption.
-        *  <li><code>ITEM_CAPTION_MODE_ID</code> : Items Id-objects
-        *      <code>toString()</code> is used as item caption.</li>
-        *   <li><code>ITEM_CAPTION_MODE_ITEM</code> : Item-objects
-        *      <code>toString()</code> is used as item caption.</li>
-        *   <li><code>ITEM_CAPTION_MODE_INDEX</code> : The index of the item is
-        *      used as item caption. The index mode can
-        *      only be used with the containers implementing
-        *      <code>Container.Indexed</code> interface.</li>
-        *   <li><code>ITEM_CAPTION_MODE_EXPLICIT</code> : The item captions
-        *       must be explicitly specified.</li>
-        *   <li><code>ITEM_CAPTION_MODE_PROPERTY</code> : The item captions
-        *       are read from property, that must be specified with 
-        *       <code>setItemCaptionPropertyId()</code>.</li>
+        * <li><code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> : Items
+        * Id-objects <code>toString()</code> is used as item caption. If caption
+        * is explicitly specified, it overrides the id-caption.
+        * <li><code>ITEM_CAPTION_MODE_ID</code> : Items Id-objects
+        * <code>toString()</code> is used as item caption.</li>
+        * <li><code>ITEM_CAPTION_MODE_ITEM</code> : Item-objects
+        * <code>toString()</code> is used as item caption.</li>
+        * <li><code>ITEM_CAPTION_MODE_INDEX</code> : The index of the item is
+        * used as item caption. The index mode can only be used with the containers
+        * implementing <code>Container.Indexed</code> interface.</li>
+        * <li><code>ITEM_CAPTION_MODE_EXPLICIT</code> : The item captions must
+        * be explicitly specified.</li>
+        * <li><code>ITEM_CAPTION_MODE_PROPERTY</code> : The item captions are
+        * read from property, that must be specified with
+        * <code>setItemCaptionPropertyId()</code>.</li>
         * </ul>
         * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default
         * mode.
         * </p>
-        *
+        * 
         * @return One of the modes listed above.
         */
        public int getItemCaptionMode() {
                return itemCaptionMode;
        }
 
-       /** Set the item caption property.
+       /**
+        * Set the item caption property.
+        * 
+        * <p>
+        * Setting the id to a existing property implicitly sets the item caption
+        * mode to <code>ITEM_CAPTION_MODE_PROPERTY</code>. If the object is in
+        * <code>ITEM_CAPTION_MODE_PROPERTY</code> mode, setting caption property
+        * id null resets the item caption mode to
+        * <code>ITEM_CAPTION_EXPLICIT_DEFAULTS_ID</code>.
+        * </p>
         * 
-        * <p>Setting the id to a existing property implicitly sets 
-        * the item caption mode to <code>ITEM_CAPTION_MODE_PROPERTY</code>.
-        * If the object is in <code>ITEM_CAPTION_MODE_PROPERTY</code>
-        * mode, setting caption property id null resets the 
-        * item caption mode to <code>ITEM_CAPTION_EXPLICIT_DEFAULTS_ID</code>.</p>
-       
-        * <p>Setting the property id to null disables this feature. The 
-        * id is null by default</p>.
+        * <p>
+        * Setting the property id to null disables this feature. The id is null by
+        * default
+        * </p>.
         * 
         */
        public void setItemCaptionPropertyId(Object propertyId) {
@@ -940,7 +1042,8 @@ public class Select
                }
        }
 
-       /** Get the item caption property.
+       /**
+        * Get the item caption property.
         * 
         * @return Id of the property used as item caption source.
         */
@@ -948,41 +1051,55 @@ public class Select
                return itemCaptionPropertyId;
        }
 
-       /** Set the item icon property.
+       /**
+        * Set the item icon property.
         * 
-        * <p>If the property id is set to a valid value, each item is given 
-        * an icon got from the given property of the items. The type
-        * of the property must be assignable to Icon.</p>
+        * <p>
+        * If the property id is set to a valid value, each item is given an icon
+        * got from the given property of the items. The type of the property must
+        * be assignable to Icon.
+        * </p>
         * 
-        * <p>Note that the icons set with <code>setItemIcon</code>
-        * function override the icons from the property.</p>
+        * <p>
+        * Note that the icons set with <code>setItemIcon</code> function override
+        * the icons from the property.
+        * </p>
         * 
-        * <p>Setting the property id to null disables this feature. The 
-        * id is null by default</p>.
+        * <p>
+        * Setting the property id to null disables this feature. The id is null by
+        * default
+        * </p>.
         * 
-        * @param propertyId Id of the property that specifies icons for
-        * items.
+        * @param propertyId
+        *            Id of the property that specifies icons for items.
         */
        public void setItemIconPropertyId(Object propertyId) {
                if ((propertyId != null)
-                       && Resource.class.isAssignableFrom(getType(propertyId))) {
+                               && Resource.class.isAssignableFrom(getType(propertyId))) {
                        itemIconPropertyId = propertyId;
                        requestRepaint();
                } else
                        itemIconPropertyId = null;
        }
 
-       /** Get the item icon property.
+       /**
+        * Get the item icon property.
         * 
-        * <p>If the property id is set to a valid value, each item is given 
-        * an icon got from the given property of the items. The type
-        * of the property must be assignable to Icon.</p>
+        * <p>
+        * If the property id is set to a valid value, each item is given an icon
+        * got from the given property of the items. The type of the property must
+        * be assignable to Icon.
+        * </p>
         * 
-        * <p>Note that the icons set with <code>setItemIcon</code>
-        * function override the icons from the property.</p>
+        * <p>
+        * Note that the icons set with <code>setItemIcon</code> function override
+        * the icons from the property.
+        * </p>
         * 
-        * <p>Setting the property id to null disables this feature. The 
-        * id is null by default</p>.
+        * <p>
+        * Setting the property id to null disables this feature. The id is null by
+        * default
+        * </p>.
         * 
         * @return Id of the property containing the item icons.
         */
@@ -990,15 +1107,19 @@ public class Select
                return itemIconPropertyId;
        }
 
-       /** Test if an item is selected
+       /**
+        * Test if an item is selected
         * 
-        * <p>In single select mode testing selection status of the item identified
-        * by {@link #getNullSelectionItemId()} returns true if the value of the 
-        * property is null.</p>
+        * <p>
+        * In single select mode testing selection status of the item identified by
+        * {@link #getNullSelectionItemId()} returns true if the value of the
+        * property is null.
+        * </p>
         * 
         * @see #getNullSelectionItemId()
         * @see #setNullSelectionItemId(Object)
-        * @param itemId Id the of the item to be tested
+        * @param itemId
+        *            Id the of the item to be tested
         */
        public boolean isSelected(Object itemId) {
                if (itemId == null)
@@ -1007,20 +1128,23 @@ public class Select
                        return ((Set) getValue()).contains(itemId);
                else {
                        Object value = getValue();
-                       return itemId.equals(
-                               value == null ? getNullSelectionItemId() : value);
+                       return itemId.equals(value == null ? getNullSelectionItemId()
+                                       : value);
                }
        }
 
-       /** Select an item.
+       /**
+        * Select an item.
         * 
-        * <p>In single select mode selecting item identified
-        * by {@link #getNullSelectionItemId()} sets the value of the 
-        * property to null.</p>
+        * <p>
+        * In single select mode selecting item identified by
+        * {@link #getNullSelectionItemId()} sets the value of the property to null.
+        * </p>
         * 
         * @see #getNullSelectionItemId()
         * @see #setNullSelectionItemId(Object)
-        * @param itemId Item to be selected.
+        * @param itemId
+        *            Item to be selected.
         */
        public void select(Object itemId) {
                if (!isSelected(itemId) && items.containsId(itemId)) {
@@ -1035,11 +1159,13 @@ public class Select
                }
        }
 
-       /** Unselect an item.
+       /**
+        * Unselect an item.
         * 
         * @see #getNullSelectionItemId()
         * @see #setNullSelectionItemId(Object)
-        * @param itemId Item to be unselected.
+        * @param itemId
+        *            Item to be unselected.
         */
        public void unselect(Object itemId) {
                if (isSelected(itemId)) {
@@ -1056,7 +1182,7 @@ public class Select
         * @see com.itmill.toolkit.data.Container.PropertySetChangeListener#containerPropertySetChange(com.itmill.toolkit.data.Container.PropertySetChangeEvent)
         */
        public void containerPropertySetChange(
-               Container.PropertySetChangeEvent event) {
+                       Container.PropertySetChangeEvent event) {
                firePropertySetChange();
        }
 
@@ -1106,7 +1232,7 @@ public class Select
        public void containerItemSetChange(Container.ItemSetChangeEvent event) {
                // Clear item id mapping table
                this.itemIdMapper.removeAll();
-               
+
                // Notify all listeners
                fireItemSetChange();
        }
@@ -1114,34 +1240,24 @@ public class Select
        /** Fire property set change event */
        protected void firePropertySetChange() {
                if (propertySetEventListeners != null
-                       && !propertySetEventListeners.isEmpty()) {
-                       Container.PropertySetChangeEvent event =
-                               new PropertySetChangeEvent();
+                               && !propertySetEventListeners.isEmpty()) {
+                       Container.PropertySetChangeEvent event = new PropertySetChangeEvent();
                        Object[] listeners = propertySetEventListeners.toArray();
                        for (int i = 0; i < listeners.length; i++)
-                               (
-                                       (
-                                               Container
-                                                       .PropertySetChangeListener) listeners[i])
-                                                       .containerPropertySetChange(
-                                       event);
+                               ((Container.PropertySetChangeListener) listeners[i])
+                                               .containerPropertySetChange(event);
                }
                requestRepaint();
        }
 
        /** Fire item set change event */
        protected void fireItemSetChange() {
-               if (itemSetEventListeners != null
-                       && !itemSetEventListeners.isEmpty()) {
+               if (itemSetEventListeners != null && !itemSetEventListeners.isEmpty()) {
                        Container.ItemSetChangeEvent event = new ItemSetChangeEvent();
                        Object[] listeners = itemSetEventListeners.toArray();
                        for (int i = 0; i < listeners.length; i++)
-                               (
-                                       (
-                                               Container
-                                                       .ItemSetChangeListener) listeners[i])
-                                                       .containerItemSetChange(
-                                       event);
+                               ((Container.ItemSetChangeListener) listeners[i])
+                                               .containerItemSetChange(event);
                }
                requestRepaint();
        }
@@ -1159,8 +1275,8 @@ public class Select
        }
 
        /** Implementation of property set change event */
-       private class PropertySetChangeEvent
-               implements Container.PropertySetChangeEvent {
+       private class PropertySetChangeEvent implements
+                       Container.PropertySetChangeEvent {
 
                /**
                 * @see com.itmill.toolkit.data.Container.PropertySetChangeEvent#getContainer()
@@ -1170,12 +1286,17 @@ public class Select
                }
 
        }
-       /** Returns the item id that represents null value of this select in single select mode.
+
+       /**
+        * Returns the item id that represents null value of this select in single
+        * select mode.
+        * 
+        * <p>
+        * Data interface does not support nulls as item ids. Selecting the item
+        * idetified by this id is the same as selecting no items at all. This
+        * setting only affects the single select mode.
+        * </p>
         * 
-        * <p>Data interface does not support nulls as item ids. Selecting the item idetified 
-        * by this id is the same as selecting no items at all. This setting only affects the
-        * single select mode.</p>
-       
         * @return Object Null value item id.
         * @see #setNullSelectionItemId(Object)
         * @see #isSelected(Object)
@@ -1185,13 +1306,17 @@ public class Select
                return nullSelectionItemId;
        }
 
-       /** Sets the item id that represents null value of this select.
+       /**
+        * Sets the item id that represents null value of this select.
+        * 
+        * <p>
+        * Data interface does not support nulls as item ids. Selecting the item
+        * idetified by this id is the same as selecting no items at all. This
+        * setting only affects the single select mode.
+        * </p>
         * 
-        * <p>Data interface does not support nulls as item ids. Selecting the item idetified 
-        * by this id is the same as selecting no items at all. This setting only affects the
-        * single select mode.</p>
-        *
-        * @param nullPropertyValueContainerItemId The nullPropertyValueContainerItemId to set
+        * @param nullPropertyValueContainerItemId
+        *            The nullPropertyValueContainerItemId to set
         * @see #getNullSelectionItemId()
         * @see #isSelected(Object)
         * @see #select(Object)
@@ -1199,4 +1324,202 @@ public class Select
        public void setNullSelectionItemId(Object nullSelectionItemId) {
                this.nullSelectionItemId = nullSelectionItemId;
        }
+
+       // TODO javadoc
+       public boolean isLazyLoading() {
+               return optionsStream != null;
+       }
+
+       // TODO javadoc
+       // TODO What to do when terminal does not support lazy loading?
+       public void setLazyLoading(boolean useLazyLoading) {
+               if (useLazyLoading != isLazyLoading()) {
+                       if (useLazyLoading) {
+                               optionsStream = new OptionsStream();
+                               if (getApplication() != null)
+                                       getWindow().addURIHandler(optionsStream);
+                       } else {
+                               if (getApplication() != null)
+                                       getWindow().removeURIHandler(optionsStream);
+                               optionsStream = null;
+                       }
+
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * @see org.millstone.base.ui.Component#attach()
+        */
+       public void attach() {
+               super.attach();
+               if (optionsStream != null) {
+                       getWindow().removeURIHandler(optionsStream);
+                       getWindow().addURIHandler(optionsStream);
+               }
+       }
+
+       /**
+        * @see org.millstone.base.ui.Component#detach()
+        */
+       public void detach() {
+               if (optionsStream != null)
+                       getWindow().removeURIHandler(optionsStream);
+               super.detach();
+       }
+
+       private class OptionsStream implements URIHandler {
+
+               private String currentFilter = "";
+
+               private ArrayList filteredItemsBuffer = null;
+
+               private String uri = "selectOptionsStream"
+                               + (long) (Math.random() * 1000000000000000000L);
+
+               public DownloadStream handleURI(URL context, String relativeUri) {
+
+                       if (!"".equals(uri)) {
+                               DownloadStream ds = null;
+
+                               if (relativeUri.indexOf(uri + "/feedMoreItems/") != -1) { // this
+                                       // feed visible items
+                                       int i = 0;
+                                       String index = relativeUri.substring(relativeUri
+                                                       .lastIndexOf("/") + 1);
+                                       try {
+                                               i = Integer.parseInt(index);
+                                       } catch (NumberFormatException e) {
+                                               // ignore
+                                       }
+                                       // TODO Req size
+                                       ds = createDownloadStream(13,i,"");
+                                       return ds;
+
+                               } else if (relativeUri.indexOf(uri) != -1) {
+
+                                       // TODO support '/' character in prefix.
+                                       // read prefix
+                                       String prefix = relativeUri.substring(relativeUri
+                                                       .lastIndexOf("/") + 1);
+                                       // TODO Req size
+                                       ds = createDownloadStream(13,0,prefix.trim());
+                                       return ds;
+                               }
+                       }
+                       return null;
+               }
+
+               /**
+                * Creates DownloadStream for response
+                * 
+                * @param visibleitems
+                *            Items to be return
+                * @return new DownloadStream
+                */
+               public DownloadStream createDownloadStream(int size, int first, String filter) {
+
+                       ByteArrayOutputStream os = new ByteArrayOutputStream();
+                       OutputStreamWriter osw = new OutputStreamWriter(os, Charset
+                                       .forName("utf-8"));
+
+                       // JSONObject json = createJSONObject(visibleitems);
+                       String json = getJSON( size,  first,  filter);
+                       try {
+                               osw.write(json);
+                               osw.flush();
+                               os.flush();
+                       } catch (IOException e) {
+                               e.printStackTrace();
+                       }
+                       DownloadStream ds = new DownloadStream(new ByteArrayInputStream(os
+                                       .toByteArray()), "text/plain;charset=utf-8", "options.js");
+                       return ds;
+               }
+
+               /**
+                * Update visible items by given prefix.
+                * 
+                * @param prefix
+                *            Filter prefix
+                * @return All item ids filtered by given prefix.
+                */
+               public ArrayList filterContent(String prefix) {
+                       // prefix MUST be in lowercase
+                       if ("".equals(prefix)) {
+                               this.filteredItemsBuffer = new ArrayList(getItemIds());
+                               return this.filteredItemsBuffer;
+
+                       } else if (items != null) { 
+                               // all items will be iterated and tested.
+                               // SLOW when there are lot of items.
+                               // TODO Should we add 
+                               this.filteredItemsBuffer = new ArrayList();
+                               for (Iterator iter = items.getItemIds().iterator(); iter
+                                               .hasNext();) {
+                                       Object id = iter.next();
+
+                                       Item item = getItem(id);
+                                       String test = "";
+                                       if (getItemCaptionMode() == ITEM_CAPTION_MODE_PROPERTY)
+                                               test = item.getItemProperty(getItemCaptionPropertyId())
+                                                               .getValue().toString().trim();
+                                       else
+                                               test = String.valueOf(id);
+
+                                       if (test.toLowerCase().startsWith(prefix)) {
+                                               this.filteredItemsBuffer.add(id);
+                                       }
+                               }
+                       }
+
+                       return this.filteredItemsBuffer;
+               }
+
+               private void addToJSONArray(StringBuffer json, ArrayList values) {
+                       for (int i = 0; i < values.size(); i++)
+                               json.append((i > 0 ? "," : "") + '"' + values.get(i).toString()
+                                               + '"');
+               }
+               
+               private String getJSON(int size, int first, String filter) {
+
+                       // Refilter options, if needed
+                       if (!currentFilter.equals(filter) || filteredItemsBuffer == null) {
+                               filteredItemsBuffer = filterContent(filter);
+                               currentFilter = filter;
+                       }       
+
+                       // Create list of shown options
+                       ArrayList keys = new ArrayList();
+                       ArrayList values = new ArrayList();
+
+                       for (int i=first; i<first+size && i<filteredItemsBuffer.size(); i++) {
+                               Object id = filteredItemsBuffer.get(i);
+                               Item item = getItem(id);
+                               keys.add(Select.this.itemIdMapper.key(id));
+                               if (getItemCaptionMode() == ITEM_CAPTION_MODE_PROPERTY)
+                                       try {
+                                               values.add(URLEncoder.encode(item.getItemProperty(
+                                                               getItemCaptionPropertyId()).getValue()
+                                                               .toString(), "ISO-8859-1"));
+                                       } catch (UnsupportedEncodingException e) {
+                                               e.printStackTrace();
+                                       }
+                               else
+                                       values.add(String.valueOf(id));
+                       }
+
+                       // Construct JSON format for response
+                       StringBuffer json = new StringBuffer();
+                       json.append("{\"keys\":[");
+                       addToJSONArray(json, keys);
+                       json.append("],\"total\":" + this.filteredItemsBuffer.size());
+                       json.append(",\"values\":[");
+                       addToJSONArray(json, values);
+                       json.append("]}");
+
+                       return json.toString();
+               }
+       }
 }
index 02c5335213a39e3d5be022ece16e7a81bddaaa38..64e5b7d1fadf419ced42ff99584964c090b7d804 100644 (file)
@@ -61,7 +61,7 @@ import com.itmill.toolkit.terminal.Sizeable;
 public class Table extends Select implements Action.Container,
         Container.Ordered, Container.Sortable, Sizeable {
 
-    private static final int CELL_KEY = 0;
+       private static final int CELL_KEY = 0;
 
     private static final int CELL_HEADER = 1;
 
@@ -2247,4 +2247,13 @@ public class Table extends Select implements Action.Container,
                requestRepaint();
        }
 
+       /** Table does not support lazy options loading mode. 
+        * Setting this true will throw UnsupportedOperationException. 
+        */
+    public void setLazyLoading(boolean useLazyLoading) {
+       if (useLazyLoading)
+               throw new UnsupportedOperationException("Lazy options loading is not supported by Table.");
+       }
+
+
 }
\ No newline at end of file
index 5ca7983b25e6cd8888a8a596cabb0cad69bbc3a4..cdb95d5ec2ddd1fb722be938e56a4adc7ec8b875 100644 (file)
@@ -759,5 +759,14 @@ public class Tree extends Select implements Container.Hierarchical, Action.Conta
        public void focus() throws UnsupportedOperationException {
                throw new UnsupportedOperationException();
        }
+       
+       /** Tree does not support lazy options loading mode. 
+        * Setting this true will throw UnsupportedOperationException. 
+        */
+    public void setLazyLoading(boolean useLazyLoading) {
+       if (useLazyLoading)
+               throw new UnsupportedOperationException("Lazy options loading is not supported by Tree.");
+       }
+
 
 }