]> source.dussan.org Git - vaadin-framework.git/commitdiff
Select refactor initial commit; not done.
authorMarc Englund <marc.englund@itmill.com>
Wed, 31 Oct 2007 07:41:08 +0000 (07:41 +0000)
committerMarc Englund <marc.englund@itmill.com>
Wed, 31 Oct 2007 07:41:08 +0000 (07:41 +0000)
svn changeset:2629/svn branch:trunk

16 files changed:
src/com/itmill/toolkit/demo/FilterSelect.java
src/com/itmill/toolkit/demo/SelectDemo.java
src/com/itmill/toolkit/tests/TestForMultipleStyleNames.java
src/com/itmill/toolkit/tests/TestForPreconfiguredComponents.java
src/com/itmill/toolkit/tests/TestForUpload.java
src/com/itmill/toolkit/tests/TestForWindowing.java
src/com/itmill/toolkit/ui/AbstractSelect.java [new file with mode: 0644]
src/com/itmill/toolkit/ui/NativeSelect.java
src/com/itmill/toolkit/ui/OptionGroup.java
src/com/itmill/toolkit/ui/Select.java
src/com/itmill/toolkit/ui/Table.java
src/com/itmill/toolkit/ui/Tree.java
src/com/itmill/toolkit/ui/TwinColSelect.java
src/com/itmill/toolkit/ui/select/ContainsFilter.java [deleted file]
src/com/itmill/toolkit/ui/select/OptionFilter.java [deleted file]
src/com/itmill/toolkit/ui/select/StartsWithFilter.java [deleted file]

index 81e702dfeb4575c53f2da371f12da23d3e4f0d44..8abda479a23b3af2ffc8834165218381bde55234 100644 (file)
@@ -1,16 +1,9 @@
 package com.itmill.toolkit.demo;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.itmill.toolkit.data.Item;
 import com.itmill.toolkit.ui.OrderedLayout;
 import com.itmill.toolkit.ui.Panel;
 import com.itmill.toolkit.ui.Select;
 import com.itmill.toolkit.ui.Window;
-import com.itmill.toolkit.ui.select.ContainsFilter;
-import com.itmill.toolkit.ui.select.OptionFilter;
 
 /**
  * The classic "hello, world!" example for IT Mill Toolkit. The class simply
@@ -50,33 +43,33 @@ public class FilterSelect extends com.itmill.toolkit.Application {
 
                // default filter
                Select s1 = new Select();
-               for (int i = 0; i < 105; i++)
+               for (int i = 0; i < 105; i++) {
                        s1
                                        .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))]
                                                        + " "
                                                        + lastnames[(int) (Math.random() * (lastnames.length - 1))]);
-               s1.setLazyLoading(true);
+               }
                s1.setImmediate(true);
 
                // contains filter
                Select s2 = new Select();
-               for (int i = 0; i < 500; i++)
+               for (int i = 0; i < 500; i++) {
                        s2
                                        .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))]
                                                        + " "
                                                        + lastnames[(int) (Math.random() * (lastnames.length - 1))]);
-               s2.setLazyLoading(true);
-               s2.setOptionFilter(new ContainsFilter(s2));
+               }
+               s2.setFilteringMode(Select.FILTERINGMODE_CONTAINS);
 
-               // custom filter
+               // startswith filter
                Select s3 = new Select();
-               for (int i = 0; i < 500; i++)
+               for (int i = 0; i < 500; i++) {
                        s3
                                        .addItem(firstnames[(int) (Math.random() * (firstnames.length - 1))]
                                                        + " "
                                                        + lastnames[(int) (Math.random() * (lastnames.length - 1))]);
-               s3.setLazyLoading(true);
-               s3.setOptionFilter(new FilterSelect.EndsWithFilter(s3));
+               }
+               s3.setFilteringMode(Select.FILTERINGMODE_STARTSWITH);
 
                // Add selects to UI using ordered layout and panels
                OrderedLayout orderedLayout = new OrderedLayout(
@@ -97,54 +90,4 @@ public class FilterSelect extends com.itmill.toolkit.Application {
 
        }
 
-       /**
-        * Custom filter that implements "ends with" functionality.
-        * 
-        * @author IT Mill Ltd.
-        * 
-        */
-       public class EndsWithFilter implements OptionFilter {
-               private Select s;
-
-               private ArrayList filteredItemsBuffer;
-
-               public EndsWithFilter(Select s) {
-                       this.s = s;
-               }
-
-               public List filter(String filterstring, int pagelength, int page) {
-                       // prefix MUST be in lowercase
-                       if (filterstring == null || "".equals(filterstring)) {
-                               this.filteredItemsBuffer = new ArrayList(s.getItemIds());
-                               return this.filteredItemsBuffer;
-
-                       } else if (s.getContainerDataSource() != null) {
-                               // all items will be iterated and tested.
-                               // SLOW when there are lot of items.
-                               this.filteredItemsBuffer = new ArrayList();
-                               for (Iterator iter = s.getItemIds().iterator(); iter.hasNext();) {
-                                       Object id = iter.next();
-
-                                       Item item = s.getItem(id);
-                                       String test = "";
-                                       if (s.getItemCaptionMode() == Select.ITEM_CAPTION_MODE_PROPERTY)
-                                               test = item.getItemProperty(
-                                                               s.getItemCaptionPropertyId()).getValue()
-                                                               .toString().trim();
-                                       else
-                                               test = String.valueOf(id);
-
-                                       if (test.toLowerCase().endsWith(filterstring)) {
-                                               this.filteredItemsBuffer.add(id);
-                                       }
-                               }
-                       }
-                       return this.filteredItemsBuffer;
-               }
-
-               public int getMatchCount() {
-                       return filteredItemsBuffer.size();
-               }
-       }
-
 }
index 7170d7aacdb73f9d69be3239b2e96326c880945c..20128ea9da23eb78ac71e8f6340569bacddd3070 100644 (file)
@@ -1,9 +1,13 @@
 package com.itmill.toolkit.demo;
 
 import java.sql.SQLException;
+
 import com.itmill.toolkit.data.util.QueryContainer;
 import com.itmill.toolkit.demo.util.SampleDatabase;
-import com.itmill.toolkit.ui.*;
+import com.itmill.toolkit.ui.Label;
+import com.itmill.toolkit.ui.Panel;
+import com.itmill.toolkit.ui.Select;
+import com.itmill.toolkit.ui.Window;
 
 /**
  * This example demonstrates what is lazy loading feature on Select component.
@@ -16,9 +20,9 @@ import com.itmill.toolkit.ui.*;
 public class SelectDemo extends com.itmill.toolkit.Application {
 
        // Select component where SQL rows are attached (using QueryContainer)
-       private Select select = new Select();
+       private final Select select = new Select();
 
-       private Select lazySelect = new Select();
+       private final Select lazySelect = new Select();
 
        // Database provided with sample data
        private SampleDatabase sampleDatabase;
@@ -32,40 +36,41 @@ public class SelectDemo extends com.itmill.toolkit.Application {
 
                // Main window contains heading, table, select and tree
                Panel panel = new Panel("Select demo (a.k.a Google Suggests)");
-               panel.addComponent(lazySelect);
+               panel.addComponent(this.lazySelect);
                panel.addComponent(new Label("<hr />", Label.CONTENT_XHTML));
-               panel.addComponent(select);
+               panel.addComponent(this.select);
                main.addComponent(panel);
 
                // create demo database
-               sampleDatabase = new SampleDatabase();
+               this.sampleDatabase = new SampleDatabase();
 
                initSelects();
        }
 
        private void initSelects() {
                // init select
-               select.setCaption("All employees default functionality.");
-               select.setItemCaptionPropertyId("WORKER");
+               this.select.setCaption("All employees default functionality.");
+               this.select.setItemCaptionPropertyId("WORKER");
                // populate Toolkit select component with test SQL table rows
                try {
                        QueryContainer qc = new QueryContainer(
                                        "SELECT ID, UNIT||', '||LASTNAME||' '||FIRSTNAME"
                                                        + " AS WORKER FROM employee ORDER BY WORKER",
-                                       sampleDatabase.getConnection());
-                       select.setContainerDataSource(qc);
+                                       this.sampleDatabase.getConnection());
+                       this.select.setContainerDataSource(qc);
                } catch (SQLException e) {
                        e.printStackTrace();
                }
 
                // init lazySelect
-               lazySelect.setCaption("All employees with lazy loading "
+               this.lazySelect.setCaption("All employees with lazy loading "
                                + "(a.k.a Google Suggests) activated.");
-               lazySelect.setItemCaptionPropertyId("WORKER");
-               // use lazy loading (a.k.a Google Suggest)
-               lazySelect.setLazyLoading(true);
+               this.lazySelect.setItemCaptionPropertyId("WORKER");
+               this.lazySelect.setFilteringMode(Select.FILTERINGMODE_CONTAINS);
+
                // use same datasource as select object uses
-               lazySelect.setContainerDataSource(select.getContainerDataSource());
+               this.lazySelect.setContainerDataSource(this.select
+                               .getContainerDataSource());
        }
 
 }
index 9eac70f48ca0babc2b2f052119c5920eb9b032cf..a87f53ae106b1287c3e2e03115572036a5a07b48 100644 (file)
@@ -7,81 +7,78 @@ import java.util.Iterator;
 import com.itmill.toolkit.data.Property.ValueChangeEvent;
 import com.itmill.toolkit.data.Property.ValueChangeListener;
 import com.itmill.toolkit.data.util.IndexedContainer;
-import com.itmill.toolkit.ui.Button;
 import com.itmill.toolkit.ui.CustomComponent;
 import com.itmill.toolkit.ui.Label;
 import com.itmill.toolkit.ui.OrderedLayout;
-import com.itmill.toolkit.ui.RichTextArea;
-import com.itmill.toolkit.ui.Select;
 import com.itmill.toolkit.ui.TwinColSelect;
 
 /**
  * 
  * @author IT Mill Ltd.
  */
-public class TestForMultipleStyleNames extends CustomComponent implements ValueChangeListener {
+public class TestForMultipleStyleNames extends CustomComponent implements
+               ValueChangeListener {
+
+       private final OrderedLayout main = new OrderedLayout();
 
-       private OrderedLayout main = new OrderedLayout();
-       
        private Label l;
-       
-       private Select s = new TwinColSelect();
+
+       private final TwinColSelect s = new TwinColSelect();
 
        private ArrayList styleNames2;
 
        public TestForMultipleStyleNames() {
-               setCompositionRoot(main);
+               setCompositionRoot(this.main);
                createNewView();
        }
 
        public void createNewView() {
-               main.removeAllComponents();
-               main
-                               .addComponent(new Label(
-                                               "TK5 supports multiple stylenames for components."));
-
-               
-               styleNames2 = new ArrayList();
-               
-               styleNames2.add("red");
-               styleNames2.add("bold");
-               styleNames2.add("italic");
-               
-               s.setContainerDataSource(new IndexedContainer(styleNames2));
-               s.addListener(this);
-               s.setImmediate(true);
-               main.addComponent(s);
-               
-               l = new Label("Test labele");
-               main.addComponent(l);
+               this.main.removeAllComponents();
+               this.main.addComponent(new Label(
+                               "TK5 supports multiple stylenames for components."));
+
+               this.styleNames2 = new ArrayList();
+
+               this.styleNames2.add("red");
+               this.styleNames2.add("bold");
+               this.styleNames2.add("italic");
+
+               this.s.setContainerDataSource(new IndexedContainer(this.styleNames2));
+               this.s.addListener(this);
+               this.s.setImmediate(true);
+               this.main.addComponent(this.s);
+
+               this.l = new Label("Test labele");
+               this.main.addComponent(this.l);
 
        }
 
        public void valueChange(ValueChangeEvent event) {
-               
-               String currentStyle = l.getStyle();
+
+               String currentStyle = this.l.getStyle();
                String[] tmp = currentStyle.split(" ");
                ArrayList curStyles = new ArrayList();
                for (int i = 0; i < tmp.length; i++) {
-                       if(tmp[i] != "")
+                       if (tmp[i] != "") {
                                curStyles.add(tmp[i]);
+                       }
                }
-               
-               Collection styles = (Collection) s.getValue();
-               
+
+               Collection styles = (Collection) this.s.getValue();
+
                for (Iterator iterator = styles.iterator(); iterator.hasNext();) {
                        String styleName = (String) iterator.next();
-                       if(curStyles.contains(styleName)) {
+                       if (curStyles.contains(styleName)) {
                                // already added
                                curStyles.remove(styleName);
                        } else {
-                               l.addStyleName(styleName);
+                               this.l.addStyleName(styleName);
                        }
                }
                for (Iterator iterator2 = curStyles.iterator(); iterator2.hasNext();) {
                        String object = (String) iterator2.next();
-                       l.removeStyleName(object);
+                       this.l.removeStyleName(object);
                }
        }
-       
+
 }
index 69d06c869b2c66c3e48798527d2e9d016c184f65..e108756c598d6a0b9ef0ac3c3a48d59f4d02f5d5 100644 (file)
@@ -2,6 +2,7 @@ package com.itmill.toolkit.tests;
 
 import com.itmill.toolkit.event.Action;
 import com.itmill.toolkit.event.Action.Handler;
+import com.itmill.toolkit.ui.AbstractSelect;
 import com.itmill.toolkit.ui.Button;
 import com.itmill.toolkit.ui.CheckBox;
 import com.itmill.toolkit.ui.Component;
@@ -11,7 +12,6 @@ import com.itmill.toolkit.ui.NativeSelect;
 import com.itmill.toolkit.ui.OptionGroup;
 import com.itmill.toolkit.ui.OrderedLayout;
 import com.itmill.toolkit.ui.Panel;
-import com.itmill.toolkit.ui.Select;
 import com.itmill.toolkit.ui.Tree;
 import com.itmill.toolkit.ui.TwinColSelect;
 import com.itmill.toolkit.ui.Button.ClickEvent;
@@ -32,9 +32,9 @@ public class TestForPreconfiguredComponents extends CustomComponent implements
                        "Smith", "Jones", "Beck", "Sheridan", "Picard", "Hill", "Fielding",
                        "Einstein" };
 
-       private OrderedLayout main = new OrderedLayout();
+       private final OrderedLayout main = new OrderedLayout();
 
-       private Action[] actions = new Action[] { new Action("edit"),
+       private final Action[] actions = new Action[] { new Action("edit"),
                        new Action("delete") };
 
        private Panel al;
@@ -43,73 +43,73 @@ public class TestForPreconfiguredComponents extends CustomComponent implements
 
        public TestForPreconfiguredComponents() {
 
-               setCompositionRoot(main);
+               setCompositionRoot(this.main);
                createNewView();
        }
 
        public void createNewView() {
-               main.removeAllComponents();
-               main
+               this.main.removeAllComponents();
+               this.main
                                .addComponent(new Label(
-                                               "In TK5 we introduce some \"new\" componens. Earlier one" +
-                                               " usually used setStyle or some other methods on possibly " +
-                                               "multiple steps to configure component for ones needs. These new " +
-                                               "server side components are mostly just classes that in constructor " +
-                                               "set base class to state that programmer wants. This ought to help " +
-                                               "newcomers and make code more readable."));
+                                               "In TK5 we introduce some \"new\" componens. Earlier one"
+                                                               + " usually used setStyle or some other methods on possibly "
+                                                               + "multiple steps to configure component for ones needs. These new "
+                                                               + "server side components are mostly just classes that in constructor "
+                                                               + "set base class to state that programmer wants. This ought to help "
+                                                               + "newcomers and make code more readable."));
 
-               main.addComponent(new Button("commit"));
+               this.main.addComponent(new Button("commit"));
 
                Panel test = createTestBench(new CheckBox());
                test.setCaption("CheckBox (configured from button)");
-               main.addComponent(test);
+               this.main.addComponent(test);
 
-               Select s = new TwinColSelect();
+               AbstractSelect s = new TwinColSelect();
                fillSelect(s, 20);
                test = createTestBench(s);
                test.setCaption("TwinColSelect (configured from select)");
-               main.addComponent(test);
+               this.main.addComponent(test);
 
                s = new NativeSelect();
                fillSelect(s, 20);
                test = createTestBench(s);
                test.setCaption("Native (configured from select)");
-               main.addComponent(test);
+               this.main.addComponent(test);
 
                s = new OptionGroup();
                fillSelect(s, 20);
                test = createTestBench(s);
                test.setCaption("OptionGroup (configured from select)");
-               main.addComponent(test);
+               this.main.addComponent(test);
 
                s = new OptionGroup();
                fillSelect(s, 20);
                s.setMultiSelect(true);
                test = createTestBench(s);
-               test.setCaption("OptionGroup + multiselect manually (configured from select)");
-               main.addComponent(test);
-
-               
-//             Tree t = createTestTree();
-//             t.setCaption("with actions");
-//             t.setImmediate(true);
-//             t.addActionHandler(this);
-//             Panel ol = (Panel) createTestBench(t);
-//             al = new Panel("action log");
-//             ol.addComponent(al);
-//             main.addComponent(ol);
-//             contextTree = t;
+               test
+                               .setCaption("OptionGroup + multiselect manually (configured from select)");
+               this.main.addComponent(test);
+
+               // Tree t = createTestTree();
+               // t.setCaption("with actions");
+               // t.setImmediate(true);
+               // t.addActionHandler(this);
+               // Panel ol = (Panel) createTestBench(t);
+               // al = new Panel("action log");
+               // ol.addComponent(al);
+               // main.addComponent(ol);
+               // contextTree = t;
 
                Button b = new Button("refresh view", this, "createNewView");
-               main.addComponent(b);
+               this.main.addComponent(b);
 
        }
-       
-       public static void fillSelect(Select s, int items) {
+
+       public static void fillSelect(AbstractSelect s, int items) {
                for (int i = 0; i < items; i++) {
                        String name = firstnames[(int) (Math.random() * (firstnames.length - 1))]
-                                                               + " "
-                                                               + lastnames[(int) (Math.random() * (lastnames.length - 1))];
+                                       + " "
+                                       + lastnames[(int) (Math.random() * (lastnames.length - 1))];
                        s.addItem(name);
                }
        }
@@ -117,24 +117,28 @@ public class TestForPreconfiguredComponents extends CustomComponent implements
        public Tree createTestTree() {
                Tree t = new Tree("Tree");
                String[] names = new String[100];
-               for (int i = 0; i < names.length; i++)
+               for (int i = 0; i < names.length; i++) {
                        names[i] = firstnames[(int) (Math.random() * (firstnames.length - 1))]
                                        + " "
                                        + lastnames[(int) (Math.random() * (lastnames.length - 1))];
+               }
 
                // Create tree
                t = new Tree("Organization Structure");
                for (int i = 0; i < 100; i++) {
                        t.addItem(names[i]);
                        String parent = names[(int) (Math.random() * (names.length - 1))];
-                       if (t.containsId(parent))
+                       if (t.containsId(parent)) {
                                t.setParent(names[i], parent);
+                       }
                }
 
                // Forbid childless people to have children (makes them leaves)
-               for (int i = 0; i < 100; i++)
-                       if (!t.hasChildren(names[i]))
+               for (int i = 0; i < 100; i++) {
+                       if (!t.hasChildren(names[i])) {
                                t.setChildrenAllowed(names[i], false);
+                       }
+               }
                return t;
        }
 
@@ -144,7 +148,8 @@ public class TestForPreconfiguredComponents extends CustomComponent implements
 
                ol.addComponent(t);
 
-               final OrderedLayout ol2 = new OrderedLayout(OrderedLayout.ORIENTATION_HORIZONTAL);
+               final OrderedLayout ol2 = new OrderedLayout(
+                               OrderedLayout.ORIENTATION_HORIZONTAL);
                final Panel status = new Panel("Events");
                final Button clear = new Button("clear event log");
                clear.addListener(new ClickListener() {
@@ -165,9 +170,7 @@ public class TestForPreconfiguredComponents extends CustomComponent implements
 
                t.addListener(new Listener() {
                        public void componentEvent(Event event) {
-                               status
-                                               .addComponent(new Label(event.getClass()
-                                                               .getName()));
+                               status.addComponent(new Label(event.getClass().getName()));
                                status.addComponent(new Label("selected: "
                                                + event.getSource().toString()));
                        }
@@ -177,16 +180,16 @@ public class TestForPreconfiguredComponents extends CustomComponent implements
        }
 
        public Action[] getActions(Object target, Object sender) {
-               return actions;
+               return this.actions;
        }
 
        public void handleAction(Action action, Object sender, Object target) {
-               if (action == actions[1]) {
-                       al.addComponent(new Label("Delete selected on " + target));
-                       contextTree.removeItem(target);
+               if (action == this.actions[1]) {
+                       this.al.addComponent(new Label("Delete selected on " + target));
+                       this.contextTree.removeItem(target);
 
                } else {
-                       al.addComponent(new Label("Edit selected on " + target));
+                       this.al.addComponent(new Label("Edit selected on " + target));
                }
        }
 }
index 91d79f40a003af71b0bafc13388444a49414efa8..05b8970411d9fd8220682a78c8f4dabe216601cc 100644 (file)
@@ -86,7 +86,6 @@ public class TestForUpload extends CustomComponent implements
                this.main.addComponent(c);
 
                this.uploadBufferSelector = new Select("Receiver type");
-               this.uploadBufferSelector.setColumns(6);
                this.uploadBufferSelector.setImmediate(true);
                this.uploadBufferSelector.addItem("memory");
                this.uploadBufferSelector.setValue("memory");
index 2239dad8732179815c269c67ff564769db91a620..1c20c81c87d256bd82caf3554d6ac1b432dc83b0 100644 (file)
@@ -2,6 +2,7 @@ package com.itmill.toolkit.tests;
 
 import com.itmill.toolkit.data.Property.ValueChangeEvent;
 import com.itmill.toolkit.data.Property.ValueChangeListener;
+import com.itmill.toolkit.ui.AbstractSelect;
 import com.itmill.toolkit.ui.Button;
 import com.itmill.toolkit.ui.CustomComponent;
 import com.itmill.toolkit.ui.Label;
@@ -12,60 +13,60 @@ import com.itmill.toolkit.ui.Window;
 import com.itmill.toolkit.ui.Button.ClickEvent;
 import com.itmill.toolkit.ui.Button.ClickListener;
 
-public class TestForWindowing extends CustomComponent {        
-       
+public class TestForWindowing extends CustomComponent {
+
        private Select s2;
 
        public TestForWindowing() {
-               
+
                OrderedLayout main = new OrderedLayout();
-               
-               main.addComponent(new Label("Click the button to create a new inline window."));
-               
+
+               main.addComponent(new Label(
+                               "Click the button to create a new inline window."));
+
                Button create = new Button("Create a new window", new ClickListener() {
 
                        public void buttonClick(ClickEvent event) {
                                Window w = new Window("Testing Window");
-                               
-                               Select s1 = new OptionGroup();
+
+                               AbstractSelect s1 = new OptionGroup();
                                s1.setCaption("1. Select output format");
                                s1.addItem("Excel sheet");
                                s1.addItem("CSV plain text");
                                s1.setValue("Excel sheet");
-                               
-                               s2 = new Select();
-                               s2.addItem("Separate by comma (,)");
-                               s2.addItem("Separate by colon (:)");
-                               s2.addItem("Separate by semicolon (;)");
-                               s2.setColumns(14);
-                               s2.setEnabled(false);
-                               
+
+                               TestForWindowing.this.s2 = new Select();
+                               TestForWindowing.this.s2.addItem("Separate by comma (,)");
+                               TestForWindowing.this.s2.addItem("Separate by colon (:)");
+                               TestForWindowing.this.s2.addItem("Separate by semicolon (;)");
+                               TestForWindowing.this.s2.setEnabled(false);
+
                                s1.addListener(new ValueChangeListener() {
 
                                        public void valueChange(ValueChangeEvent event) {
-                                               String v = (String) event.getProperty().getValue();     
-                                               if(v.equals("CSV plain text"))
-                                                       s2.setEnabled(true);
-                                               else
-                                                       s2.setEnabled(false);
+                                               String v = (String) event.getProperty().getValue();
+                                               if (v.equals("CSV plain text")) {
+                                                       TestForWindowing.this.s2.setEnabled(true);
+                                               } else {
+                                                       TestForWindowing.this.s2.setEnabled(false);
+                                               }
                                        }
-                                       
+
                                });
-                               
+
                                w.addComponent(s1);
-                               w.addComponent(s2);
-                               
+                               w.addComponent(TestForWindowing.this.s2);
+
                                getApplication().getMainWindow().addWindow(w);
-                               
+
                        }
-                       
+
                });
-               
+
                main.addComponent(create);
-               
+
                setCompositionRoot(main);
-               
-       }
 
+       }
 
 }
diff --git a/src/com/itmill/toolkit/ui/AbstractSelect.java b/src/com/itmill/toolkit/ui/AbstractSelect.java
new file mode 100644 (file)
index 0000000..0d0fa88
--- /dev/null
@@ -0,0 +1,1502 @@
+/* *************************************************************************
+ IT Mill Toolkit 
+
+ Development of Browser User Interfaces Made Easy
+
+ 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
+
+ *************************************************************************
+ 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.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+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.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>
+ * 
+ * <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>
+ * 
+ * @author IT Mill Ltd.
+ * @version
+ * @VERSION@
+ * @since 3.0
+ */
+public abstract class AbstractSelect 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.
+        */
+       public static final int ITEM_CAPTION_MODE_ID = 0;
+       /**
+        * 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
+        * {@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>.
+        */
+       public static final int ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID = 3;
+       /**
+        * 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.
+        */
+       public static final int ITEM_CAPTION_MODE_ICON_ONLY = 5;
+       /**
+        * Item caption mode: Item captions are read from property specified with
+        * <code>setItemCaptionPropertyId</code>.
+        */
+       public static final int ITEM_CAPTION_MODE_PROPERTY = 6;
+
+       /**
+        * Interface for option filtering, used to filter options based on user
+        * entered value. The value is matched to the item caption.
+        * <code>FILTERINGMODE_OFF</code> (0) turns the filtering off.
+        * <code>FILTERINGMODE_STARTSWITH</code> (1) matches from the start of the
+        * caption. <code>FILTERINGMODE_CONTAINS</code> (1) matches anywhere in
+        * the caption.
+        */
+       public interface Filtering {
+               public static final int FILTERINGMODE_OFF = 0;
+               public static final int FILTERINGMODE_STARTSWITH = 1;
+               public static final int FILTERINGMODE_CONTAINS = 2;
+
+               /**
+                * Sets the option filtering mode.
+                * 
+                * @param filteringMode
+                *            the filtering mode to use
+                */
+               public void setFilteringMode(int filteringMode);
+
+               /**
+                * Gets the current filtering mode.
+                * 
+                * @return the filtering mode in use
+                */
+               public int getFilteringMode();
+
+       }
+
+       /**
+        * Is the select in multiselect mode?
+        */
+       private boolean multiSelect = false;
+
+       /**
+        * Select options.
+        */
+       protected Container items;
+
+       /**
+        * Is the user allowed to add new options?
+        */
+       private boolean allowNewOptions;
+
+       /**
+        * Keymapper used to map key values.
+        */
+       protected KeyMapper itemIdMapper = new KeyMapper();
+
+       /**
+        * Item icons.
+        */
+       private final HashMap itemIcons = new HashMap();
+
+       /**
+        * Item captions.
+        */
+       private final HashMap itemCaptions = new HashMap();
+
+       /**
+        * Item caption mode.
+        */
+       private int itemCaptionMode = ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID;
+
+       /**
+        * Item caption source property id.
+        */
+       private Object itemCaptionPropertyId = null;
+
+       /**
+        * Item icon source property id.
+        */
+       private Object itemIconPropertyId = null;
+
+       /**
+        * List of property set change event listeners.
+        */
+       private LinkedList propertySetEventListeners = null;
+
+       /**
+        * List of item set change event listeners.
+        */
+       private LinkedList itemSetEventListeners = null;
+
+       /**
+        * 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>
+        */
+       private Object nullSelectionItemId = null;
+
+       // Null (empty) selection is enabled by default
+       private boolean nullSelectionAllowed = true;
+
+       /* Constructors ********************************************************* */
+
+       /**
+        * Creates an empty Select. The caption is not used.
+        */
+       public AbstractSelect() {
+               setContainerDataSource(new IndexedContainer());
+       }
+
+       /**
+        * Creates an empty Select with caption.
+        */
+       public AbstractSelect(String caption) {
+               setContainerDataSource(new IndexedContainer());
+               setCaption(caption);
+       }
+
+       /**
+        * Creates a new select that is connected to a data-source.
+        * 
+        * @param caption
+        *            the Caption of the component.
+        * @param dataSource
+        *            the Container datasource to be selected from by this select.
+        */
+       public AbstractSelect(String caption, Container dataSource) {
+               setCaption(caption);
+               setContainerDataSource(dataSource);
+       }
+
+       /**
+        * Creates a new select that is filled from a collection of option values.
+        * 
+        * @param caption
+        *            the Caption of this field.
+        * @param options
+        *            the Collection containing the options.
+        */
+       public AbstractSelect(String caption, Collection options) {
+
+               // Creates the options container and add given options to it
+               Container c = new IndexedContainer();
+               if (options != null) {
+                       for (Iterator i = options.iterator(); i.hasNext();) {
+                               c.addItem(i.next());
+                       }
+               }
+
+               setCaption(caption);
+               setContainerDataSource(c);
+       }
+
+       /* Component methods **************************************************** */
+
+       /**
+        * Paints the content of this component.
+        * 
+        * @param target
+        *            the Paint Event.
+        * @throws PaintException
+        *             if the paint operation failed.
+        */
+       public void paintContent(PaintTarget target) throws PaintException {
+
+               // Paints field properties
+               super.paintContent(target);
+
+               // Paints select attributes
+               if (isMultiSelect()) {
+                       target.addAttribute("selectmode", "multi");
+               }
+               if (isNewItemsAllowed()) {
+                       target.addAttribute("allownewitem", true);
+               }
+               if (!isNullSelectionAllowed()) {
+                       target.addAttribute("nullselect", false);
+               }
+
+               // Constructs selected keys array
+               String[] selectedKeys;
+               if (isMultiSelect()) {
+                       selectedKeys = new String[((Set) getValue()).size()];
+               } else {
+                       selectedKeys = new String[(getValue() == null
+                                       && getNullSelectionItemId() == null ? 0 : 1)];
+               }
+
+               // ==
+               // Paints the options and create array of selected id keys
+               target.startTag("options");
+               int keyIndex = 0;
+               // Support for external null selection item id
+               Collection ids = getItemIds();
+               if (getNullSelectionItemId() != null
+                               && (!ids.contains(getNullSelectionItemId()))) {
+                       // Gets the option attribute values
+                       Object id = getNullSelectionItemId();
+                       String key = this.itemIdMapper.key(id);
+                       String caption = getItemCaption(id);
+                       Resource icon = getItemIcon(id);
+                       // Paints 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");
+               }
+
+               Iterator i = getItemIds().iterator();
+               // Paints the available selection options from data source
+               while (i.hasNext()) {
+                       // Gets the option attribute values
+                       Object id = i.next();
+                       String key = this.itemIdMapper.key(id);
+                       String caption = getItemCaption(id);
+                       Resource icon = getItemIcon(id); // Paints the 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("options");
+               // ==
+
+               // Paint variables
+               target.addVariable(this, "selected", selectedKeys);
+               if (isNewItemsAllowed()) {
+                       target.addVariable(this, "newitem", "");
+               }
+
+       }
+
+       /**
+        * Invoked when the value of a variable has changed.
+        * 
+        * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object,
+        *      java.util.Map)
+        */
+       public void changeVariables(Object source, Map variables) {
+               // Try to set the property value
+
+               // New option entered (and it is allowed)
+               String newitem = (String) variables.get("newitem");
+               if (newitem != null && newitem.length() > 0) {
+
+                       // Checks for readonly
+                       if (isReadOnly()) {
+                               throw new Property.ReadOnlyException();
+                       }
+
+                       // Adds new option
+                       if (addItem(newitem) != null) {
+
+                               // Sets the caption property, if used
+                               if (getItemCaptionPropertyId() != null) {
+                                       try {
+                                               getContainerProperty(newitem,
+                                                               getItemCaptionPropertyId()).setValue(newitem);
+                                       } catch (Property.ConversionException ignored) {
+                                               // The conversion exception is safely ignored, the
+                                               // caption is
+                                               // just missing
+                                       }
+                               }
+                       }
+               }
+
+               // Selection change
+               if (variables.containsKey("selected")) {
+                       String[] ka = (String[]) variables.get("selected");
+
+                       // Multiselect mode
+                       if (isMultiSelect()) {
+
+                               // TODO Optimize by adding repaintNotNeeded when applicable
+
+                               // Converts the key-array to id-set
+                               LinkedList s = new LinkedList();
+                               for (int i = 0; i < ka.length; i++) {
+                                       Object id = this.itemIdMapper.get(ka[i]);
+                                       if (id != null && containsId(id)) {
+                                               s.add(id);
+                                       } else if (this.itemIdMapper.isNewIdKey(ka[i])
+                                                       && newitem != null && newitem.length() > 0) {
+                                               s.add(newitem);
+                                       }
+                               }
+
+                               // Limits the deselection to the set of visible items
+                               // (non-visible items can not be deselected)
+                               Collection visible = getVisibleItemIds();
+                               if (visible != null) {
+                                       Set newsel = (Set) getValue();
+                                       if (newsel == null) {
+                                               newsel = new HashSet();
+                                       } else {
+                                               newsel = new HashSet(newsel);
+                                       }
+                                       newsel.removeAll(visible);
+                                       newsel.addAll(s);
+                                       setValue(newsel, true);
+                               }
+                       } else {
+                               // Single select mode
+                               if (ka.length == 0) {
+                                       // Allows deselection only if the deselected item is visible
+                                       Object current = getValue();
+                                       Collection visible = getVisibleItemIds();
+                                       if (visible != null && visible.contains(current)) {
+                                               setValue(null, true);
+                                       }
+                               } else {
+                                       Object id = this.itemIdMapper.get(ka[0]);
+                                       if (id != null && id.equals(getNullSelectionItemId())) {
+                                               setValue(null, true);
+                                       } else if (this.itemIdMapper.isNewIdKey(ka[0])) {
+                                               setValue(newitem);
+                                       } else {
+                                               setValue(id, true);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Gets the component UIDL tag.
+        * 
+        * @return the Component UIDL tag as string.
+        */
+       public String getTag() {
+               return "select";
+       }
+
+       /**
+        * Gets 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() {
+               if (isVisible()) {
+                       return getItemIds();
+               }
+               return null;
+       }
+
+       /* Property methods ***************************************************** */
+
+       /**
+        * Returns the type of the property. <code>getValue</code> and
+        * <code>setValue</code> methods must be compatible with this type: one
+        * can safely cast <code>getValue</code> to given type and pass any
+        * variable assignable to this type as a parameter to <code>setValue</code>.
+        * 
+        * @return the Type of the property.
+        */
+       public Class getType() {
+               if (isMultiSelect()) {
+                       return Set.class;
+               } else {
+                       return Object.class;
+               }
+       }
+
+       /**
+        * Gets the selected item id or in multiselect mode a set of selected ids.
+        * 
+        * @see com.itmill.toolkit.ui.AbstractField#getValue()
+        */
+       public Object getValue() {
+               Object retValue = super.getValue();
+
+               if (isMultiSelect()) {
+
+                       // If the return value is not a set
+                       if (retValue == null) {
+                               return new HashSet();
+                       }
+                       if (retValue instanceof Set) {
+                               return Collections.unmodifiableSet((Set) retValue);
+                       } else if (retValue instanceof Collection) {
+                               return new HashSet((Collection) retValue);
+                       } else {
+                               Set s = new HashSet();
+                               if (this.items.containsId(retValue)) {
+                                       s.add(retValue);
+                               }
+                               return s;
+                       }
+
+               } else {
+                       return retValue;
+               }
+       }
+
+       /**
+        * Sets 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>
+        * 
+        * @param newValue
+        *            the New selected item or collection of selected items.
+        * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object)
+        */
+       public void setValue(Object newValue) throws Property.ReadOnlyException,
+                       Property.ConversionException {
+               setValue(newValue, false);
+       }
+
+       /**
+        * Sets 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>
+        * 
+        * @param newValue
+        *            the New selected item or collection of selected items.
+        * @param repaintIsNotNeeded
+        *            True if caller is sure that repaint is not needed.
+        * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object,
+        *      java.lang.Boolean)
+        */
+       protected void setValue(Object newValue, boolean repaintIsNotNeeded)
+                       throws Property.ReadOnlyException, Property.ConversionException {
+
+               if (isMultiSelect()) {
+                       if (newValue == null) {
+                               super.setValue(new HashSet(), repaintIsNotNeeded);
+                       } else if (Collection.class.isAssignableFrom(newValue.getClass())) {
+                               super.setValue(new HashSet((Collection) newValue),
+                                               repaintIsNotNeeded);
+                       }
+               } else if (newValue == null || this.items.containsId(newValue)) {
+                       super.setValue(newValue, repaintIsNotNeeded);
+               }
+       }
+
+       /* Container methods **************************************************** */
+
+       /**
+        * Gets the item from the container with given id. If the container does not
+        * contain the requested item, null is returned.
+        * 
+        * @param itemId
+        *            the item id.
+        * @return the item from the container.
+        */
+       public Item getItem(Object itemId) {
+               return this.items.getItem(itemId);
+       }
+
+       /**
+        * Gets the item Id collection from the container.
+        * 
+        * @return the Collection of item ids.
+        */
+       public Collection getItemIds() {
+               return this.items.getItemIds();
+       }
+
+       /**
+        * Gets the property Id collection from the container.
+        * 
+        * @return the Collection of property ids.
+        */
+       public Collection getContainerPropertyIds() {
+               return this.items.getContainerPropertyIds();
+       }
+
+       /**
+        * Gets the property type.
+        * 
+        * @param propertyId
+        *            the Id identifying the property.
+        * @see com.itmill.toolkit.data.Container#getType(java.lang.Object)
+        */
+       public Class getType(Object propertyId) {
+               return this.items.getType(propertyId);
+       }
+
+       /*
+        * Gets the number of items in the container.
+        * 
+        * @return the Number of items in the container.
+        * 
+        * @see com.itmill.toolkit.data.Container#size()
+        */
+       public int size() {
+               return this.items.size();
+       }
+
+       /**
+        * Tests, if the collection contains an item with given id.
+        * 
+        * @param itemId
+        *            the Id the of item to be tested.
+        */
+       public boolean containsId(Object itemId) {
+               if (itemId != null) {
+                       return this.items.containsId(itemId);
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * Gets the Property identified by the given itemId and propertyId from the
+        * Container
+        * 
+        * @see com.itmill.toolkit.data.Container#getContainerProperty(Object,
+        *      Object)
+        */
+       public Property getContainerProperty(Object itemId, Object propertyId) {
+               return this.items.getContainerProperty(itemId, propertyId);
+       }
+
+       /* Container.Managed methods ******************************************** */
+
+       /**
+        * Adds the 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 if the operation succeeded.
+        * @see com.itmill.toolkit.data.Container#addContainerProperty(java.lang.Object,
+        *      java.lang.Class, java.lang.Object)
+        */
+       public boolean addContainerProperty(Object propertyId, Class type,
+                       Object defaultValue) throws UnsupportedOperationException {
+
+               boolean retval = this.items.addContainerProperty(propertyId, type,
+                               defaultValue);
+               if (retval
+                               && !(this.items instanceof Container.PropertySetChangeNotifier)) {
+                       firePropertySetChange();
+               }
+               return retval;
+       }
+
+       /**
+        * Removes all items from the container.
+        * 
+        * This functionality is optional. If the function is unsupported, it always
+        * returns false.
+        * 
+        * @return True if the operation succeeded.
+        * @see com.itmill.toolkit.data.Container#removeAllItems()
+        */
+       public boolean removeAllItems() throws UnsupportedOperationException {
+
+               boolean retval = this.items.removeAllItems();
+               this.itemIdMapper.removeAll();
+               if (retval) {
+                       setValue(null);
+                       if (!(this.items instanceof Container.ItemSetChangeNotifier)) {
+                               fireItemSetChange();
+                       }
+               }
+               return retval;
+       }
+
+       /**
+        * Creates 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 the Id of the created item or null in case of failure.
+        * @see com.itmill.toolkit.data.Container#addItem()
+        */
+       public Object addItem() throws UnsupportedOperationException {
+
+               Object retval = this.items.addItem();
+               if (retval != null
+                               && !(this.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.
+        * 
+        * This functionality is optional. If the function is unsupported, it always
+        * returns null.
+        * 
+        * @param itemId
+        *            the Identification of the item to be created.
+        * @return the Created item with the given id, or null in case of failure.
+        * @see com.itmill.toolkit.data.Container#addItem(java.lang.Object)
+        */
+       public Item addItem(Object itemId) throws UnsupportedOperationException {
+
+               Item retval = this.items.addItem(itemId);
+               if (retval != null
+                               && !(this.items instanceof Container.ItemSetChangeNotifier)) {
+                       fireItemSetChange();
+               }
+               return retval;
+       }
+
+       /**
+        * Removes the item identified by Id from the container. This functionality
+        * is optional. If the function is not implemented, the functions allways
+        * returns false.
+        * 
+        * @return True if the operation succeeded.
+        * @see com.itmill.toolkit.data.Container#removeItem(java.lang.Object)
+        */
+       public boolean removeItem(Object itemId)
+                       throws UnsupportedOperationException {
+
+               unselect(itemId);
+               boolean retval = this.items.removeItem(itemId);
+               this.itemIdMapper.remove(itemId);
+               if (retval && !(this.items instanceof Container.ItemSetChangeNotifier)) {
+                       fireItemSetChange();
+               }
+               return retval;
+       }
+
+       /**
+        * Removes the 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 if the operation succeeded.
+        * @see com.itmill.toolkit.data.Container#removeContainerProperty(java.lang.Object)
+        */
+       public boolean removeContainerProperty(Object propertyId)
+                       throws UnsupportedOperationException {
+
+               boolean retval = this.items.removeContainerProperty(propertyId);
+               if (retval
+                               && !(this.items instanceof Container.PropertySetChangeNotifier)) {
+                       firePropertySetChange();
+               }
+               return retval;
+       }
+
+       /* Container.Viewer methods ********************************************* */
+
+       /**
+        * Sets the container as data-source for viewing.
+        * 
+        * @param newDataSource
+        *            the new data source.
+        */
+       public void setContainerDataSource(Container newDataSource) {
+               if (newDataSource == null) {
+                       newDataSource = new IndexedContainer();
+               }
+
+               if (this.items != newDataSource) {
+
+                       // Removes listeners from the old datasource
+                       if (this.items != null) {
+                               try {
+                                       ((Container.ItemSetChangeNotifier) this.items)
+                                                       .removeListener(this);
+                               } catch (ClassCastException ignored) {
+                                       // Ignored
+                               }
+                               try {
+                                       ((Container.PropertySetChangeNotifier) this.items)
+                                                       .removeListener(this);
+                               } catch (ClassCastException ignored) {
+                                       // Ignored
+                               }
+                       }
+
+                       // Assigns new data source
+                       this.items = newDataSource;
+
+                       // Clears itemIdMapper also
+                       this.itemIdMapper.removeAll();
+
+                       // Adds listeners
+                       if (this.items != null) {
+                               try {
+                                       ((Container.ItemSetChangeNotifier) this.items)
+                                                       .addListener(this);
+                               } catch (ClassCastException ignored) {
+                                       // Ignored
+                               }
+                               try {
+                                       ((Container.PropertySetChangeNotifier) this.items)
+                                                       .addListener(this);
+                               } catch (ClassCastException ignored) {
+                                       // Ignored
+                               }
+                       }
+
+                       // TODO: This should be conditional
+                       fireValueChange(false);
+               }
+       }
+
+       /**
+        * Gets the viewing data-source container.
+        * 
+        * @see com.itmill.toolkit.data.Container.Viewer#getContainerDataSource()
+        */
+       public Container getContainerDataSource() {
+               return this.items;
+       }
+
+       /* Select attributes **************************************************** */
+
+       /**
+        * Is the select in multiselect mode? In multiselect mode
+        * 
+        * @return the Value of property multiSelect.
+        */
+       public boolean isMultiSelect() {
+               return this.multiSelect;
+       }
+
+       /**
+        * Sets 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
+        *            the New value of property multiSelect.
+        */
+       public void setMultiSelect(boolean multiSelect) {
+
+               if (multiSelect != this.multiSelect) {
+
+                       // Selection before mode change
+                       Object oldValue = getValue();
+
+                       this.multiSelect = multiSelect;
+
+                       // Convert the value type
+                       if (multiSelect) {
+                               Set s = new HashSet();
+                               if (oldValue != null) {
+                                       s.add(oldValue);
+                               }
+                               setValue(s);
+                       } else {
+                               Set s = (Set) oldValue;
+                               if (s == null || s.isEmpty()) {
+                                       setValue(null);
+                               } else {
+                                       // Set the single select to contain only the first
+                                       // selected value in the multiselect
+                                       setValue(s.iterator().next());
+                               }
+                       }
+
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * 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 if additions are allowed.
+        */
+       public boolean isNewItemsAllowed() {
+
+               return this.allowNewOptions;
+       }
+
+       /**
+        * Enables or disables possibility to add new options by the user.
+        * 
+        * @param allowNewOptions
+        *            the New value of property allowNewOptions.
+        */
+       public void setNewItemsAllowed(boolean allowNewOptions) {
+
+               // Only handle change requests
+               if (this.allowNewOptions != allowNewOptions) {
+
+                       this.allowNewOptions = allowNewOptions;
+
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * 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
+        *            the New caption.
+        */
+       public void setItemCaption(Object itemId, String caption) {
+               if (itemId != null) {
+                       this.itemCaptions.put(itemId, caption);
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * Gets 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 the caption for specified item.
+        */
+       public String getItemCaption(Object itemId) {
+
+               // Null items can not be found
+               if (itemId == null) {
+                       return null;
+               }
+
+               String caption = null;
+
+               switch (getItemCaptionMode()) {
+
+               case ITEM_CAPTION_MODE_ID:
+                       caption = itemId.toString();
+                       break;
+
+               case ITEM_CAPTION_MODE_INDEX:
+                       try {
+                               caption = String.valueOf(((Container.Indexed) this.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) this.itemCaptions.get(itemId);
+                       break;
+
+               case ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID:
+                       caption = (String) this.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 : "";
+       }
+
+       /**
+        * Sets the icon for an item.
+        * 
+        * @param itemId
+        *            the id of the item to be assigned an icon.
+        * @param icon
+        *            the New icon.
+        */
+       public void setItemIcon(Object itemId, Resource icon) {
+               if (itemId != null) {
+                       if (icon == null) {
+                               this.itemIcons.remove(itemId);
+                       } else {
+                               this.itemIcons.put(itemId, icon);
+                       }
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * Gets the item icon.
+        * 
+        * @param itemId
+        *            the id of the item to be assigned an icon.
+        * @return the Icon for the item or null, if not specified.
+        */
+       public Resource getItemIcon(Object itemId) {
+               Resource explicit = (Resource) this.itemIcons.get(itemId);
+               if (explicit != null) {
+                       return explicit;
+               }
+
+               if (getItemIconPropertyId() == null) {
+                       return null;
+               }
+
+               Property ip = getContainerProperty(itemId, getItemIconPropertyId());
+               if (ip == null) {
+                       return null;
+               }
+               Object icon = ip.getValue();
+               if (icon instanceof Resource) {
+                       return (Resource) icon;
+               }
+
+               return null;
+       }
+
+       /**
+        * Sets 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>
+        * </ul>
+        * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default
+        * mode.
+        * </p>
+        * 
+        * @param mode
+        *            the One of the modes listed above.
+        */
+       public void setItemCaptionMode(int mode) {
+               if (ITEM_CAPTION_MODE_ID <= mode && mode <= ITEM_CAPTION_MODE_PROPERTY) {
+                       this.itemCaptionMode = mode;
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * Gets 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>
+        * </ul>
+        * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default
+        * mode.
+        * </p>
+        * 
+        * @return the One of the modes listed above.
+        */
+       public int getItemCaptionMode() {
+               return this.itemCaptionMode;
+       }
+
+       /**
+        * Sets 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 property id to null disables this feature. The id is null by
+        * default
+        * </p>.
+        * 
+        * @param propertyId
+        *            the id of the property.
+        * 
+        */
+       public void setItemCaptionPropertyId(Object propertyId) {
+               if (propertyId != null) {
+                       this.itemCaptionPropertyId = propertyId;
+                       setItemCaptionMode(ITEM_CAPTION_MODE_PROPERTY);
+                       requestRepaint();
+               } else {
+                       this.itemCaptionPropertyId = null;
+                       if (getItemCaptionMode() == ITEM_CAPTION_MODE_PROPERTY) {
+                               setItemCaptionMode(ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID);
+                       }
+                       requestRepaint();
+               }
+       }
+
+       /**
+        * Gets the item caption property.
+        * 
+        * @return the Id of the property used as item caption source.
+        */
+       public Object getItemCaptionPropertyId() {
+               return this.itemCaptionPropertyId;
+       }
+
+       /**
+        * Sets 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>
+        * Note : 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>.
+        * 
+        * @param propertyId
+        *            the Id of the property that specifies icons for items.
+        */
+       public void setItemIconPropertyId(Object propertyId) {
+               if ((propertyId != null)
+                               && Resource.class.isAssignableFrom(getType(propertyId))) {
+                       this.itemIconPropertyId = propertyId;
+                       requestRepaint();
+               } else {
+                       this.itemIconPropertyId = null;
+               }
+       }
+
+       /**
+        * Gets 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>
+        * Note : 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>.
+        * 
+        * @return the Id of the property containing the item icons.
+        */
+       public Object getItemIconPropertyId() {
+               return this.itemIconPropertyId;
+       }
+
+       /**
+        * Tests 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>
+        * 
+        * @param itemId
+        *            the Id the of the item to be tested.
+        * @see #getNullSelectionItemId()
+        * @see #setNullSelectionItemId(Object)
+        * 
+        */
+       public boolean isSelected(Object itemId) {
+               if (itemId == null) {
+                       return false;
+               }
+               if (isMultiSelect()) {
+                       return ((Set) getValue()).contains(itemId);
+               } else {
+                       Object value = getValue();
+                       return itemId.equals(value == null ? getNullSelectionItemId()
+                                       : value);
+               }
+       }
+
+       /**
+        * Selects an item.
+        * 
+        * <p>
+        * In single select mode selecting item identified by
+        * {@link #getNullSelectionItemId()} sets the value of the property to null.
+        * </p>
+        * 
+        * @param itemId
+        *            the tem to be selected.
+        * @see #getNullSelectionItemId()
+        * @see #setNullSelectionItemId(Object)
+        * 
+        */
+       public void select(Object itemId) {
+               if (!isSelected(itemId) && this.items.containsId(itemId)) {
+                       if (isMultiSelect()) {
+                               Set s = new HashSet((Set) getValue());
+                               s.add(itemId);
+                               setValue(s);
+                       } else if (itemId.equals(getNullSelectionItemId())) {
+                               setValue(null);
+                       } else {
+                               setValue(itemId);
+                       }
+               }
+       }
+
+       /**
+        * Unselects an item.
+        * 
+        * @param itemId
+        *            the Item to be unselected.
+        * @see #getNullSelectionItemId()
+        * @see #setNullSelectionItemId(Object)
+        * 
+        */
+       public void unselect(Object itemId) {
+               if (isSelected(itemId)) {
+                       if (isMultiSelect()) {
+                               Set s = new HashSet((Set) getValue());
+                               s.remove(itemId);
+                               setValue(s);
+                       } else {
+                               setValue(null);
+                       }
+               }
+       }
+
+       /**
+        * Notifies this listener that the Containers contents has changed.
+        * 
+        * @see com.itmill.toolkit.data.Container.PropertySetChangeListener#containerPropertySetChange(com.itmill.toolkit.data.Container.PropertySetChangeEvent)
+        */
+       public void containerPropertySetChange(
+                       Container.PropertySetChangeEvent event) {
+               firePropertySetChange();
+       }
+
+       /**
+        * Adds a new Property set change listener for this Container.
+        * 
+        * @see com.itmill.toolkit.data.Container.PropertySetChangeNotifier#addListener(com.itmill.toolkit.data.Container.PropertySetChangeListener)
+        */
+       public void addListener(Container.PropertySetChangeListener listener) {
+               if (this.propertySetEventListeners == null) {
+                       this.propertySetEventListeners = new LinkedList();
+               }
+               this.propertySetEventListeners.add(listener);
+       }
+
+       /**
+        * Removes a previously registered Property set change listener.
+        * 
+        * @see com.itmill.toolkit.data.Container.PropertySetChangeNotifier#removeListener(com.itmill.toolkit.data.Container.PropertySetChangeListener)
+        */
+       public void removeListener(Container.PropertySetChangeListener listener) {
+               if (this.propertySetEventListeners != null) {
+                       this.propertySetEventListeners.remove(listener);
+                       if (this.propertySetEventListeners.isEmpty()) {
+                               this.propertySetEventListeners = null;
+                       }
+               }
+       }
+
+       /**
+        * Adds an Item set change listener for the object.
+        * 
+        * @see com.itmill.toolkit.data.Container.ItemSetChangeNotifier#addListener(com.itmill.toolkit.data.Container.ItemSetChangeListener)
+        */
+       public void addListener(Container.ItemSetChangeListener listener) {
+               if (this.itemSetEventListeners == null) {
+                       this.itemSetEventListeners = new LinkedList();
+               }
+               this.itemSetEventListeners.add(listener);
+       }
+
+       /**
+        * Removes the Item set change listener from the object.
+        * 
+        * @see com.itmill.toolkit.data.Container.ItemSetChangeNotifier#removeListener(com.itmill.toolkit.data.Container.ItemSetChangeListener)
+        */
+       public void removeListener(Container.ItemSetChangeListener listener) {
+               if (this.itemSetEventListeners != null) {
+                       this.itemSetEventListeners.remove(listener);
+                       if (this.itemSetEventListeners.isEmpty()) {
+                               this.itemSetEventListeners = null;
+                       }
+               }
+       }
+
+       /**
+        * Lets the listener know a Containers Item set has changed.
+        * 
+        * @see com.itmill.toolkit.data.Container.ItemSetChangeListener#containerItemSetChange(com.itmill.toolkit.data.Container.ItemSetChangeEvent)
+        */
+       public void containerItemSetChange(Container.ItemSetChangeEvent event) {
+               // Clears the item id mapping table
+               this.itemIdMapper.removeAll();
+
+               // Notify all listeners
+               fireItemSetChange();
+       }
+
+       /**
+        * Fires the property set change event.
+        */
+       protected void firePropertySetChange() {
+               if (this.propertySetEventListeners != null
+                               && !this.propertySetEventListeners.isEmpty()) {
+                       Container.PropertySetChangeEvent event = new PropertySetChangeEvent();
+                       Object[] listeners = this.propertySetEventListeners.toArray();
+                       for (int i = 0; i < listeners.length; i++) {
+                               ((Container.PropertySetChangeListener) listeners[i])
+                                               .containerPropertySetChange(event);
+                       }
+               }
+               requestRepaint();
+       }
+
+       /**
+        * Fires the item set change event.
+        */
+       protected void fireItemSetChange() {
+               if (this.itemSetEventListeners != null
+                               && !this.itemSetEventListeners.isEmpty()) {
+                       Container.ItemSetChangeEvent event = new ItemSetChangeEvent();
+                       Object[] listeners = this.itemSetEventListeners.toArray();
+                       for (int i = 0; i < listeners.length; i++) {
+                               ((Container.ItemSetChangeListener) listeners[i])
+                                               .containerItemSetChange(event);
+                       }
+               }
+               requestRepaint();
+       }
+
+       /**
+        * Implementation of item set change event.
+        */
+       private class ItemSetChangeEvent implements Container.ItemSetChangeEvent {
+
+               /**
+                * Gets the Property where the event occurred.
+                * 
+                * @see com.itmill.toolkit.data.Container.ItemSetChangeEvent#getContainer()
+                */
+               public Container getContainer() {
+                       return AbstractSelect.this;
+               }
+
+       }
+
+       /**
+        * Implementation of property set change event.
+        */
+       private class PropertySetChangeEvent implements
+                       Container.PropertySetChangeEvent {
+
+               /**
+                * Retrieves the Container whose contents have been modified.
+                * 
+                * @see com.itmill.toolkit.data.Container.PropertySetChangeEvent#getContainer()
+                */
+               public Container getContainer() {
+                       return AbstractSelect.this;
+               }
+
+       }
+
+       // TODO javadoc
+       public void setNullSelectionAllowed(boolean nullSelectionAllowed) {
+               this.nullSelectionAllowed = nullSelectionAllowed;
+       }
+
+       // TODO javadoc
+       public boolean isNullSelectionAllowed() {
+               return this.nullSelectionAllowed;
+       }
+
+       /**
+        * 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>
+        * 
+        * @return the Object Null value item id.
+        * @see #setNullSelectionItemId(Object)
+        * @see #isSelected(Object)
+        * @see #select(Object)
+        */
+       public final Object getNullSelectionItemId() {
+               return this.nullSelectionItemId;
+       }
+
+       /**
+        * 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>
+        * 
+        * @param nullSelectionItemId
+        *            the nullSelectionItemId to set.
+        * @see #getNullSelectionItemId()
+        * @see #isSelected(Object)
+        * @see #select(Object)
+        */
+       public void setNullSelectionItemId(Object nullSelectionItemId) {
+               this.nullSelectionItemId = nullSelectionItemId;
+       }
+
+       /**
+        * Notifies the component that it is connected to an application.
+        * 
+        * @see com.itmill.toolkit.ui.AbstractField#attach()
+        */
+       public void attach() {
+               super.attach();
+       }
+
+       /**
+        * Detaches the component from application.
+        * 
+        * @see com.itmill.toolkit.ui.AbstractComponent#detach()
+        */
+       public void detach() {
+               super.detach();
+       }
+
+}
index 187069e8c788b88f0a006c9598d5bfced78e3404..8de651ebd6eb682acbfec8e60922cd3e703778cd 100644 (file)
@@ -10,17 +10,17 @@ import com.itmill.toolkit.terminal.PaintException;
 import com.itmill.toolkit.terminal.PaintTarget;
 
 /**
- * Since TK5 default select is customized component with mane advanced features
+ * Since TK5 default select is customized component with many advanced features
  * over terminals native select components. Sometimes "native" select may still
  * be the best option. Terminal renders this select with its native select
  * widget.
  */
-public class NativeSelect extends Select {
+public class NativeSelect extends AbstractSelect {
 
        public NativeSelect() {
                super();
        }
-       
+
        public NativeSelect(String caption, Collection options) {
                super(caption, options);
        }
index b5bb594563856bb9e5e523cb6250f82472606814..f58667c43edc09f230cfd15ece6f46805b5f2875 100644 (file)
@@ -12,7 +12,7 @@ import com.itmill.toolkit.terminal.PaintTarget;
 /**
  * Configures select to be used as an option group.
  */
-public class OptionGroup extends Select {
+public class OptionGroup extends AbstractSelect {
 
        public OptionGroup() {
                super();
index 961e0c9b01d381cea28be2b3475a2b85c0328c71..e56666f3ad284074338a725f196c785618b1af38 100644 (file)
 package com.itmill.toolkit.ui;
 
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 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.KeyMapper;
 import com.itmill.toolkit.terminal.PaintException;
 import com.itmill.toolkit.terminal.PaintTarget;
 import com.itmill.toolkit.terminal.Resource;
-import com.itmill.toolkit.ui.select.OptionFilter;
-import com.itmill.toolkit.ui.select.StartsWithFilter;
 
 /**
  * <p>
@@ -66,199 +60,42 @@ import com.itmill.toolkit.ui.select.StartsWithFilter;
  * @VERSION@
  * @since 3.0
  */
-public class Select extends AbstractField implements Container,
-               Container.Viewer, Container.PropertySetChangeListener,
-               Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier,
-               Container.ItemSetChangeListener {
+public class Select extends AbstractSelect implements AbstractSelect.Filtering {
 
        /**
-        * Item caption mode: Item's ID's <code>String</code> representation is
-        * used as caption.
+        * Holds value of property pageLength. 0 disables paging.
         */
-       public static final int ITEM_CAPTION_MODE_ID = 0;
+       protected int pageLength = 15;
 
-       /**
-        * 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
-        * {@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>.
-        */
-       public static final int ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID = 3;
-
-       /**
-        * 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.
-        */
-       public static final int ITEM_CAPTION_MODE_ICON_ONLY = 5;
-
-       /**
-        * Item caption mode: Item captions are read from property specified with
-        * <code>setItemCaptionPropertyId</code>.
-        */
-       public static final int ITEM_CAPTION_MODE_PROPERTY = 6;
-
-       /**
-        * Is the select in multiselect mode?
-        */
-       private boolean multiSelect = false;
-
-       /**
-        * Select options.
-        */
-       protected Container items;
-
-       /**
-        * Is the user allowed to add new options?
-        */
-       private boolean allowNewOptions;
-
-       /**
-        * Keymapper used to map key values.
-        */
-       protected KeyMapper itemIdMapper = new KeyMapper();
-
-       /**
-        * Item icons.
-        */
-       private HashMap itemIcons = new HashMap();
+       // current page when the user is 'paging' trough options
+       private int currentPage;
 
-       /**
-        * Item captions.
-        */
-       private HashMap itemCaptions = new HashMap();
-
-       /**
-        * Item caption mode.
-        */
-       private int itemCaptionMode = ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID;
-
-       /**
-        * Item caption source property id.
-        */
-       private Object itemCaptionPropertyId = null;
-
-       /**
-        * Item icon source property id.
-        */
-       private Object itemIconPropertyId = null;
-
-       /**
-        * List of property set change event listeners.
-        */
-       private LinkedList propertySetEventListeners = null;
-
-       /**
-        * List of item set change event listeners.
-        */
-       private LinkedList itemSetEventListeners = null;
-
-       /**
-        * 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>
-        */
-       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;
-       /**
-        * Number of options to stream per request ('page size') when lazyLoading
-        * options.
-        */
-       private int lazyLoadingPageLength = 20;
-
-       private OptionFilter optionFilter;
-
-       private boolean isLazyLoading;
-
-       private int page;
+       private int filteringMode = FILTERINGMODE_OFF;
 
        private String filterstring;
-
-       /**
-        * How many visible columns (~characters) does select occupy visually. Used
-        * to size select appropriately. Minus one sets to 100% width.
-        */
-       private int columns = -1;
+       private String prevfilterstring;
+       private List filteredOptions;
 
        /* Constructors ********************************************************* */
 
-       /**
-        * Creates an empty Select. The caption is not used.
-        */
+       /* Component methods **************************************************** */
+
        public Select() {
-               setContainerDataSource(new IndexedContainer());
+               super();
        }
 
-       /**
-        * Creates an empty Select with caption.
-        */
-       public Select(String caption) {
-               setContainerDataSource(new IndexedContainer());
-               setCaption(caption);
+       public Select(String caption, Collection options) {
+               super(caption, options);
        }
 
-       /**
-        * Creates a new select that is connected to a data-source.
-        * 
-        * @param caption
-        *            the Caption of the component.
-        * @param dataSource
-        *            the Container datasource to be selected from by this select.
-        */
        public Select(String caption, Container dataSource) {
-               setCaption(caption);
-               setContainerDataSource(dataSource);
+               super(caption, dataSource);
        }
 
-       /**
-        * Creates a new select that is filled from a collection of option values.
-        * 
-        * @param caption
-        *            the Caption of this field.
-        * @param options
-        *            the Collection containing the options.
-        */
-       public Select(String caption, Collection options) {
-
-               // Creates the options container and add given options to it
-               Container c = new IndexedContainer();
-               if (options != null)
-                       for (Iterator i = options.iterator(); i.hasNext();)
-                               c.addItem(i.next());
-
-               setCaption(caption);
-               setContainerDataSource((Container) c);
+       public Select(String caption) {
+               super(caption);
        }
 
-       /* Component methods **************************************************** */
-
        /**
         * Paints the content of this component.
         * 
@@ -268,84 +105,104 @@ public class Select extends AbstractField implements Container,
         *             if the paint operation failed.
         */
        public void paintContent(PaintTarget target) throws PaintException {
+               // Focus control id
+               if (getFocusableId() > 0) {
+                       target.addAttribute("focusid", getFocusableId());
+               }
+
+               // The tab ordering number
+               if (getTabIndex() > 0) {
+                       target.addAttribute("tabindex", getTabIndex());
+               }
+
+               // If the field is modified, but not committed, set modified attribute
+               if (isModified()) {
+                       target.addAttribute("modified", true);
+               }
 
-               // Paints field properties
-               super.paintContent(target);
+               // Adds the required attribute
+               if (isRequired()) {
+                       target.addAttribute("required", true);
+               }
 
                // Paints select attributes
-               if (isMultiSelect())
+               if (isMultiSelect()) {
                        target.addAttribute("selectmode", "multi");
-               if (isNewItemsAllowed())
+               }
+               if (isNewItemsAllowed()) {
                        target.addAttribute("allownewitem", true);
-               if (getColumns() > -1)
-                       target.addAttribute("cols", getColumns());
+               }
+               if (!isNullSelectionAllowed()) {
+                       target.addAttribute("nullselect", false);
+               }
 
                // Constructs selected keys array
                String[] selectedKeys;
-               if (isMultiSelect())
+               if (isMultiSelect()) {
                        selectedKeys = new String[((Set) getValue()).size()];
-               else
+               } else {
                        selectedKeys = new String[(getValue() == null
                                        && getNullSelectionItemId() == null ? 0 : 1)];
+               }
+
+               target.addAttribute("filteringmode", getFilteringMode());
 
                // Paints the options and create array of selected id keys
-               target.startTag("options");
                // TODO Also use conventional rendering if lazy loading is not supported
                // by terminal
                int keyIndex = 0;
 
-               if (!isLazyLoading()) {
-                       // Support for external null selection item id
-                       Collection ids = getItemIds();
-                       if (getNullSelectionItemId() != null
-                                       && (!ids.contains(getNullSelectionItemId()))) {
-
-                               // Gets the option attribute values
-                               Object id = getNullSelectionItemId();
-                               String key = itemIdMapper.key(id);
-                               String caption = getItemCaption(id);
-                               Resource icon = getItemIcon(id);
-
-                               // Paints 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");
+               /*
+                * if (!isLazyLoading()) { // Support for external null selection item
+                * id Collection ids = getItemIds(); if (getNullSelectionItemId() !=
+                * null && (!ids.contains(getNullSelectionItemId()))) { // Gets the
+                * option attribute values Object id = getNullSelectionItemId(); String
+                * key = this.itemIdMapper.key(id); String caption = getItemCaption(id);
+                * Resource icon = getItemIcon(id); // Paints 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"); } }
+                */
+               /*
+                * Iterator i; if (this.filterstring != null) { i =
+                * this.optionFilter.filter(this.filterstring,
+                * this.lazyLoadingPageLength, this.page).iterator();
+                * target.addAttribute("totalMatches", this.optionFilter
+                * .getMatchCount()); } else { i = getItemIds().iterator(); }
+                */
+               List options = getFilteredOptions();
+               if (options.size() > this.pageLength) {
+                       int first = this.currentPage * this.pageLength;
+                       int last = first + this.pageLength;
+                       if (options.size() < last) {
+                               last = options.size();
                        }
+                       options = options.subList(first, last);
                }
-
-               Iterator i;
-               if (isLazyLoading()) {
-                       i = optionFilter.filter(filterstring, lazyLoadingPageLength, page)
-                                       .iterator();
-                       target.addAttribute("totalMatches", optionFilter.getMatchCount());
-               } else {
-                       i = getItemIds().iterator();
-               }
-
+               Iterator i = options.iterator();
                // Paints the available selection options from data source
+
+               target.startTag("options");
                while (i.hasNext()) {
 
                        // Gets the option attribute values
                        Object id = i.next();
-                       String key = itemIdMapper.key(id);
+                       String key = this.itemIdMapper.key(id);
                        String caption = getItemCaption(id);
                        Resource icon = getItemIcon(id);
 
                        // Paints the option
                        target.startTag("so");
-                       if (icon != null)
+                       if (icon != null) {
                                target.addAttribute("icon", icon);
+                       }
                        target.addAttribute("caption", caption);
-                       if (id != null && id.equals(getNullSelectionItemId()))
+                       if (id != null && id.equals(getNullSelectionItemId())) {
                                target.addAttribute("nullselection", true);
+                       }
                        target.addAttribute("key", key);
                        if (isSelected(id) && keyIndex < selectedKeys.length) {
                                target.addAttribute("selected", true);
@@ -355,14 +212,62 @@ public class Select extends AbstractField implements Container,
                }
                target.endTag("options");
 
+               target.addAttribute("totalitems", size());
+               if (this.filteredOptions != null) {
+                       target.addAttribute("totalMatches", this.filteredOptions.size());
+               }
+
                // Paint variables
                target.addVariable(this, "selected", selectedKeys);
-               if (isNewItemsAllowed())
+               if (isNewItemsAllowed()) {
                        target.addVariable(this, "newitem", "");
-               if (isLazyLoading()) {
-                       target.addVariable(this, "filter", filterstring);
-                       target.addVariable(this, "page", page);
                }
+
+               target.addVariable(this, "filter", this.filterstring);
+               target.addVariable(this, "page", this.currentPage);
+
+       }
+
+       protected List getFilteredOptions() {
+               if (this.filterstring == null || this.filterstring.equals("")
+                               || this.filteringMode == FILTERINGMODE_OFF) {
+                       this.filteredOptions = new LinkedList(getItemIds());
+                       return this.filteredOptions;
+               }
+               if (this.filterstring.equals(this.prevfilterstring)) {
+                       return this.filteredOptions;
+               }
+
+               Collection items;
+               if (this.filterstring.startsWith(this.prevfilterstring)) {
+                       items = this.filteredOptions;
+               } else {
+                       items = getItemIds();
+               }
+
+               this.filteredOptions = new LinkedList();
+               for (Iterator it = items.iterator(); it.hasNext();) {
+                       Object itemId = it.next();
+                       String caption = getItemCaption(it);
+                       if (caption != null || caption.equals("")) {
+                               continue;
+                       }
+                       switch (this.filteringMode) {
+                       case FILTERINGMODE_CONTAINS:
+                               if (caption.indexOf(this.filterstring) > -1) {
+                                       this.filteredOptions.add(itemId);
+                               }
+                               break;
+                       case FILTERINGMODE_STARTSWITH:
+                       default:
+                               if (caption.startsWith(this.filterstring)) {
+                                       this.filteredOptions.add(itemId);
+                               }
+                               break;
+                       }
+               }
+
+               return this.filteredOptions;
        }
 
        /**
@@ -375,8 +280,8 @@ public class Select extends AbstractField implements Container,
                String newFilter;
                if ((newFilter = (String) variables.get("filter")) != null) {
                        // this is a filter request
-                       page = ((Integer) variables.get("page")).intValue();
-                       filterstring = newFilter;
+                       this.currentPage = ((Integer) variables.get("page")).intValue();
+                       this.filterstring = newFilter;
                        requestRepaint();
                        return;
                }
@@ -388,14 +293,15 @@ public class Select extends AbstractField implements Container,
                if (newitem != null && newitem.length() > 0) {
 
                        // Checks for readonly
-                       if (isReadOnly())
+                       if (isReadOnly()) {
                                throw new Property.ReadOnlyException();
+                       }
 
                        // Adds new option
                        if (addItem(newitem) != null) {
 
                                // Sets the caption property, if used
-                               if (getItemCaptionPropertyId() != null)
+                               if (getItemCaptionPropertyId() != null) {
                                        try {
                                                getContainerProperty(newitem,
                                                                getItemCaptionPropertyId()).setValue(newitem);
@@ -404,6 +310,7 @@ public class Select extends AbstractField implements Container,
                                                // caption is
                                                // just missing
                                        }
+                               }
                        }
                }
 
@@ -419,12 +326,13 @@ public class Select extends AbstractField implements Container,
                                // Converts the key-array to id-set
                                LinkedList s = new LinkedList();
                                for (int i = 0; i < ka.length; i++) {
-                                       Object id = itemIdMapper.get(ka[i]);
-                                       if (id != null && containsId(id))
+                                       Object id = this.itemIdMapper.get(ka[i]);
+                                       if (id != null && containsId(id)) {
                                                s.add(id);
-                                       else if (itemIdMapper.isNewIdKey(ka[i]) && newitem != null
-                                                       && newitem.length() > 0)
+                                       } else if (this.itemIdMapper.isNewIdKey(ka[i])
+                                                       && newitem != null && newitem.length() > 0) {
                                                s.add(newitem);
+                                       }
                                }
 
                                // Limits the deselection to the set of visible items
@@ -432,10 +340,11 @@ public class Select extends AbstractField implements Container,
                                Collection visible = getVisibleItemIds();
                                if (visible != null) {
                                        Set newsel = (Set) getValue();
-                                       if (newsel == null)
+                                       if (newsel == null) {
                                                newsel = new HashSet();
-                                       else
+                                       } else {
                                                newsel = new HashSet(newsel);
+                                       }
                                        newsel.removeAll(visible);
                                        newsel.addAll(s);
                                        setValue(newsel, true);
@@ -449,16 +358,18 @@ public class Select extends AbstractField implements Container,
                                        // Allows deselection only if the deselected item is visible
                                        Object current = getValue();
                                        Collection visible = getVisibleItemIds();
-                                       if (visible != null && visible.contains(current))
+                                       if (visible != null && visible.contains(current)) {
                                                setValue(null, true);
+                                       }
                                } else {
-                                       Object id = itemIdMapper.get(ka[0]);
-                                       if (id != null && id.equals(getNullSelectionItemId()))
+                                       Object id = this.itemIdMapper.get(ka[0]);
+                                       if (id != null && id.equals(getNullSelectionItemId())) {
                                                setValue(null, true);
-                                       else if (itemIdMapper.isNewIdKey(ka[0]))
+                                       } else if (this.itemIdMapper.isNewIdKey(ka[0])) {
                                                setValue(newitem);
-                                       else
+                                       } else {
                                                setValue(id, true);
+                                       }
                                }
                        }
                }
@@ -473,1048 +384,11 @@ public class Select extends AbstractField implements Container,
                return "select";
        }
 
-       /**
-        * Gets 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() {
-               if (isVisible())
-                       return getItemIds();
-               return null;
-       }
-
-       /* Property methods ***************************************************** */
-
-       /**
-        * Returns the type of the property. <code>getValue</code> and
-        * <code>setValue</code> methods must be compatible with this type: one
-        * can safely cast <code>getValue</code> to given type and pass any
-        * variable assignable to this type as a parameter to <code>setValue</code>.
-        * 
-        * @return the Type of the property.
-        */
-       public Class getType() {
-               if (isMultiSelect())
-                       return Set.class;
-               else
-                       return Object.class;
-       }
-
-       /**
-        * Gets the selected item id or in multiselect mode a set of selected ids.
-        * 
-        * @see com.itmill.toolkit.ui.AbstractField#getValue()
-        */
-       public Object getValue() {
-               Object retValue = super.getValue();
-
-               if (isMultiSelect()) {
-
-                       // If the return value is not a set
-                       if (retValue == null)
-                               return new HashSet();
-                       if (retValue instanceof Set) {
-                               return Collections.unmodifiableSet((Set) retValue);
-                       } else if (retValue instanceof Collection) {
-                               return new HashSet((Collection) retValue);
-                       } else {
-                               Set s = new HashSet();
-                               if (items.containsId(retValue))
-                                       s.add(retValue);
-                               return s;
-                       }
-
-               } else
-                       return retValue;
-       }
-
-       /**
-        * Sets 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>
-        * 
-        * @param newValue
-        *            the New selected item or collection of selected items.
-        * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object)
-        */
-       public void setValue(Object newValue) throws Property.ReadOnlyException,
-                       Property.ConversionException {
-               setValue(newValue, false);
-       }
-
-       /**
-        * Sets 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>
-        * 
-        * @param newValue
-        *            the New selected item or collection of selected items.
-        * @param repaintIsNotNeeded
-        *            True if caller is sure that repaint is not needed.
-        * @see com.itmill.toolkit.ui.AbstractField#setValue(java.lang.Object,
-        *      java.lang.Boolean)
-        */
-       protected void setValue(Object newValue, boolean repaintIsNotNeeded)
-                       throws Property.ReadOnlyException, Property.ConversionException {
-
-               if (isMultiSelect()) {
-                       if (newValue == null)
-                               super.setValue(new HashSet(), repaintIsNotNeeded);
-                       else if (Collection.class.isAssignableFrom(newValue.getClass()))
-                               super.setValue(new HashSet((Collection) newValue),
-                                               repaintIsNotNeeded);
-               } else if (newValue == null || items.containsId(newValue))
-                       super.setValue(newValue, repaintIsNotNeeded);
-       }
-
-       /* Container methods **************************************************** */
-
-       /**
-        * Gets the item from the container with given id. If the container does not
-        * contain the requested item, null is returned.
-        * 
-        * @param itemId
-        *            the item id.
-        * @return the item from the container.
-        */
-       public Item getItem(Object itemId) {
-               return items.getItem(itemId);
-       }
-
-       /**
-        * Gets the item Id collection from the container.
-        * 
-        * @return the Collection of item ids.
-        */
-       public Collection getItemIds() {
-               return items.getItemIds();
-       }
-
-       /**
-        * Gets the property Id collection from the container.
-        * 
-        * @return the Collection of property ids.
-        */
-       public Collection getContainerPropertyIds() {
-               return items.getContainerPropertyIds();
-       }
-
-       /**
-        * Gets the property type.
-        * 
-        * @param propertyId
-        *            the Id identifying the property.
-        * @see com.itmill.toolkit.data.Container#getType(java.lang.Object)
-        */
-       public Class getType(Object propertyId) {
-               return items.getType(propertyId);
-       }
-
-       /*
-        * Gets the number of items in the container.
-        * 
-        * @return the Number of items in the container.
-        * 
-        * @see com.itmill.toolkit.data.Container#size()
-        */
-       public int size() {
-               return items.size();
-       }
-
-       /**
-        * Tests, if the collection contains an item with given id.
-        * 
-        * @param itemId
-        *            the Id the of item to be tested.
-        */
-       public boolean containsId(Object itemId) {
-               if (itemId != null)
-                       return items.containsId(itemId);
-               else
-                       return false;
-       }
-
-       /**
-        * Gets the Property identified by the given itemId and propertyId from the
-        * Container
-        * 
-        * @see com.itmill.toolkit.data.Container#getContainerProperty(Object,
-        *      Object)
-        */
-       public Property getContainerProperty(Object itemId, Object propertyId) {
-               return items.getContainerProperty(itemId, propertyId);
-       }
-
-       /* Container.Managed methods ******************************************** */
-
-       /**
-        * Adds the 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 if the operation succeeded.
-        * @see com.itmill.toolkit.data.Container#addContainerProperty(java.lang.Object,
-        *      java.lang.Class, java.lang.Object)
-        */
-       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;
-       }
-
-       /**
-        * Removes all items from the container.
-        * 
-        * This functionality is optional. If the function is unsupported, it always
-        * returns false.
-        * 
-        * @return True if the operation succeeded.
-        * @see com.itmill.toolkit.data.Container#removeAllItems()
-        */
-       public boolean removeAllItems() throws UnsupportedOperationException {
-
-               boolean retval = items.removeAllItems();
-               this.itemIdMapper.removeAll();
-               if (retval) {
-                       setValue(null);
-                       if (!(items instanceof Container.ItemSetChangeNotifier))
-                               fireItemSetChange();
-               }
-               return retval;
-       }
-
-       /**
-        * Creates 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 the Id of the created item or null in case of failure.
-        * @see com.itmill.toolkit.data.Container#addItem()
-        */
-       public Object addItem() throws UnsupportedOperationException {
-
-               Object retval = items.addItem();
-               if (retval != null
-                               && !(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.
-        * 
-        * This functionality is optional. If the function is unsupported, it always
-        * returns null.
-        * 
-        * @param itemId
-        *            the Identification of the item to be created.
-        * @return the Created item with the given id, or null in case of failure.
-        * @see com.itmill.toolkit.data.Container#addItem(java.lang.Object)
-        */
-       public Item addItem(Object itemId) throws UnsupportedOperationException {
-
-               Item retval = items.addItem(itemId);
-               if (retval != null
-                               && !(items instanceof Container.ItemSetChangeNotifier))
-                       fireItemSetChange();
-               return retval;
-       }
-
-       /**
-        * Removes the item identified by Id from the container. This functionality
-        * is optional. If the function is not implemented, the functions allways
-        * returns false.
-        * 
-        * @return True if the operation succeeded.
-        * @see com.itmill.toolkit.data.Container#removeItem(java.lang.Object)
-        */
-       public boolean removeItem(Object itemId)
-                       throws UnsupportedOperationException {
-
-               unselect(itemId);
-               boolean retval = items.removeItem(itemId);
-               this.itemIdMapper.remove(itemId);
-               if (retval && !(items instanceof Container.ItemSetChangeNotifier))
-                       fireItemSetChange();
-               return retval;
+       public void setFilteringMode(int filteringMode) {
+               this.filteringMode = filteringMode;
        }
 
-       /**
-        * Removes the 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 if the operation succeeded.
-        * @see com.itmill.toolkit.data.Container#removeContainerProperty(java.lang.Object)
-        */
-       public boolean removeContainerProperty(Object propertyId)
-                       throws UnsupportedOperationException {
-
-               boolean retval = items.removeContainerProperty(propertyId);
-               if (retval && !(items instanceof Container.PropertySetChangeNotifier))
-                       firePropertySetChange();
-               return retval;
+       public int getFilteringMode() {
+               return this.filteringMode;
        }
-
-       /* Container.Viewer methods ********************************************* */
-
-       /**
-        * Sets the container as data-source for viewing.
-        * 
-        * @param newDataSource
-        *            the new data source.
-        */
-       public void setContainerDataSource(Container newDataSource) {
-               if (newDataSource == null)
-                       newDataSource = new IndexedContainer();
-
-               if (items != newDataSource) {
-
-                       // Removes listeners from the old datasource
-                       if (items != null) {
-                               try {
-                                       ((Container.ItemSetChangeNotifier) items)
-                                                       .removeListener((Container.ItemSetChangeListener) this);
-                               } catch (ClassCastException ignored) {
-                                       // Ignored
-                               }
-                               try {
-                                       ((Container.PropertySetChangeNotifier) items)
-                                                       .removeListener((Container.PropertySetChangeListener) this);
-                               } catch (ClassCastException ignored) {
-                                       // Ignored
-                               }
-                       }
-
-                       // Assigns new data source
-                       items = newDataSource;
-
-                       // Clears itemIdMapper also
-                       this.itemIdMapper.removeAll();
-
-                       // Adds listeners
-                       if (items != null) {
-                               try {
-                                       ((Container.ItemSetChangeNotifier) items)
-                                                       .addListener((Container.ItemSetChangeListener) this);
-                               } catch (ClassCastException ignored) {
-                                       // Ignored
-                               }
-                               try {
-                                       ((Container.PropertySetChangeNotifier) items)
-                                                       .addListener((Container.PropertySetChangeListener) this);
-                               } catch (ClassCastException ignored) {
-                                       // Ignored
-                               }
-                       }
-
-                       // TODO: This should be conditional
-                       fireValueChange(false);
-               }
-       }
-
-       /**
-        * Gets the viewing data-source container.
-        * 
-        * @see com.itmill.toolkit.data.Container.Viewer#getContainerDataSource()
-        */
-       public Container getContainerDataSource() {
-               return items;
-       }
-
-       /* Select attributes **************************************************** */
-
-       /**
-        * Is the select in multiselect mode? In multiselect mode
-        * 
-        * @return the Value of property multiSelect.
-        */
-       public boolean isMultiSelect() {
-               return this.multiSelect;
-       }
-
-       /**
-        * Sets 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
-        *            the New value of property multiSelect.
-        */
-       public void setMultiSelect(boolean multiSelect) {
-
-               if (multiSelect != this.multiSelect) {
-
-                       // Selection before mode change
-                       Object oldValue = getValue();
-
-                       this.multiSelect = multiSelect;
-
-                       // Convert the value type
-                       if (multiSelect) {
-                               Set s = new HashSet();
-                               if (oldValue != null)
-                                       s.add(oldValue);
-                               setValue(s);
-                       } else {
-                               Set s = (Set) oldValue;
-                               if (s == null || s.isEmpty())
-                                       setValue(null);
-                               else
-
-                                       // Set the single select to contain only the first
-                                       // selected value in the multiselect
-                                       setValue(s.iterator().next());
-                       }
-
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * 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 if additions are allowed.
-        */
-       public boolean isNewItemsAllowed() {
-
-               return this.allowNewOptions;
-       }
-
-       /**
-        * Enables or disables possibility to add new options by the user.
-        * 
-        * @param allowNewOptions
-        *            the New value of property allowNewOptions.
-        */
-       public void setNewItemsAllowed(boolean allowNewOptions) {
-
-               // Only handle change requests
-               if (this.allowNewOptions != allowNewOptions) {
-
-                       this.allowNewOptions = allowNewOptions;
-
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * 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
-        *            the New caption.
-        */
-       public void setItemCaption(Object itemId, String caption) {
-               if (itemId != null) {
-                       itemCaptions.put(itemId, caption);
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * Gets 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 the caption for specified item.
-        */
-       public String getItemCaption(Object itemId) {
-
-               // Null items can not be found
-               if (itemId == null)
-                       return null;
-
-               String caption = null;
-
-               switch (getItemCaptionMode()) {
-
-               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;
-               }
-
-               // All items must have some captions
-               return caption != null ? caption : "";
-       }
-
-       /**
-        * Sets the icon for an item.
-        * 
-        * @param itemId
-        *            the id of the item to be assigned an icon.
-        * @param icon
-        *            the New icon.
-        */
-       public void setItemIcon(Object itemId, Resource icon) {
-               if (itemId != null) {
-                       if (icon == null)
-                               itemIcons.remove(itemId);
-                       else
-                               itemIcons.put(itemId, icon);
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * Gets the item icon.
-        * 
-        * @param itemId
-        *            the id of the item to be assigned an icon.
-        * @return the Icon for the item or null, if not specified.
-        */
-       public Resource getItemIcon(Object itemId) {
-               Resource explicit = (Resource) itemIcons.get(itemId);
-               if (explicit != null)
-                       return explicit;
-
-               if (getItemIconPropertyId() == null)
-                       return null;
-
-               Property ip = getContainerProperty(itemId, getItemIconPropertyId());
-               if (ip == null)
-                       return null;
-               Object icon = ip.getValue();
-               if (icon instanceof Resource)
-                       return (Resource) icon;
-
-               return null;
-       }
-
-       /**
-        * Sets 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>
-        * </ul>
-        * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default
-        * mode.
-        * </p>
-        * 
-        * @param mode
-        *            the One of the modes listed above.
-        */
-       public void setItemCaptionMode(int mode) {
-               if (ITEM_CAPTION_MODE_ID <= mode && mode <= ITEM_CAPTION_MODE_PROPERTY) {
-                       itemCaptionMode = mode;
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * Gets 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>
-        * </ul>
-        * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default
-        * mode.
-        * </p>
-        * 
-        * @return the One of the modes listed above.
-        */
-       public int getItemCaptionMode() {
-               return itemCaptionMode;
-       }
-
-       /**
-        * Sets 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 property id to null disables this feature. The id is null by
-        * default
-        * </p>.
-        * 
-        * @param propertyId
-        *            the id of the property.
-        * 
-        */
-       public void setItemCaptionPropertyId(Object propertyId) {
-               if (propertyId != null) {
-                       itemCaptionPropertyId = propertyId;
-                       setItemCaptionMode(ITEM_CAPTION_MODE_PROPERTY);
-                       requestRepaint();
-               } else {
-                       itemCaptionPropertyId = null;
-                       if (getItemCaptionMode() == ITEM_CAPTION_MODE_PROPERTY)
-                               setItemCaptionMode(ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID);
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * Gets the item caption property.
-        * 
-        * @return the Id of the property used as item caption source.
-        */
-       public Object getItemCaptionPropertyId() {
-               return itemCaptionPropertyId;
-       }
-
-       /**
-        * Sets 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>
-        * Note : 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>.
-        * 
-        * @param propertyId
-        *            the Id of the property that specifies icons for items.
-        */
-       public void setItemIconPropertyId(Object propertyId) {
-               if ((propertyId != null)
-                               && Resource.class.isAssignableFrom(getType(propertyId))) {
-                       itemIconPropertyId = propertyId;
-                       requestRepaint();
-               } else
-                       itemIconPropertyId = null;
-       }
-
-       /**
-        * Gets 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>
-        * Note : 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>.
-        * 
-        * @return the Id of the property containing the item icons.
-        */
-       public Object getItemIconPropertyId() {
-               return itemIconPropertyId;
-       }
-
-       /**
-        * Tests 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>
-        * 
-        * @param itemId
-        *            the Id the of the item to be tested.
-        * @see #getNullSelectionItemId()
-        * @see #setNullSelectionItemId(Object)
-        * 
-        */
-       public boolean isSelected(Object itemId) {
-               if (itemId == null)
-                       return false;
-               if (isMultiSelect())
-                       return ((Set) getValue()).contains(itemId);
-               else {
-                       Object value = getValue();
-                       return itemId.equals(value == null ? getNullSelectionItemId()
-                                       : value);
-               }
-       }
-
-       /**
-        * Selects an item.
-        * 
-        * <p>
-        * In single select mode selecting item identified by
-        * {@link #getNullSelectionItemId()} sets the value of the property to null.
-        * </p>
-        * 
-        * @param itemId
-        *            the tem to be selected.
-        * @see #getNullSelectionItemId()
-        * @see #setNullSelectionItemId(Object)
-        * 
-        */
-       public void select(Object itemId) {
-               if (!isSelected(itemId) && items.containsId(itemId)) {
-                       if (isMultiSelect()) {
-                               Set s = new HashSet((Set) getValue());
-                               s.add(itemId);
-                               setValue(s);
-                       } else if (itemId.equals(getNullSelectionItemId()))
-                               setValue(null);
-                       else
-                               setValue(itemId);
-               }
-       }
-
-       /**
-        * Unselects an item.
-        * 
-        * @param itemId
-        *            the Item to be unselected.
-        * @see #getNullSelectionItemId()
-        * @see #setNullSelectionItemId(Object)
-        * 
-        */
-       public void unselect(Object itemId) {
-               if (isSelected(itemId)) {
-                       if (isMultiSelect()) {
-                               Set s = new HashSet((Set) getValue());
-                               s.remove(itemId);
-                               setValue(s);
-                       } else
-                               setValue(null);
-               }
-       }
-
-       /**
-        * Notifies this listener that the Containers contents has changed.
-        * 
-        * @see com.itmill.toolkit.data.Container.PropertySetChangeListener#containerPropertySetChange(com.itmill.toolkit.data.Container.PropertySetChangeEvent)
-        */
-       public void containerPropertySetChange(
-                       Container.PropertySetChangeEvent event) {
-               firePropertySetChange();
-       }
-
-       /**
-        * Adds a new Property set change listener for this Container.
-        * 
-        * @see com.itmill.toolkit.data.Container.PropertySetChangeNotifier#addListener(com.itmill.toolkit.data.Container.PropertySetChangeListener)
-        */
-       public void addListener(Container.PropertySetChangeListener listener) {
-               if (propertySetEventListeners == null)
-                       propertySetEventListeners = new LinkedList();
-               propertySetEventListeners.add(listener);
-       }
-
-       /**
-        * Removes a previously registered Property set change listener.
-        * 
-        * @see com.itmill.toolkit.data.Container.PropertySetChangeNotifier#removeListener(com.itmill.toolkit.data.Container.PropertySetChangeListener)
-        */
-       public void removeListener(Container.PropertySetChangeListener listener) {
-               if (propertySetEventListeners != null) {
-                       propertySetEventListeners.remove(listener);
-                       if (propertySetEventListeners.isEmpty())
-                               propertySetEventListeners = null;
-               }
-       }
-
-       /**
-        * Adds an Item set change listener for the object.
-        * 
-        * @see com.itmill.toolkit.data.Container.ItemSetChangeNotifier#addListener(com.itmill.toolkit.data.Container.ItemSetChangeListener)
-        */
-       public void addListener(Container.ItemSetChangeListener listener) {
-               if (itemSetEventListeners == null)
-                       itemSetEventListeners = new LinkedList();
-               itemSetEventListeners.add(listener);
-       }
-
-       /**
-        * Removes the Item set change listener from the object.
-        * 
-        * @see com.itmill.toolkit.data.Container.ItemSetChangeNotifier#removeListener(com.itmill.toolkit.data.Container.ItemSetChangeListener)
-        */
-       public void removeListener(Container.ItemSetChangeListener listener) {
-               if (itemSetEventListeners != null) {
-                       itemSetEventListeners.remove(listener);
-                       if (itemSetEventListeners.isEmpty())
-                               itemSetEventListeners = null;
-               }
-       }
-
-       /**
-        * Lets the listener know a Containers Item set has changed.
-        * 
-        * @see com.itmill.toolkit.data.Container.ItemSetChangeListener#containerItemSetChange(com.itmill.toolkit.data.Container.ItemSetChangeEvent)
-        */
-       public void containerItemSetChange(Container.ItemSetChangeEvent event) {
-               // Clears the item id mapping table
-               this.itemIdMapper.removeAll();
-
-               // Notify all listeners
-               fireItemSetChange();
-       }
-
-       /**
-        * Fires the property set change event.
-        */
-       protected void firePropertySetChange() {
-               if (propertySetEventListeners != null
-                               && !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);
-               }
-               requestRepaint();
-       }
-
-       /**
-        * Fires the item set change event.
-        */
-       protected void fireItemSetChange() {
-               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);
-               }
-               requestRepaint();
-       }
-
-       /**
-        * Implementation of item set change event.
-        */
-       private class ItemSetChangeEvent implements Container.ItemSetChangeEvent {
-
-               /**
-                * Gets the Property where the event occurred.
-                * 
-                * @see com.itmill.toolkit.data.Container.ItemSetChangeEvent#getContainer()
-                */
-               public Container getContainer() {
-                       return Select.this;
-               }
-
-       }
-
-       /**
-        * Implementation of property set change event.
-        */
-       private class PropertySetChangeEvent implements
-                       Container.PropertySetChangeEvent {
-
-               /**
-                * Retrieves the Container whose contents have been modified.
-                * 
-                * @see com.itmill.toolkit.data.Container.PropertySetChangeEvent#getContainer()
-                */
-               public Container getContainer() {
-                       return Select.this;
-               }
-
-       }
-
-       /**
-        * 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>
-        * 
-        * @return the Object Null value item id.
-        * @see #setNullSelectionItemId(Object)
-        * @see #isSelected(Object)
-        * @see #select(Object)
-        */
-       public final Object getNullSelectionItemId() {
-               return nullSelectionItemId;
-       }
-
-       /**
-        * 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>
-        * 
-        * @param nullSelectionItemId
-        *            the nullSelectionItemId to set.
-        * @see #getNullSelectionItemId()
-        * @see #isSelected(Object)
-        * @see #select(Object)
-        */
-       public void setNullSelectionItemId(Object nullSelectionItemId) {
-               this.nullSelectionItemId = nullSelectionItemId;
-       }
-
-       // TODO javadoc
-       public boolean isLazyLoading() {
-               return isLazyLoading;
-       }
-
-       // TODO javadoc
-       // TODO What to do when terminal does not support lazy loading?
-       public void setLazyLoading(boolean useLazyLoading) {
-               if (useLazyLoading != isLazyLoading) {
-                       isLazyLoading = useLazyLoading;
-                       if (getOptionFilter() == null)
-                               setOptionFilter(new StartsWithFilter(this));
-                       requestRepaint();
-               }
-       }
-
-       /**
-        * Notifies the component that it is connected to an application.
-        * 
-        * @see com.itmill.toolkit.ui.AbstractField#attach()
-        */
-       public void attach() {
-               super.attach();
-       }
-
-       /**
-        * Detaches the component from application.
-        * 
-        * @see com.itmill.toolkit.ui.AbstractComponent#detach()
-        */
-       public void detach() {
-               super.detach();
-       }
-
-       /**
-        * Sets OptionFilter which will do filtering base on query string if Select
-        * is in lazy loading mode.
-        * 
-        * @param of
-        *            OptionFilter to be used in filtering
-        */
-       public void setOptionFilter(OptionFilter of) {
-               optionFilter = of;
-       }
-
-       /**
-        * @return reference to option filter
-        */
-       public OptionFilter getOptionFilter() {
-               return optionFilter;
-       }
-
-       /**
-        * Set visible columns.
-        */
-       public void setColumns(int cols) {
-               this.columns = cols;
-       }
-
-       /**
-        * Get visible columns.
-        */
-       public int getColumns() {
-               return this.columns;
-       }
-
 }
index 2299383366ae29104db9df7b2ff4be11a63ec8a2..c36f7bd811d5e4a49bb3dafe48018edc594419aa 100644 (file)
@@ -60,7 +60,7 @@ import com.itmill.toolkit.terminal.Sizeable;
  * @VERSION@
  * @since 3.0
  */
-public class Table extends Select implements Action.Container,
+public class Table extends AbstractSelect implements Action.Container,
                Container.Ordered, Container.Sortable, Sizeable {
 
        private static final int CELL_KEY = 0;
@@ -192,7 +192,7 @@ public class Table extends Select implements Action.Container,
        /**
         * Keymapper for column ids.
         */
-       private KeyMapper columnIdMap = new KeyMapper();
+       private final KeyMapper columnIdMap = new KeyMapper();
 
        /**
         * Holds visible column propertyIds - in order.
@@ -202,17 +202,17 @@ public class Table extends Select implements Action.Container,
        /**
         * Holds propertyIds of currently collapsed columns.
         */
-       private HashSet collapsedColumns = new HashSet();
+       private final HashSet collapsedColumns = new HashSet();
 
        /**
         * Holds headers for visible columns (by propertyId).
         */
-       private HashMap columnHeaders = new HashMap();
+       private final HashMap columnHeaders = new HashMap();
 
        /**
         * Holds icons for visible columns (by propertyId).
         */
-       private HashMap columnIcons = new HashMap();
+       private final HashMap columnIcons = new HashMap();
 
        /**
         * Holds alignments for visible columns (by propertyId).
@@ -222,7 +222,7 @@ public class Table extends Select implements Action.Container,
        /**
         * Holds column widths in pixels for visible columns (by propertyId).
         */
-       private HashMap columnWidths = new HashMap();
+       private final HashMap columnWidths = new HashMap();
 
        /**
         * Holds value of property pageLength. 0 disables paging.
@@ -387,20 +387,22 @@ public class Table extends Select implements Action.Container,
        public void setVisibleColumns(Object[] visibleColumns) {
 
                // Visible columns must exist
-               if (visibleColumns == null)
+               if (visibleColumns == null) {
                        throw new NullPointerException(
                                        "Can not set visible columns to null value");
+               }
 
                // Checks that the new visible columns contains no nulls and properties
                // exist
                Collection properties = getContainerPropertyIds();
                for (int i = 0; i < visibleColumns.length; i++) {
-                       if (visibleColumns[i] == null)
+                       if (visibleColumns[i] == null) {
                                throw new NullPointerException("Properties must be non-nulls");
-                       else if (!properties.contains(visibleColumns[i]))
+                       } else if (!properties.contains(visibleColumns[i])) {
                                throw new IllegalArgumentException(
                                                "Properties must exist in the Container, missing property: "
                                                                + visibleColumns[i]);
+                       }
                }
 
                // If this is called befor the constructor is finished, it might be
@@ -411,7 +413,7 @@ public class Table extends Select implements Action.Container,
                }
 
                // Removes alignments, icons and headers from hidden columns
-               if (this.visibleColumns != null)
+               if (this.visibleColumns != null) {
                        for (Iterator i = this.visibleColumns.iterator(); i.hasNext();) {
                                Object col = i.next();
                                if (!newVC.contains(col)) {
@@ -420,6 +422,7 @@ public class Table extends Select implements Action.Container,
                                        setColumnIcon(col, null);
                                }
                        }
+               }
 
                this.visibleColumns = newVC;
 
@@ -471,9 +474,10 @@ public class Table extends Select implements Action.Container,
         */
        public void setColumnHeaders(String[] columnHeaders) {
 
-               if (columnHeaders.length != this.visibleColumns.size())
+               if (columnHeaders.length != this.visibleColumns.size()) {
                        throw new IllegalArgumentException(
                                        "The length of the headers array must match the number of visible columns");
+               }
 
                this.columnHeaders.clear();
                int i = 0;
@@ -529,9 +533,10 @@ public class Table extends Select implements Action.Container,
         */
        public void setColumnIcons(Resource[] columnIcons) {
 
-               if (columnIcons.length != this.visibleColumns.size())
+               if (columnIcons.length != this.visibleColumns.size()) {
                        throw new IllegalArgumentException(
                                        "The length of the icons array must match the number of visible columns");
+               }
 
                this.columnIcons.clear();
                int i = 0;
@@ -595,17 +600,19 @@ public class Table extends Select implements Action.Container,
         */
        public void setColumnAlignments(String[] columnAlignments) {
 
-               if (columnAlignments.length != this.visibleColumns.size())
+               if (columnAlignments.length != this.visibleColumns.size()) {
                        throw new IllegalArgumentException(
                                        "The length of the alignments array must match the number of visible columns");
+               }
 
                // Checks all alignments
                for (int i = 0; i < columnAlignments.length; i++) {
                        String a = columnAlignments[i];
                        if (a != null && !a.equals(ALIGN_LEFT) && !a.equals(ALIGN_CENTER)
-                                       && !a.equals(ALIGN_RIGHT))
+                                       && !a.equals(ALIGN_RIGHT)) {
                                throw new IllegalArgumentException("Column " + i
                                                + " aligment '" + a + "' is invalid");
+                       }
                }
 
                // Resets the alignments
@@ -633,7 +640,7 @@ public class Table extends Select implements Action.Container,
         * @since 4.0.3
         */
        public void setColumnWidth(Object columnId, int width) {
-               columnWidths.put(columnId, new Integer(width));
+               this.columnWidths.put(columnId, new Integer(width));
        }
 
        /**
@@ -643,9 +650,10 @@ public class Table extends Select implements Action.Container,
         * @return width of colun or -1 when value not set
         */
        public int getColumnWidth(Object propertyId) {
-               Integer value = (Integer) columnWidths.get(propertyId);
-               if (value == null)
+               Integer value = (Integer) this.columnWidths.get(propertyId);
+               if (value == null) {
                        return -1;
+               }
                return value.intValue();
        }
 
@@ -676,7 +684,7 @@ public class Table extends Select implements Action.Container,
                if (pageLength >= 0 && this.pageLength != pageLength) {
                        this.pageLength = pageLength;
                        // "scroll" to first row
-                       this.setCurrentPageFirstItemIndex(0);
+                       setCurrentPageFirstItemIndex(0);
                        // Assures the visual refresh
                        refreshCurrentPage();
                }
@@ -690,20 +698,24 @@ public class Table extends Select implements Action.Container,
        public Object getCurrentPageFirstItemId() {
 
                // Priorise index over id if indexes are supported
-               if (items instanceof Container.Indexed) {
+               if (this.items instanceof Container.Indexed) {
                        int index = getCurrentPageFirstItemIndex();
                        Object id = null;
-                       if (index >= 0 && index < size())
-                               id = ((Container.Indexed) items).getIdByIndex(index);
-                       if (id != null && !id.equals(currentPageFirstItemId))
-                               currentPageFirstItemId = id;
+                       if (index >= 0 && index < size()) {
+                               id = ((Container.Indexed) this.items).getIdByIndex(index);
+                       }
+                       if (id != null && !id.equals(this.currentPageFirstItemId)) {
+                               this.currentPageFirstItemId = id;
+                       }
                }
 
                // If there is no item id at all, use the first one
-               if (currentPageFirstItemId == null)
-                       currentPageFirstItemId = ((Container.Ordered) items).firstItemId();
+               if (this.currentPageFirstItemId == null) {
+                       this.currentPageFirstItemId = ((Container.Ordered) this.items)
+                                       .firstItemId();
+               }
 
-               return currentPageFirstItemId;
+               return this.currentPageFirstItemId;
        }
 
        /**
@@ -717,19 +729,20 @@ public class Table extends Select implements Action.Container,
                // Gets the corresponding index
                int index = -1;
                try {
-                       index = ((Container.Indexed) items)
+                       index = ((Container.Indexed) this.items)
                                        .indexOfId(currentPageFirstItemId);
                } catch (ClassCastException e) {
 
                        // If the table item container does not have index, we have to
                        // calculates the index by hand
-                       Object id = ((Container.Ordered) items).firstItemId();
+                       Object id = ((Container.Ordered) this.items).firstItemId();
                        while (id != null && !id.equals(currentPageFirstItemId)) {
                                index++;
-                               id = ((Container.Ordered) items).nextItemId(id);
+                               id = ((Container.Ordered) this.items).nextItemId(id);
                        }
-                       if (id == null)
+                       if (id == null) {
                                index = -1;
+                       }
                }
 
                // If the search for item index was successfull
@@ -768,10 +781,11 @@ public class Table extends Select implements Action.Container,
         */
        public void setColumnIcon(Object propertyId, Resource icon) {
 
-               if (icon == null)
+               if (icon == null) {
                        this.columnIcons.remove(propertyId);
-               else
+               } else {
                        this.columnIcons.put(propertyId, icon);
+               }
 
                // Assures the visual refresh
                refreshCurrentPage();
@@ -785,12 +799,13 @@ public class Table extends Select implements Action.Container,
         * @return the header for the specifed column if it has one.
         */
        public String getColumnHeader(Object propertyId) {
-               if (getColumnHeaderMode() == COLUMN_HEADER_MODE_HIDDEN)
+               if (getColumnHeaderMode() == COLUMN_HEADER_MODE_HIDDEN) {
                        return null;
+               }
 
                String header = (String) this.columnHeaders.get(propertyId);
-               if ((header == null && this.getColumnHeaderMode() == COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID)
-                               || this.getColumnHeaderMode() == COLUMN_HEADER_MODE_ID) {
+               if ((header == null && getColumnHeaderMode() == COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID)
+                               || getColumnHeaderMode() == COLUMN_HEADER_MODE_ID) {
                        header = propertyId.toString();
                }
 
@@ -847,9 +862,10 @@ public class Table extends Select implements Action.Container,
                // Checks for valid alignments
                if (alignment != null && !alignment.equals(ALIGN_LEFT)
                                && !alignment.equals(ALIGN_CENTER)
-                               && !alignment.equals(ALIGN_RIGHT))
+                               && !alignment.equals(ALIGN_RIGHT)) {
                        throw new IllegalArgumentException("Column alignment '" + alignment
                                        + "' is not supported.");
+               }
 
                if (alignment == null || alignment.equals(ALIGN_LEFT)) {
                        this.columnAlignments.remove(propertyId);
@@ -870,8 +886,8 @@ public class Table extends Select implements Action.Container,
         * @return true if the column is collapsed; false otherwise;
         */
        public boolean isColumnCollapsed(Object propertyId) {
-               return collapsedColumns != null
-                               && collapsedColumns.contains(propertyId);
+               return this.collapsedColumns != null
+                               && this.collapsedColumns.contains(propertyId);
        }
 
        /**
@@ -886,14 +902,15 @@ public class Table extends Select implements Action.Container,
         */
        public void setColumnCollapsed(Object propertyId, boolean collapsed)
                        throws IllegalAccessException {
-               if (!this.isColumnCollapsingAllowed()) {
+               if (!isColumnCollapsingAllowed()) {
                        throw new IllegalAccessException("Column collapsing not allowed!");
                }
 
-               if (collapsed)
+               if (collapsed) {
                        this.collapsedColumns.add(propertyId);
-               else
+               } else {
                        this.collapsedColumns.remove(propertyId);
+               }
 
                // Assures the visual refresh
                refreshCurrentPage();
@@ -917,8 +934,9 @@ public class Table extends Select implements Action.Container,
        public void setColumnCollapsingAllowed(boolean collapsingAllowed) {
                this.columnCollapsingAllowed = collapsingAllowed;
 
-               if (!collapsingAllowed)
-                       collapsedColumns.clear();
+               if (!collapsingAllowed) {
+                       this.collapsedColumns.clear();
+               }
 
                // Assures the visual refresh
                refreshCurrentPage();
@@ -953,7 +971,7 @@ public class Table extends Select implements Action.Container,
         * nothing if columnReordering is not allowed.
         */
        private void setColumnOrder(Object[] columnOrder) {
-               if (columnOrder == null || !this.isColumnReorderingAllowed()) {
+               if (columnOrder == null || !isColumnReorderingAllowed()) {
                        return;
                }
                LinkedList newOrder = new LinkedList();
@@ -966,8 +984,9 @@ public class Table extends Select implements Action.Container,
                }
                for (Iterator it = this.visibleColumns.iterator(); it.hasNext();) {
                        Object columnId = it.next();
-                       if (!newOrder.contains(columnId))
+                       if (!newOrder.contains(columnId)) {
                                newOrder.add(columnId);
+                       }
                }
                this.visibleColumns = newOrder;
 
@@ -993,18 +1012,20 @@ public class Table extends Select implements Action.Container,
        public void setCurrentPageFirstItemIndex(int newIndex) {
 
                // Ensures that the new value is valid
-               if (newIndex < 0)
+               if (newIndex < 0) {
                        newIndex = 0;
-               if (newIndex >= size())
+               }
+               if (newIndex >= size()) {
                        newIndex = size() - 1;
+               }
 
                // Refresh first item id
-               if (items instanceof Container.Indexed) {
+               if (this.items instanceof Container.Indexed) {
                        try {
-                               currentPageFirstItemId = ((Container.Indexed) items)
+                               this.currentPageFirstItemId = ((Container.Indexed) this.items)
                                                .getIdByIndex(newIndex);
                        } catch (IndexOutOfBoundsException e) {
-                               currentPageFirstItemId = null;
+                               this.currentPageFirstItemId = null;
                        }
                        this.currentPageFirstItemIndex = newIndex;
                } else {
@@ -1013,49 +1034,52 @@ public class Table extends Select implements Action.Container,
                        // container forwards / backwards
                        // next available item forward or backward
 
-                       this.currentPageFirstItemId = ((Container.Ordered) items)
+                       this.currentPageFirstItemId = ((Container.Ordered) this.items)
                                        .firstItemId();
 
                        // Go forwards in the middle of the list (respect borders)
                        while (this.currentPageFirstItemIndex < newIndex
-                                       && !((Container.Ordered) items)
-                                                       .isLastId(currentPageFirstItemId)) {
+                                       && !((Container.Ordered) this.items)
+                                                       .isLastId(this.currentPageFirstItemId)) {
                                this.currentPageFirstItemIndex++;
-                               currentPageFirstItemId = ((Container.Ordered) items)
-                                               .nextItemId(currentPageFirstItemId);
+                               this.currentPageFirstItemId = ((Container.Ordered) this.items)
+                                               .nextItemId(this.currentPageFirstItemId);
                        }
 
                        // If we did hit the border
-                       if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) {
+                       if (((Container.Ordered) this.items)
+                                       .isLastId(this.currentPageFirstItemId)) {
                                this.currentPageFirstItemIndex = size() - 1;
                        }
 
                        // Go backwards in the middle of the list (respect borders)
                        while (this.currentPageFirstItemIndex > newIndex
-                                       && !((Container.Ordered) items)
-                                                       .isFirstId(currentPageFirstItemId)) {
+                                       && !((Container.Ordered) this.items)
+                                                       .isFirstId(this.currentPageFirstItemId)) {
                                this.currentPageFirstItemIndex--;
-                               currentPageFirstItemId = ((Container.Ordered) items)
-                                               .prevItemId(currentPageFirstItemId);
+                               this.currentPageFirstItemId = ((Container.Ordered) this.items)
+                                               .prevItemId(this.currentPageFirstItemId);
                        }
 
                        // If we did hit the border
-                       if (((Container.Ordered) items).isFirstId(currentPageFirstItemId)) {
+                       if (((Container.Ordered) this.items)
+                                       .isFirstId(this.currentPageFirstItemId)) {
                                this.currentPageFirstItemIndex = 0;
                        }
 
                        // Go forwards once more
                        while (this.currentPageFirstItemIndex < newIndex
-                                       && !((Container.Ordered) items)
-                                                       .isLastId(currentPageFirstItemId)) {
+                                       && !((Container.Ordered) this.items)
+                                                       .isLastId(this.currentPageFirstItemId)) {
                                this.currentPageFirstItemIndex++;
-                               currentPageFirstItemId = ((Container.Ordered) items)
-                                               .nextItemId(currentPageFirstItemId);
+                               this.currentPageFirstItemId = ((Container.Ordered) this.items)
+                                               .nextItemId(this.currentPageFirstItemId);
                        }
 
                        // If for some reason we do hit border again, override
                        // the user index request
-                       if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) {
+                       if (((Container.Ordered) this.items)
+                                       .isLastId(this.currentPageFirstItemId)) {
                                newIndex = this.currentPageFirstItemIndex = size() - 1;
                        }
                }
@@ -1084,8 +1108,9 @@ public class Table extends Select implements Action.Container,
                this.pageBuffering = pageBuffering;
 
                // If page buffering is disabled, clear the buffer
-               if (!pageBuffering)
-                       pageBuffer = null;
+               if (!pageBuffering) {
+                       this.pageBuffer = null;
+               }
        }
 
        /**
@@ -1135,8 +1160,9 @@ public class Table extends Select implements Action.Container,
         */
        public void setColumnHeaderMode(int columnHeaderMode) {
                if (columnHeaderMode >= COLUMN_HEADER_MODE_HIDDEN
-                               && columnHeaderMode <= COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID)
+                               && columnHeaderMode <= COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID) {
                        this.columnHeaderMode = columnHeaderMode;
+               }
 
                // Assures the visual refresh
                refreshCurrentPage();
@@ -1149,7 +1175,7 @@ public class Table extends Select implements Action.Container,
        public void refreshCurrentPage() {
 
                // Clear page buffer and notify about the change
-               pageBuffer = null;
+               this.pageBuffer = null;
                requestRepaint();
        }
 
@@ -1182,10 +1208,10 @@ public class Table extends Select implements Action.Container,
         *            the One of the modes listed above.
         */
        public void setRowHeaderMode(int mode) {
-               if (ROW_HEADER_MODE_HIDDEN == mode)
-                       rowCaptionsAreHidden = true;
-               else {
-                       rowCaptionsAreHidden = false;
+               if (ROW_HEADER_MODE_HIDDEN == mode) {
+                       this.rowCaptionsAreHidden = true;
+               else {
+                       this.rowCaptionsAreHidden = false;
                        setItemCaptionMode(mode);
                }
 
@@ -1200,7 +1226,7 @@ public class Table extends Select implements Action.Container,
         * @see #setRowHeaderMode(int)
         */
        public int getRowHeaderMode() {
-               return rowCaptionsAreHidden ? ROW_HEADER_MODE_HIDDEN
+               return this.rowCaptionsAreHidden ? ROW_HEADER_MODE_HIDDEN
                                : getItemCaptionMode();
        }
 
@@ -1223,24 +1249,29 @@ public class Table extends Select implements Action.Container,
                Object[] cols = getVisibleColumns();
 
                // Checks that a correct number of cells are given
-               if (cells.length != cols.length)
+               if (cells.length != cols.length) {
                        return null;
+               }
 
                // Creates new item
                Item item;
                if (itemId == null) {
-                       itemId = items.addItem();
-                       if (itemId == null)
+                       itemId = this.items.addItem();
+                       if (itemId == null) {
                                return null;
-                       item = items.getItem(itemId);
-               } else
-                       item = items.addItem(itemId);
-               if (item == null)
+                       }
+                       item = this.items.getItem(itemId);
+               } else {
+                       item = this.items.addItem(itemId);
+               }
+               if (item == null) {
                        return null;
+               }
 
                // Fills the item properties
-               for (int i = 0; i < cols.length; i++)
+               for (int i = 0; i < cols.length; i++) {
                        item.getItemProperty(cols[i]).setValue(cells[i]);
+               }
 
                return itemId;
        }
@@ -1254,24 +1285,27 @@ public class Table extends Select implements Action.Container,
         */
        public void setContainerDataSource(Container newDataSource) {
 
-               if (newDataSource == null)
+               if (newDataSource == null) {
                        newDataSource = new IndexedContainer();
+               }
 
                // Assures that the data source is ordered by making unordered
                // containers ordered by wrapping them
-               if (newDataSource instanceof Container.Ordered)
+               if (newDataSource instanceof Container.Ordered) {
                        super.setContainerDataSource(newDataSource);
-               else
+               } else {
                        super.setContainerDataSource(new ContainerOrderedWrapper(
                                        newDataSource));
+               }
 
                // Resets page position
-               currentPageFirstItemId = null;
-               currentPageFirstItemIndex = 0;
+               this.currentPageFirstItemId = null;
+               this.currentPageFirstItemIndex = 0;
 
                // Resets column properties
-               if (this.collapsedColumns != null)
+               if (this.collapsedColumns != null) {
                        this.collapsedColumns.clear();
+               }
                setVisibleColumns(getContainerPropertyIds().toArray());
 
                // Assure visual refresh
@@ -1293,20 +1327,23 @@ public class Table extends Select implements Action.Container,
                // Page start index
                if (variables.containsKey("firstvisible")) {
                        Integer value = (Integer) variables.get("firstvisible");
-                       if (value != null)
+                       if (value != null) {
                                setCurrentPageFirstItemIndex(value.intValue());
+                       }
                }
 
                // Sets requested firstrow and rows for the next paint
                if (variables.containsKey("reqfirstrow")
                                || variables.containsKey("reqrows")) {
                        Integer value = (Integer) variables.get("reqfirstrow");
-                       if (value != null)
-                               reqFirstRowToPaint = value.intValue();
+                       if (value != null) {
+                               this.reqFirstRowToPaint = value.intValue();
+                       }
                        value = (Integer) variables.get("reqrows");
-                       if (value != null)
-                               reqRowsToPaint = value.intValue();
-                       pageBuffer = null;
+                       if (value != null) {
+                               this.reqRowsToPaint = value.intValue();
+                       }
+                       this.pageBuffer = null;
                        requestRepaint();
                }
 
@@ -1315,13 +1352,16 @@ public class Table extends Select implements Action.Container,
                        StringTokenizer st = new StringTokenizer((String) variables
                                        .get("action"), ",");
                        if (st.countTokens() == 2) {
-                               Object itemId = itemIdMapper.get(st.nextToken());
-                               Action action = (Action) actionMapper.get(st.nextToken());
+                               Object itemId = this.itemIdMapper.get(st.nextToken());
+                               Action action = (Action) this.actionMapper.get(st.nextToken());
                                if (action != null && containsId(itemId)
-                                               && actionHandlers != null)
-                                       for (Iterator i = actionHandlers.iterator(); i.hasNext();)
+                                               && this.actionHandlers != null) {
+                                       for (Iterator i = this.actionHandlers.iterator(); i
+                                                       .hasNext();) {
                                                ((Action.Handler) i.next()).handleAction(action, this,
                                                                itemId);
+                                       }
+                               }
                        }
                }
 
@@ -1345,35 +1385,36 @@ public class Table extends Select implements Action.Container,
                                }
                        }
                }
-               if (doSort)
+               if (doSort) {
                        this.sort();
+               }
 
                // Dynamic column hide/show and order
                // Update visible columns
-               if (this.isColumnCollapsingAllowed()) {
+               if (isColumnCollapsingAllowed()) {
                        if (variables.containsKey("collapsedcolumns")) {
                                try {
                                        Object[] ids = (Object[]) variables.get("collapsedcolumns");
                                        for (Iterator it = this.visibleColumns.iterator(); it
                                                        .hasNext();) {
-                                               this.setColumnCollapsed(it.next(), false);
+                                               setColumnCollapsed(it.next(), false);
                                        }
                                        for (int i = 0; i < ids.length; i++) {
-                                               this.setColumnCollapsed(columnIdMap.get(ids[i]
+                                               setColumnCollapsed(this.columnIdMap.get(ids[i]
                                                                .toString()), true);
                                        }
                                } catch (Exception ignored) {
                                }
                        }
                }
-               if (this.isColumnReorderingAllowed()) {
+               if (isColumnReorderingAllowed()) {
                        if (variables.containsKey("columnorder")) {
                                try {
                                        Object[] ids = (Object[]) variables.get("columnorder");
                                        for (int i = 0; i < ids.length; i++) {
-                                               ids[i] = columnIdMap.get(ids[i].toString());
+                                               ids[i] = this.columnIdMap.get(ids[i].toString());
                                        }
-                                       this.setColumnOrder(ids);
+                                       setColumnOrder(ids);
                                } catch (Exception ignored) {
                                }
                        }
@@ -1391,21 +1432,24 @@ public class Table extends Select implements Action.Container,
        public void paintContent(PaintTarget target) throws PaintException {
 
                // Focus control id
-               if (this.getFocusableId() > 0) {
-                       target.addAttribute("focusid", this.getFocusableId());
+               if (getFocusableId() > 0) {
+                       target.addAttribute("focusid", getFocusableId());
                }
 
                // The tab ordering number
-               if (this.getTabIndex() > 0)
-                       target.addAttribute("tabindex", this.getTabIndex());
+               if (getTabIndex() > 0) {
+                       target.addAttribute("tabindex", getTabIndex());
+               }
 
                // Size
-               if (getHeight() >= 0)
+               if (getHeight() >= 0) {
                        target.addAttribute("height", "" + getHeight()
                                        + Sizeable.UNIT_SYMBOLS[getHeightUnits()]);
-               if (getWidth() >= 0)
+               }
+               if (getWidth() >= 0) {
                        target.addAttribute("width", "" + getWidth()
                                        + Sizeable.UNIT_SYMBOLS[getWidthUnits()]);
+               }
 
                // Initialize temps
                Object[] colids = getVisibleColumns();
@@ -1417,34 +1461,41 @@ public class Table extends Select implements Action.Container,
                boolean colheads = colHeadMode != COLUMN_HEADER_MODE_HIDDEN;
                boolean rowheads = getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN;
                Object[][] cells = getVisibleCells();
-               boolean iseditable = this.isEditable();
+               boolean iseditable = isEditable();
 
                // selection support
                String[] selectedKeys;
-               if (isMultiSelect())
+               if (isMultiSelect()) {
                        selectedKeys = new String[((Set) getValue()).size()];
-               else
+               } else {
                        selectedKeys = new String[(getValue() == null
                                        && getNullSelectionItemId() == null ? 0 : 1)];
+               }
                int keyIndex = 0;
 
                // Table attributes
-               if (isSelectable())
+               if (isSelectable()) {
                        target.addAttribute("selectmode", (isMultiSelect() ? "multi"
                                        : "single"));
-               else
+               } else {
                        target.addAttribute("selectmode", "none");
+               }
                target.addAttribute("cols", cols);
                target.addAttribute("rows", cells[0].length);
-               target.addAttribute("firstrow",
-                               (reqFirstRowToPaint >= 0 ? reqFirstRowToPaint : first));
+               target
+                               .addAttribute("firstrow",
+                                               (this.reqFirstRowToPaint >= 0 ? this.reqFirstRowToPaint
+                                                               : first));
                target.addAttribute("totalrows", total);
-               if (pagelen != 0)
+               if (pagelen != 0) {
                        target.addAttribute("pagelength", pagelen);
-               if (colheads)
+               }
+               if (colheads) {
                        target.addAttribute("colheaders", true);
-               if (rowheads)
+               }
+               if (rowheads) {
                        target.addAttribute("rowheaders", true);
+               }
 
                // Visible column order
                Collection sortables = getSortableContainerPropertyIds();
@@ -1476,15 +1527,17 @@ public class Table extends Select implements Action.Container,
 
                        // tr attributes
                        if (rowheads) {
-                               if (cells[CELL_ICON][i] != null)
+                               if (cells[CELL_ICON][i] != null) {
                                        target.addAttribute("icon", (Resource) cells[CELL_ICON][i]);
-                               if (cells[CELL_HEADER][i] != null)
+                               }
+                               if (cells[CELL_HEADER][i] != null) {
                                        target.addAttribute("caption",
                                                        (String) cells[CELL_HEADER][i]);
+                               }
                        }
                        target.addAttribute("key", Integer.parseInt(cells[CELL_KEY][i]
                                        .toString()));
-                       if (actionHandlers != null || isSelectable()) {
+                       if (this.actionHandlers != null || isSelectable()) {
                                if (isSelected(itemId) && keyIndex < selectedKeys.length) {
                                        target.addAttribute("selected", true);
                                        selectedKeys[keyIndex++] = (String) cells[CELL_KEY][i];
@@ -1492,17 +1545,19 @@ public class Table extends Select implements Action.Container,
                        }
 
                        // Actions
-                       if (actionHandlers != null) {
+                       if (this.actionHandlers != null) {
                                ArrayList keys = new ArrayList();
-                               for (Iterator ahi = actionHandlers.iterator(); ahi.hasNext();) {
+                               for (Iterator ahi = this.actionHandlers.iterator(); ahi
+                                               .hasNext();) {
                                        Action[] aa = ((Action.Handler) ahi.next()).getActions(
                                                        itemId, this);
-                                       if (aa != null)
+                                       if (aa != null) {
                                                for (int ai = 0; ai < aa.length; ai++) {
-                                                       String key = actionMapper.key(aa[ai]);
+                                                       String key = this.actionMapper.key(aa[ai]);
                                                        actionSet.add(aa[ai]);
                                                        keys.add(key);
                                                }
+                                       }
                                }
                                target.addAttribute("al", keys.toArray());
                        }
@@ -1511,21 +1566,24 @@ public class Table extends Select implements Action.Container,
                        int currentColumn = 0;
                        for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); currentColumn++) {
                                Object columnId = it.next();
-                               if (columnId == null || this.isColumnCollapsed(columnId))
+                               if (columnId == null || isColumnCollapsed(columnId)) {
                                        continue;
+                               }
                                if ((iscomponent[currentColumn] || iseditable)
                                                && Component.class.isInstance(cells[CELL_FIRSTCOL
                                                                + currentColumn][i])) {
                                        Component c = (Component) cells[CELL_FIRSTCOL
                                                        + currentColumn][i];
-                                       if (c == null)
+                                       if (c == null) {
                                                target.addText("");
-                                       else
+                                       } else {
                                                c.paint(target);
-                               } else
+                                       }
+                               } else {
                                        target
                                                        .addText((String) cells[CELL_FIRSTCOL
                                                                        + currentColumn][i]);
+                               }
                        }
 
                        target.endTag("tr");
@@ -1533,12 +1591,14 @@ public class Table extends Select implements Action.Container,
                target.endTag("rows");
 
                // The select variable is only enabled if selectable
-               if (selectable)
+               if (selectable) {
                        target.addVariable(this, "selected", selectedKeys);
+               }
 
                // The cursors are only shown on pageable table
-               if (first != 0 || getPageLength() > 0)
+               if (first != 0 || getPageLength() > 0) {
                        target.addVariable(this, "firstvisible", first);
+               }
 
                // Sorting
                if (getContainerDataSource() instanceof Container.Sortable) {
@@ -1549,11 +1609,11 @@ public class Table extends Select implements Action.Container,
 
                // Resets and paints "to be painted next" variables. Also reset
                // pageBuffer
-               reqFirstRowToPaint = -1;
-               reqRowsToPaint = -1;
-               pageBuffer = null;
-               target.addVariable(this, "reqrows", reqRowsToPaint);
-               target.addVariable(this, "reqfirstrow", reqFirstRowToPaint);
+               this.reqFirstRowToPaint = -1;
+               this.reqRowsToPaint = -1;
+               this.pageBuffer = null;
+               target.addVariable(this, "reqrows", this.reqRowsToPaint);
+               target.addVariable(this, "reqfirstrow", this.reqFirstRowToPaint);
 
                // Actions
                if (!actionSet.isEmpty()) {
@@ -1562,11 +1622,13 @@ public class Table extends Select implements Action.Container,
                        for (Iterator it = actionSet.iterator(); it.hasNext();) {
                                Action a = (Action) it.next();
                                target.startTag("action");
-                               if (a.getCaption() != null)
+                               if (a.getCaption() != null) {
                                        target.addAttribute("caption", a.getCaption());
-                               if (a.getIcon() != null)
+                               }
+                               if (a.getIcon() != null) {
                                        target.addAttribute("icon", a.getIcon());
-                               target.addAttribute("key", actionMapper.key(a));
+                               }
+                               target.addAttribute("key", this.actionMapper.key(a));
                                target.endTag("action");
                        }
                        target.endTag("actions");
@@ -1583,17 +1645,18 @@ public class Table extends Select implements Action.Container,
                // Available columns
                if (this.columnCollapsingAllowed) {
                        HashSet ccs = new HashSet();
-                       for (Iterator i = visibleColumns.iterator(); i.hasNext();) {
+                       for (Iterator i = this.visibleColumns.iterator(); i.hasNext();) {
                                Object o = i.next();
-                               if (isColumnCollapsed(o))
+                               if (isColumnCollapsed(o)) {
                                        ccs.add(o);
+                               }
                        }
                        String[] collapsedkeys = new String[ccs.size()];
                        int nextColumn = 0;
                        for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
                                        && nextColumn < collapsedkeys.length;) {
                                Object columnId = it.next();
-                               if (this.isColumnCollapsed(columnId)) {
+                               if (isColumnCollapsed(columnId)) {
                                        collapsedkeys[nextColumn++] = this.columnIdMap
                                                        .key(columnId);
                                }
@@ -1609,22 +1672,24 @@ public class Table extends Select implements Action.Container,
                                target.addAttribute("cid", this.columnIdMap.key(columnId));
                                String head = getColumnHeader(columnId);
                                target.addAttribute("caption", (head != null ? head : ""));
-                               if (this.isColumnCollapsed(columnId)) {
+                               if (isColumnCollapsed(columnId)) {
                                        target.addAttribute("collapsed", true);
                                }
                                if (colheads) {
-                                       if (this.getColumnIcon(columnId) != null)
-                                               target.addAttribute("icon", this
-                                                               .getColumnIcon(columnId));
-                                       if (sortables.contains(columnId))
+                                       if (getColumnIcon(columnId) != null) {
+                                               target.addAttribute("icon", getColumnIcon(columnId));
+                                       }
+                                       if (sortables.contains(columnId)) {
                                                target.addAttribute("sortable", true);
+                                       }
+                               }
+                               if (!ALIGN_LEFT.equals(getColumnAlignment(columnId))) {
+                                       target.addAttribute("align", getColumnAlignment(columnId));
                                }
-                               if (!ALIGN_LEFT.equals(this.getColumnAlignment(columnId)))
-                                       target.addAttribute("align", this
-                                                       .getColumnAlignment(columnId));
-                               if (getColumnWidth(columnId) > -1)
+                               if (getColumnWidth(columnId) > -1) {
                                        target.addAttribute("width", String
                                                        .valueOf(getColumnWidth(columnId)));
+                               }
 
                                target.endTag("column");
                        }
@@ -1649,25 +1714,27 @@ public class Table extends Select implements Action.Container,
        private Object[][] getVisibleCells() {
 
                // Returns a buffered value if possible
-               if (pageBuffer != null && isPageBufferingEnabled())
-                       return pageBuffer;
+               if (this.pageBuffer != null && isPageBufferingEnabled()) {
+                       return this.pageBuffer;
+               }
 
                // Stops listening the old properties and initialise the list
-               if (listenedProperties == null)
-                       listenedProperties = new LinkedList();
-               else
-                       for (Iterator i = listenedProperties.iterator(); i.hasNext();) {
+               if (this.listenedProperties == null) {
+                       this.listenedProperties = new LinkedList();
+               } else {
+                       for (Iterator i = this.listenedProperties.iterator(); i.hasNext();) {
                                ((Property.ValueChangeNotifier) i.next()).removeListener(this);
                        }
+               }
 
                // Detach old visible component from the table
-               if (visibleComponents == null)
-                       visibleComponents = new LinkedList();
-               else {
-                       for (Iterator i = visibleComponents.iterator(); i.hasNext();) {
+               if (this.visibleComponents == null) {
+                       this.visibleComponents = new LinkedList();
+               else {
+                       for (Iterator i = this.visibleComponents.iterator(); i.hasNext();) {
                                ((Component) i.next()).setParent(null);
                        }
-                       visibleComponents.clear();
+                       this.visibleComponents.clear();
                }
 
                // Collects the basic facts about the table page
@@ -1676,48 +1743,56 @@ public class Table extends Select implements Action.Container,
                int pagelen = getPageLength();
                int firstIndex = getCurrentPageFirstItemIndex();
                int rows = size();
-               if (rows > 0 && firstIndex >= 0)
+               if (rows > 0 && firstIndex >= 0) {
                        rows -= firstIndex;
-               if (pagelen > 0 && pagelen < rows)
+               }
+               if (pagelen > 0 && pagelen < rows) {
                        rows = pagelen;
+               }
 
                // If "to be painted next" variables are set, use them
-               if (reqRowsToPaint >= 0)
-                       rows = reqRowsToPaint;
+               if (this.reqRowsToPaint >= 0) {
+                       rows = this.reqRowsToPaint;
+               }
                Object id;
-               if (reqFirstRowToPaint >= 0 && reqFirstRowToPaint < size())
-                       firstIndex = reqFirstRowToPaint;
+               if (this.reqFirstRowToPaint >= 0 && this.reqFirstRowToPaint < size()) {
+                       firstIndex = this.reqFirstRowToPaint;
+               }
                if (size() > 0) {
-                       if (rows + firstIndex > size())
+                       if (rows + firstIndex > size()) {
                                rows = size() - firstIndex;
+                       }
                } else {
                        rows = 0;
                }
 
                Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows];
-               if (rows == 0)
+               if (rows == 0) {
                        return cells;
+               }
 
                // Gets the first item id
-               if (items instanceof Container.Indexed)
-                       id = ((Container.Indexed) items).getIdByIndex(firstIndex);
-               else {
-                       id = ((Container.Ordered) items).firstItemId();
-                       for (int i = 0; i < firstIndex; i++)
-                               id = ((Container.Ordered) items).nextItemId(id);
+               if (this.items instanceof Container.Indexed) {
+                       id = ((Container.Indexed) this.items).getIdByIndex(firstIndex);
+               } else {
+                       id = ((Container.Ordered) this.items).firstItemId();
+                       for (int i = 0; i < firstIndex; i++) {
+                               id = ((Container.Ordered) this.items).nextItemId(id);
+                       }
                }
 
                int headmode = getRowHeaderMode();
                boolean[] iscomponent = new boolean[cols];
-               for (int i = 0; i < cols; i++)
+               for (int i = 0; i < cols; i++) {
                        iscomponent[i] = Component.class
                                        .isAssignableFrom(getType(colids[i]));
+               }
 
                // Creates the page contents
                int filledRows = 0;
                for (int i = 0; i < rows && id != null; i++) {
                        cells[CELL_ITEMID][i] = id;
-                       cells[CELL_KEY][i] = itemIdMapper.key(id);
+                       cells[CELL_KEY][i] = this.itemIdMapper.key(id);
                        if (headmode != ROW_HEADER_MODE_HIDDEN) {
                                switch (headmode) {
                                case ROW_HEADER_MODE_INDEX:
@@ -1736,7 +1811,7 @@ public class Table extends Select implements Action.Container,
                                                if (p instanceof Property.ValueChangeNotifier) {
                                                        ((Property.ValueChangeNotifier) p)
                                                                        .addListener(this);
-                                                       listenedProperties.add(p);
+                                                       this.listenedProperties.add(p);
                                                }
                                                if (iscomponent[j]) {
                                                        value = p.getValue();
@@ -1751,13 +1826,13 @@ public class Table extends Select implements Action.Container,
 
                                        if (value instanceof Component) {
                                                ((Component) value).setParent(this);
-                                               visibleComponents.add((Component) value);
+                                               this.visibleComponents.add(value);
                                        }
                                        cells[CELL_FIRSTCOL + j][i] = value;
 
                                }
                        }
-                       id = ((Container.Ordered) items).nextItemId(id);
+                       id = ((Container.Ordered) this.items).nextItemId(id);
 
                        filledRows++;
                }
@@ -1765,16 +1840,19 @@ public class Table extends Select implements Action.Container,
                // Assures that all the rows of the cell-buffer are valid
                if (filledRows != cells[0].length) {
                        Object[][] temp = new Object[cells.length][filledRows];
-                       for (int i = 0; i < cells.length; i++)
-                               for (int j = 0; j < filledRows; j++)
+                       for (int i = 0; i < cells.length; i++) {
+                               for (int j = 0; j < filledRows; j++) {
                                        temp[i][j] = cells[i][j];
+                               }
+                       }
                        cells = temp;
                }
 
                // Saves the results to internal buffer iff in buffering mode
                // to possible conserve memory from large non-buffered pages
-               if (isPageBufferingEnabled())
-                       pageBuffer = cells;
+               if (isPageBufferingEnabled()) {
+                       this.pageBuffer = cells;
+               }
 
                return cells;
        }
@@ -1797,7 +1875,7 @@ public class Table extends Select implements Action.Container,
         */
        protected Object getPropertyValue(Object rowId, Object colId,
                        Property property) {
-               if (this.isEditable() && this.fieldFactory != null) {
+               if (isEditable() && this.fieldFactory != null) {
                        Field f = this.fieldFactory.createField(getContainerDataSource(),
                                        rowId, colId, this);
                        if (f != null) {
@@ -1841,13 +1919,13 @@ public class Table extends Select implements Action.Container,
 
                if (actionHandler != null) {
 
-                       if (actionHandlers == null) {
-                               actionHandlers = new LinkedList();
-                               actionMapper = new KeyMapper();
+                       if (this.actionHandlers == null) {
+                               this.actionHandlers = new LinkedList();
+                               this.actionMapper = new KeyMapper();
                        }
 
-                       if (!actionHandlers.contains(actionHandler)) {
-                               actionHandlers.add(actionHandler);
+                       if (!this.actionHandlers.contains(actionHandler)) {
+                               this.actionHandlers.add(actionHandler);
                                requestRepaint();
                        }
 
@@ -1862,13 +1940,14 @@ public class Table extends Select implements Action.Container,
         */
        public void removeActionHandler(Action.Handler actionHandler) {
 
-               if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
+               if (this.actionHandlers != null
+                               && this.actionHandlers.contains(actionHandler)) {
 
-                       actionHandlers.remove(actionHandler);
+                       this.actionHandlers.remove(actionHandler);
 
-                       if (actionHandlers.isEmpty()) {
-                               actionHandlers = null;
-                               actionMapper = null;
+                       if (this.actionHandlers.isEmpty()) {
+                               this.actionHandlers = null;
+                               this.actionMapper = null;
                        }
 
                        requestRepaint();
@@ -1895,9 +1974,11 @@ public class Table extends Select implements Action.Container,
        public void attach() {
                super.attach();
 
-               if (visibleComponents != null)
-                       for (Iterator i = visibleComponents.iterator(); i.hasNext();)
+               if (this.visibleComponents != null) {
+                       for (Iterator i = this.visibleComponents.iterator(); i.hasNext();) {
                                ((Component) i.next()).attach();
+                       }
+               }
        }
 
        /**
@@ -1908,9 +1989,11 @@ public class Table extends Select implements Action.Container,
        public void detach() {
                super.detach();
 
-               if (visibleComponents != null)
-                       for (Iterator i = visibleComponents.iterator(); i.hasNext();)
+               if (this.visibleComponents != null) {
+                       for (Iterator i = this.visibleComponents.iterator(); i.hasNext();) {
                                ((Component) i.next()).detach();
+                       }
+               }
        }
 
        /**
@@ -1930,7 +2013,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container#removeItem(Object)
         */
        public boolean removeItem(Object itemId) {
-               Object nextItemId = ((Container.Ordered) items).nextItemId(itemId);
+               Object nextItemId = ((Container.Ordered) this.items).nextItemId(itemId);
                boolean ret = super.removeItem(itemId);
                if (ret && (itemId != null)
                                && (itemId.equals(this.currentPageFirstItemId))) {
@@ -1970,10 +2053,12 @@ public class Table extends Select implements Action.Container,
         */
        public boolean addContainerProperty(Object propertyId, Class type,
                        Object defaultValue) throws UnsupportedOperationException {
-               if (!super.addContainerProperty(propertyId, type, defaultValue))
+               if (!super.addContainerProperty(propertyId, type, defaultValue)) {
                        return false;
-               if (!this.visibleColumns.contains(propertyId))
+               }
+               if (!this.visibleColumns.contains(propertyId)) {
                        this.visibleColumns.add(propertyId);
+               }
                return true;
        }
 
@@ -2002,11 +2087,12 @@ public class Table extends Select implements Action.Container,
        public boolean addContainerProperty(Object propertyId, Class type,
                        Object defaultValue, String columnHeader, Resource columnIcon,
                        String columnAlignment) throws UnsupportedOperationException {
-               if (!this.addContainerProperty(propertyId, type, defaultValue))
+               if (!this.addContainerProperty(propertyId, type, defaultValue)) {
                        return false;
-               this.setColumnAlignment(propertyId, columnAlignment);
-               this.setColumnHeader(propertyId, columnHeader);
-               this.setColumnIcon(propertyId, columnIcon);
+               }
+               setColumnAlignment(propertyId, columnAlignment);
+               setColumnHeader(propertyId, columnHeader);
+               setColumnIcon(propertyId, columnIcon);
                return true;
        }
 
@@ -2020,8 +2106,9 @@ public class Table extends Select implements Action.Container,
                LinkedList visible = new LinkedList();
 
                Object[][] cells = getVisibleCells();
-               for (int i = 0; i < cells[CELL_ITEMID].length; i++)
+               for (int i = 0; i < cells[CELL_ITEMID].length; i++) {
                        visible.add(cells[CELL_ITEMID][i]);
+               }
 
                return visible;
        }
@@ -2033,9 +2120,9 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.ItemSetChangeListener#containerItemSetChange(com.itmill.toolkit.data.Container.ItemSetChangeEvent)
         */
        public void containerItemSetChange(Container.ItemSetChangeEvent event) {
-               pageBuffer = null;
+               this.pageBuffer = null;
                super.containerItemSetChange(event);
-               setCurrentPageFirstItemIndex(this.getCurrentPageFirstItemIndex());
+               setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex());
        }
 
        /**
@@ -2046,7 +2133,7 @@ public class Table extends Select implements Action.Container,
         */
        public void containerPropertySetChange(
                        Container.PropertySetChangeEvent event) {
-               pageBuffer = null;
+               this.pageBuffer = null;
                super.containerPropertySetChange(event);
        }
 
@@ -2059,8 +2146,9 @@ public class Table extends Select implements Action.Container,
         */
        public void setNewItemsAllowed(boolean allowNewOptions)
                        throws UnsupportedOperationException {
-               if (allowNewOptions)
+               if (allowNewOptions) {
                        throw new UnsupportedOperationException();
+               }
        }
 
        /**
@@ -2080,7 +2168,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.Ordered#nextItemId(java.lang.Object)
         */
        public Object nextItemId(Object itemId) {
-               return ((Container.Ordered) items).nextItemId(itemId);
+               return ((Container.Ordered) this.items).nextItemId(itemId);
        }
 
        /**
@@ -2090,7 +2178,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.Ordered#prevItemId(java.lang.Object)
         */
        public Object prevItemId(Object itemId) {
-               return ((Container.Ordered) items).prevItemId(itemId);
+               return ((Container.Ordered) this.items).prevItemId(itemId);
        }
 
        /**
@@ -2099,7 +2187,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.Ordered#firstItemId()
         */
        public Object firstItemId() {
-               return ((Container.Ordered) items).firstItemId();
+               return ((Container.Ordered) this.items).firstItemId();
        }
 
        /**
@@ -2108,7 +2196,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.Ordered#lastItemId()
         */
        public Object lastItemId() {
-               return ((Container.Ordered) items).lastItemId();
+               return ((Container.Ordered) this.items).lastItemId();
        }
 
        /**
@@ -2118,7 +2206,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.Ordered#isFirstId(java.lang.Object)
         */
        public boolean isFirstId(Object itemId) {
-               return ((Container.Ordered) items).isFirstId(itemId);
+               return ((Container.Ordered) this.items).isFirstId(itemId);
        }
 
        /**
@@ -2128,7 +2216,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.data.Container.Ordered#isLastId(java.lang.Object)
         */
        public boolean isLastId(Object itemId) {
-               return ((Container.Ordered) items).isLastId(itemId);
+               return ((Container.Ordered) this.items).isLastId(itemId);
        }
 
        /**
@@ -2138,7 +2226,7 @@ public class Table extends Select implements Action.Container,
         */
        public Object addItemAfter(Object previousItemId)
                        throws UnsupportedOperationException {
-               return ((Container.Ordered) items).addItemAfter(previousItemId);
+               return ((Container.Ordered) this.items).addItemAfter(previousItemId);
        }
 
        /**
@@ -2149,7 +2237,7 @@ public class Table extends Select implements Action.Container,
         */
        public Item addItemAfter(Object previousItemId, Object newItemId)
                        throws UnsupportedOperationException {
-               return ((Container.Ordered) items).addItemAfter(previousItemId,
+               return ((Container.Ordered) this.items).addItemAfter(previousItemId,
                                newItemId);
        }
 
@@ -2162,7 +2250,7 @@ public class Table extends Select implements Action.Container,
         * @see #isEditable
         */
        public FieldFactory getFieldFactory() {
-               return fieldFactory;
+               return this.fieldFactory;
        }
 
        /**
@@ -2200,7 +2288,7 @@ public class Table extends Select implements Action.Container,
         * 
         */
        public boolean isEditable() {
-               return editable;
+               return this.editable;
        }
 
        /**
@@ -2240,7 +2328,7 @@ public class Table extends Select implements Action.Container,
                        throws UnsupportedOperationException {
                Container c = getContainerDataSource();
                if (c instanceof Container.Sortable) {
-                       int pageIndex = this.getCurrentPageFirstItemIndex();
+                       int pageIndex = getCurrentPageFirstItemIndex();
                        ((Container.Sortable) c).sort(propertyId, ascending);
                        setCurrentPageFirstItemIndex(pageIndex);
                } else if (c != null) {
@@ -2257,8 +2345,9 @@ public class Table extends Select implements Action.Container,
         *             Container.Sortable
         */
        public void sort() {
-               if (getSortContainerPropertyId() == null)
+               if (getSortContainerPropertyId() == null) {
                        return;
+               }
                sort(new Object[] { this.sortContainerPropertyId },
                                new boolean[] { this.sortAscending });
        }
@@ -2340,7 +2429,7 @@ public class Table extends Select implements Action.Container,
         * @return True iff sorting is disabled.
         */
        public boolean isSortDisabled() {
-               return sortDisabled;
+               return this.sortDisabled;
        }
 
        /**
@@ -2365,7 +2454,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits()
         */
        public int getHeightUnits() {
-               return heightUnit;
+               return this.heightUnit;
        }
 
        /**
@@ -2374,7 +2463,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits()
         */
        public int getWidthUnits() {
-               return widthUnit;
+               return this.widthUnit;
        }
 
        /**
@@ -2395,8 +2484,9 @@ public class Table extends Select implements Action.Container,
         */
        public void setWidthUnits(int units) {
                if (units != Sizeable.UNITS_PIXELS
-                               && units != Sizeable.UNITS_PERCENTAGE)
+                               && units != Sizeable.UNITS_PERCENTAGE) {
                        throw new IllegalArgumentException();
+               }
                this.widthUnit = units;
        }
 
@@ -2407,7 +2497,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.terminal.Sizeable#getHeight()
         */
        public int getHeight() {
-               return height;
+               return this.height;
        }
 
        /**
@@ -2417,7 +2507,7 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.terminal.Sizeable#getWidth()
         */
        public int getWidth() {
-               return width;
+               return this.width;
        }
 
        /**
@@ -2451,9 +2541,10 @@ public class Table extends Select implements Action.Container,
         * @see com.itmill.toolkit.ui.Select#setLazyLoading(boolean)
         */
        public void setLazyLoading(boolean useLazyLoading) {
-               if (useLazyLoading)
+               if (useLazyLoading) {
                        throw new UnsupportedOperationException(
                                        "Lazy options loading is not supported by Table.");
+               }
        }
 
 }
\ No newline at end of file
index 5d84385b7e020bf890f175235863ade2d50ceb05..0aaa22a3c7ec333f4444171298ca45395db8958c 100644 (file)
@@ -57,7 +57,7 @@ import com.itmill.toolkit.terminal.Resource;
  * @VERSION@
  * @since 3.0
  */
-public class Tree extends Select implements Container.Hierarchical,
+public class Tree extends AbstractSelect implements Container.Hierarchical,
                Action.Container {
 
        /* Static members ***************************************************** */
@@ -85,7 +85,7 @@ public class Tree extends Select implements Container.Hierarchical,
        /**
         * Set of expanded nodes.
         */
-       private HashSet expanded = new HashSet();
+       private final HashSet expanded = new HashSet();
 
        /**
         * List of action handlers.
@@ -156,7 +156,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @return true iff the item is expanded.
         */
        public boolean isExpanded(Object itemId) {
-               return expanded.contains(itemId);
+               return this.expanded.contains(itemId);
        }
 
        /**
@@ -169,21 +169,24 @@ public class Tree extends Select implements Container.Hierarchical,
        public boolean expandItem(Object itemId) {
 
                // Succeeds if the node is already expanded
-               if (isExpanded(itemId))
+               if (isExpanded(itemId)) {
                        return true;
+               }
 
                // Nodes that can not have children are not expandable
-               if (!areChildrenAllowed(itemId))
+               if (!areChildrenAllowed(itemId)) {
                        return false;
+               }
 
                // Expands
-               expanded.add(itemId);
+               this.expanded.add(itemId);
 
-               expandedItemId = itemId;
-               if (initialPaint)
+               this.expandedItemId = itemId;
+               if (this.initialPaint) {
                        requestRepaint();
-               else
+               } else {
                        requestPartialRepaint();
+               }
                fireExpandEvent(itemId);
 
                return true;
@@ -191,12 +194,12 @@ public class Tree extends Select implements Container.Hierarchical,
 
        public void requestRepaint() {
                super.requestRepaint();
-               partialUpdate = false;
+               this.partialUpdate = false;
        }
 
        private void requestPartialRepaint() {
                super.requestRepaint();
-               partialUpdate = true;
+               this.partialUpdate = true;
        }
 
        /**
@@ -240,11 +243,12 @@ public class Tree extends Select implements Container.Hierarchical,
        public boolean collapseItem(Object itemId) {
 
                // Succeeds if the node is already collapsed
-               if (!isExpanded(itemId))
+               if (!isExpanded(itemId)) {
                        return true;
+               }
 
                // Collapse
-               expanded.remove(itemId);
+               this.expanded.remove(itemId);
                requestRepaint();
                fireCollapseEvent(itemId);
 
@@ -336,9 +340,9 @@ public class Tree extends Select implements Container.Hierarchical,
                if (variables.containsKey("collapse")) {
                        String[] keys = (String[]) variables.get("collapse");
                        for (int i = 0; i < keys.length; i++) {
-                               Object id = itemIdMapper.get(keys[i]);
+                               Object id = this.itemIdMapper.get(keys[i]);
                                if (id != null && isExpanded(id)) {
-                                       expanded.remove(id);
+                                       this.expanded.remove(id);
                                        fireCollapseEvent(id);
                                }
                        }
@@ -348,9 +352,10 @@ public class Tree extends Select implements Container.Hierarchical,
                if (variables.containsKey("expand")) {
                        String[] keys = (String[]) variables.get("expand");
                        for (int i = 0; i < keys.length; i++) {
-                               Object id = itemIdMapper.get(keys[i]);
-                               if (id != null)
+                               Object id = this.itemIdMapper.get(keys[i]);
+                               if (id != null) {
                                        expandItem(id);
+                               }
                        }
                }
 
@@ -363,13 +368,16 @@ public class Tree extends Select implements Container.Hierarchical,
                        StringTokenizer st = new StringTokenizer((String) variables
                                        .get("action"), ",");
                        if (st.countTokens() == 2) {
-                               Object itemId = itemIdMapper.get(st.nextToken());
-                               Action action = (Action) actionMapper.get(st.nextToken());
+                               Object itemId = this.itemIdMapper.get(st.nextToken());
+                               Action action = (Action) this.actionMapper.get(st.nextToken());
                                if (action != null && containsId(itemId)
-                                               && actionHandlers != null)
-                                       for (Iterator i = actionHandlers.iterator(); i.hasNext();)
+                                               && this.actionHandlers != null) {
+                                       for (Iterator i = this.actionHandlers.iterator(); i
+                                                       .hasNext();) {
                                                ((Action.Handler) i.next()).handleAction(action, this,
                                                                itemId);
+                                       }
+                               }
                        }
                }
        }
@@ -380,53 +388,60 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.ui.AbstractComponent#paintContent(PaintTarget)
         */
        public void paintContent(PaintTarget target) throws PaintException {
-               initialPaint = false;
+               this.initialPaint = false;
 
-               if (partialUpdate) {
+               if (this.partialUpdate) {
                        target.addAttribute("partialUpdate", true);
-                       target.addAttribute("rootKey", itemIdMapper.key(expandedItemId));
+                       target.addAttribute("rootKey", this.itemIdMapper
+                                       .key(this.expandedItemId));
                } else {
 
                        // Focus control id
-                       if (this.getFocusableId() > 0) {
-                               target.addAttribute("focusid", this.getFocusableId());
+                       if (getFocusableId() > 0) {
+                               target.addAttribute("focusid", getFocusableId());
                        }
 
                        // The tab ordering number
-                       if (this.getTabIndex() > 0)
-                               target.addAttribute("tabindex", this.getTabIndex());
+                       if (getTabIndex() > 0) {
+                               target.addAttribute("tabindex", getTabIndex());
+                       }
 
                        // Paint tree attributes
-                       if (isSelectable())
+                       if (isSelectable()) {
                                target.addAttribute("selectmode", (isMultiSelect() ? "multi"
                                                : "single"));
-                       else
+                       } else {
                                target.addAttribute("selectmode", "none");
-                       if (isNewItemsAllowed())
+                       }
+                       if (isNewItemsAllowed()) {
                                target.addAttribute("allownewitem", true);
+                       }
 
                }
 
                // Initialize variables
                Set actionSet = new LinkedHashSet();
                String[] selectedKeys;
-               if (isMultiSelect())
+               if (isMultiSelect()) {
                        selectedKeys = new String[((Set) getValue()).size()];
-               else
+               } else {
                        selectedKeys = new String[(getValue() == null ? 0 : 1)];
+               }
                int keyIndex = 0;
                LinkedList expandedKeys = new LinkedList();
 
                // Iterates through hierarchical tree using a stack of iterators
                Stack iteratorStack = new Stack();
                Collection ids;
-               if (partialUpdate)
-                       ids = getChildren(expandedItemId);
-               else
+               if (this.partialUpdate) {
+                       ids = getChildren(this.expandedItemId);
+               } else {
                        ids = rootItemIds();
+               }
 
-               if (ids != null)
+               if (ids != null) {
                        iteratorStack.push(ids.iterator());
+               }
 
                while (!iteratorStack.isEmpty()) {
 
@@ -440,8 +455,9 @@ public class Tree extends Select implements Container.Hierarchical,
                                iteratorStack.pop();
 
                                // Closes node
-                               if (!iteratorStack.isEmpty())
+                               if (!iteratorStack.isEmpty()) {
                                        target.endTag("node");
+                               }
                        }
 
                        // Adds the item on current level
@@ -451,17 +467,19 @@ public class Tree extends Select implements Container.Hierarchical,
                                // Starts the item / node
                                boolean isNode = areChildrenAllowed(itemId)
                                                && hasChildren(itemId);
-                               if (isNode)
+                               if (isNode) {
                                        target.startTag("node");
-                               else
+                               } else {
                                        target.startTag("leaf");
+                               }
 
                                // Adds the attributes
                                target.addAttribute("caption", getItemCaption(itemId));
                                Resource icon = getItemIcon(itemId);
-                               if (icon != null)
+                               if (icon != null) {
                                        target.addAttribute("icon", getItemIcon(itemId));
-                               String key = itemIdMapper.key(itemId);
+                               }
+                               String key = this.itemIdMapper.key(itemId);
                                target.addAttribute("key", key);
                                if (isSelected(itemId)) {
                                        target.addAttribute("selected", true);
@@ -473,18 +491,19 @@ public class Tree extends Select implements Container.Hierarchical,
                                }
 
                                // Actions
-                               if (actionHandlers != null) {
+                               if (this.actionHandlers != null) {
                                        ArrayList keys = new ArrayList();
-                                       for (Iterator ahi = actionHandlers.iterator(); ahi
+                                       for (Iterator ahi = this.actionHandlers.iterator(); ahi
                                                        .hasNext();) {
                                                Action[] aa = ((Action.Handler) ahi.next()).getActions(
                                                                itemId, this);
-                                               if (aa != null)
+                                               if (aa != null) {
                                                        for (int ai = 0; ai < aa.length; ai++) {
-                                                               String akey = actionMapper.key(aa[ai]);
+                                                               String akey = this.actionMapper.key(aa[ai]);
                                                                actionSet.add(aa[ai]);
                                                                keys.add(akey);
                                                        }
+                                               }
                                        }
                                        target.addAttribute("al", keys.toArray());
                                }
@@ -494,10 +513,11 @@ public class Tree extends Select implements Container.Hierarchical,
                                                && areChildrenAllowed(itemId)) {
                                        iteratorStack.push(getChildren(itemId).iterator());
                                } else {
-                                       if (isNode)
+                                       if (isNode) {
                                                target.endTag("node");
-                                       else
+                                       } else {
                                                target.endTag("leaf");
+                                       }
                                }
                        }
                }
@@ -509,18 +529,20 @@ public class Tree extends Select implements Container.Hierarchical,
                        for (Iterator i = actionSet.iterator(); i.hasNext();) {
                                Action a = (Action) i.next();
                                target.startTag("action");
-                               if (a.getCaption() != null)
+                               if (a.getCaption() != null) {
                                        target.addAttribute("caption", a.getCaption());
-                               if (a.getIcon() != null)
+                               }
+                               if (a.getIcon() != null) {
                                        target.addAttribute("icon", a.getIcon());
-                               target.addAttribute("key", actionMapper.key(a));
+                               }
+                               target.addAttribute("key", this.actionMapper.key(a));
                                target.endTag("action");
                        }
                        target.endTag("actions");
                }
 
-               if (partialUpdate) {
-                       partialUpdate = false;
+               if (this.partialUpdate) {
+                       this.partialUpdate = false;
                } else {
                        // Selected
                        target.addVariable(this, "selected", selectedKeys);
@@ -542,7 +564,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.data.Container.Hierarchical#areChildrenAllowed(Object)
         */
        public boolean areChildrenAllowed(Object itemId) {
-               return ((Container.Hierarchical) items).areChildrenAllowed(itemId);
+               return ((Container.Hierarchical) this.items).areChildrenAllowed(itemId);
        }
 
        /**
@@ -551,7 +573,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.data.Container.Hierarchical#getChildren(Object)
         */
        public Collection getChildren(Object itemId) {
-               return ((Container.Hierarchical) items).getChildren(itemId);
+               return ((Container.Hierarchical) this.items).getChildren(itemId);
        }
 
        /**
@@ -560,7 +582,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.data.Container.Hierarchical#getParent(Object)
         */
        public Object getParent(Object itemId) {
-               return ((Container.Hierarchical) items).getParent(itemId);
+               return ((Container.Hierarchical) this.items).getParent(itemId);
        }
 
        /**
@@ -570,7 +592,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.data.Container.Hierarchical#hasChildren(Object)
         */
        public boolean hasChildren(Object itemId) {
-               return ((Container.Hierarchical) items).hasChildren(itemId);
+               return ((Container.Hierarchical) this.items).hasChildren(itemId);
        }
 
        /**
@@ -579,7 +601,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.data.Container.Hierarchical#isRoot(Object)
         */
        public boolean isRoot(Object itemId) {
-               return ((Container.Hierarchical) items).isRoot(itemId);
+               return ((Container.Hierarchical) this.items).isRoot(itemId);
        }
 
        /**
@@ -588,7 +610,7 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.data.Container.Hierarchical#rootItemIds()
         */
        public Collection rootItemIds() {
-               return ((Container.Hierarchical) items).rootItemIds();
+               return ((Container.Hierarchical) this.items).rootItemIds();
        }
 
        /**
@@ -598,10 +620,11 @@ public class Tree extends Select implements Container.Hierarchical,
         *      boolean)
         */
        public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) {
-               boolean success = ((Container.Hierarchical) items).setChildrenAllowed(
-                               itemId, areChildrenAllowed);
-               if (success)
+               boolean success = ((Container.Hierarchical) this.items)
+                               .setChildrenAllowed(itemId, areChildrenAllowed);
+               if (success) {
                        fireValueChange(false);
+               }
                return success;
        }
 
@@ -612,10 +635,11 @@ public class Tree extends Select implements Container.Hierarchical,
         *      Object)
         */
        public boolean setParent(Object itemId, Object newParentId) {
-               boolean success = ((Container.Hierarchical) items).setParent(itemId,
-                               newParentId);
-               if (success)
+               boolean success = ((Container.Hierarchical) this.items).setParent(
+                               itemId, newParentId);
+               if (success) {
                        requestRepaint();
+               }
                return success;
        }
 
@@ -631,11 +655,12 @@ public class Tree extends Select implements Container.Hierarchical,
                // Assure that the data source is ordered by making unordered
                // containers ordered by wrapping them
                if (Container.Hierarchical.class.isAssignableFrom(newDataSource
-                               .getClass()))
+                               .getClass())) {
                        super.setContainerDataSource(newDataSource);
-               else
+               } else {
                        super.setContainerDataSource(new ContainerHierarchicalWrapper(
                                        newDataSource));
+               }
        }
 
        /* Expand event and listener ****************************************** */
@@ -657,7 +682,7 @@ public class Tree extends Select implements Container.Hierarchical,
                 */
                private static final long serialVersionUID = 3832624001804481075L;
 
-               private Object expandedItemId;
+               private final Object expandedItemId;
 
                /**
                 * New instance of options change event
@@ -747,7 +772,7 @@ public class Tree extends Select implements Container.Hierarchical,
                 */
                private static final long serialVersionUID = 3257009834783290160L;
 
-               private Object collapsedItemId;
+               private final Object collapsedItemId;
 
                /**
                 * New instance of options change event.
@@ -767,7 +792,7 @@ public class Tree extends Select implements Container.Hierarchical,
                 * @return the collapsed item id.
                 */
                public Object getItemId() {
-                       return collapsedItemId;
+                       return this.collapsedItemId;
                }
        }
 
@@ -831,13 +856,13 @@ public class Tree extends Select implements Container.Hierarchical,
 
                if (actionHandler != null) {
 
-                       if (actionHandlers == null) {
-                               actionHandlers = new LinkedList();
-                               actionMapper = new KeyMapper();
+                       if (this.actionHandlers == null) {
+                               this.actionHandlers = new LinkedList();
+                               this.actionMapper = new KeyMapper();
                        }
 
-                       if (!actionHandlers.contains(actionHandler)) {
-                               actionHandlers.add(actionHandler);
+                       if (!this.actionHandlers.contains(actionHandler)) {
+                               this.actionHandlers.add(actionHandler);
                                requestRepaint();
                        }
                }
@@ -850,13 +875,14 @@ public class Tree extends Select implements Container.Hierarchical,
         */
        public void removeActionHandler(Action.Handler actionHandler) {
 
-               if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
+               if (this.actionHandlers != null
+                               && this.actionHandlers.contains(actionHandler)) {
 
-                       actionHandlers.remove(actionHandler);
+                       this.actionHandlers.remove(actionHandler);
 
-                       if (actionHandlers.isEmpty()) {
-                               actionHandlers = null;
-                               actionMapper = null;
+                       if (this.actionHandlers.isEmpty()) {
+                               this.actionHandlers = null;
+                               this.actionMapper = null;
                        }
 
                        requestRepaint();
@@ -875,8 +901,9 @@ public class Tree extends Select implements Container.Hierarchical,
                // Iterates trough hierarchical tree using a stack of iterators
                Stack iteratorStack = new Stack();
                Collection ids = rootItemIds();
-               if (ids != null)
+               if (ids != null) {
                        iteratorStack.push(ids.iterator());
+               }
                while (!iteratorStack.isEmpty()) {
 
                        // Gets the iterator for current tree level
@@ -914,8 +941,9 @@ public class Tree extends Select implements Container.Hierarchical,
         */
        public void setNewItemsAllowed(boolean allowNewOptions)
                        throws UnsupportedOperationException {
-               if (allowNewOptions)
+               if (allowNewOptions) {
                        throw new UnsupportedOperationException();
+               }
        }
 
        /**
@@ -936,9 +964,10 @@ public class Tree extends Select implements Container.Hierarchical,
         * @see com.itmill.toolkit.ui.Select#setLazyLoading(boolean)
         */
        public void setLazyLoading(boolean useLazyLoading) {
-               if (useLazyLoading)
+               if (useLazyLoading) {
                        throw new UnsupportedOperationException(
                                        "Lazy options loading is not supported by Tree.");
+               }
        }
 
 }
index ec129934ce687a8a5db98bd423bba5924fe5cca9..70bbf4709810c4af7ade55ef486bf5e0e1d76f06 100644 (file)
@@ -10,10 +10,10 @@ import com.itmill.toolkit.terminal.PaintException;
 import com.itmill.toolkit.terminal.PaintTarget;
 
 /**
- * Multiselect component with two lists: left side for available items and right side for
- * selected items.
+ * Multiselect component with two lists: left side for available items and right
+ * side for selected items.
  */
-public class TwinColSelect extends Select {
+public class TwinColSelect extends AbstractSelect {
 
        /**
         * 
diff --git a/src/com/itmill/toolkit/ui/select/ContainsFilter.java b/src/com/itmill/toolkit/ui/select/ContainsFilter.java
deleted file mode 100644 (file)
index 6f4f353..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.itmill.toolkit.ui.select;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.itmill.toolkit.data.Item;
-import com.itmill.toolkit.ui.Select;
-
-public class ContainsFilter implements OptionFilter {
-       private Select s;
-
-       private ArrayList filteredItemsBuffer;
-
-       private String prevFilter;
-
-       public ContainsFilter(Select s) {
-               this.s = s;
-       }
-
-       public List filter(String filterstring, int pageLength, int page) {
-               if (filterstring == null) {
-                       filterstring = "";
-               }
-               if (this.prevFilter != filterstring || filteredItemsBuffer == null) {
-                       if ("".equals(filterstring)) {
-                               this.filteredItemsBuffer = new ArrayList(s.getItemIds());
-                       } else if (s.getContainerDataSource() != null) {
-                               // prefix MUST be in lowercase
-                               filterstring = filterstring.toLowerCase();
-
-                               // all items will be iterated and tested.
-                               // SLOW when there are lot of items.
-                               this.filteredItemsBuffer = new ArrayList();
-                               for (Iterator iter = s.getItemIds().iterator(); iter.hasNext();) {
-                                       Object id = iter.next();
-
-                                       Item item = s.getItem(id);
-                                       String test = "";
-                                       if (s.getItemCaptionMode() == Select.ITEM_CAPTION_MODE_PROPERTY)
-                                               test = item.getItemProperty(
-                                                               s.getItemCaptionPropertyId()).getValue()
-                                                               .toString().trim();
-                                       else
-                                               test = String.valueOf(id);
-
-                                       if (test.toLowerCase().indexOf(filterstring) > -1) {
-                                               this.filteredItemsBuffer.add(id);
-                                       }
-                               }
-                       }
-               }
-
-               prevFilter = filterstring;
-
-               if (filteredItemsBuffer.size() > pageLength) {
-                       int first = page * pageLength;
-                       int last = first + pageLength;
-                       if (filteredItemsBuffer.size() < last) {
-                               last = filteredItemsBuffer.size();
-                       }
-                       return filteredItemsBuffer.subList(first, last);
-               } else {
-                       return filteredItemsBuffer;
-               }
-       }
-
-       public int getMatchCount() {
-               return filteredItemsBuffer.size();
-       }
-}
diff --git a/src/com/itmill/toolkit/ui/select/OptionFilter.java b/src/com/itmill/toolkit/ui/select/OptionFilter.java
deleted file mode 100644 (file)
index 3b56eed..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.itmill.toolkit.ui.select;
-
-import java.util.List;
-
-public interface OptionFilter {
-       /**
-        * 
-        * @param filterstring
-        *            string to use in filtering
-        * @return List of filtered item id's
-        */
-       public List filter(String filterstring, int pageLength, int page);
-
-       /**
-        * Returns total matches in last filtering process
-        * 
-        * @return
-        */
-       public int getMatchCount();
-}
diff --git a/src/com/itmill/toolkit/ui/select/StartsWithFilter.java b/src/com/itmill/toolkit/ui/select/StartsWithFilter.java
deleted file mode 100644 (file)
index 9972aa5..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.itmill.toolkit.ui.select;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.itmill.toolkit.data.Item;
-import com.itmill.toolkit.ui.Select;
-
-public class StartsWithFilter implements OptionFilter {
-       private Select s;
-
-       public StartsWithFilter(Select s) {
-               this.s = s;
-       }
-
-       ArrayList filteredItemsBuffer;
-
-       private String prevFilter;
-
-       public List filter(String filterstring, int pageLength, int page) {
-               if (filterstring == null) {
-                       filterstring = "";
-               }
-               if (this.prevFilter != filterstring || filteredItemsBuffer == null) {
-                       if ("".equals(filterstring)) {
-                               this.filteredItemsBuffer = new ArrayList(s.getItemIds());
-                       } else if (s.getContainerDataSource() != null) {
-                               // prefix MUST be in lowercase
-                               filterstring = filterstring.toLowerCase();
-
-                               // all items will be iterated and tested.
-                               // SLOW when there are lot of items.
-                               this.filteredItemsBuffer = new ArrayList();
-                               for (Iterator iter = s.getItemIds().iterator(); iter.hasNext();) {
-                                       Object id = iter.next();
-
-                                       Item item = s.getItem(id);
-                                       String test = "";
-                                       if (s.getItemCaptionMode() == Select.ITEM_CAPTION_MODE_PROPERTY)
-                                               test = item.getItemProperty(
-                                                               s.getItemCaptionPropertyId()).getValue()
-                                                               .toString().trim();
-                                       else
-                                               test = String.valueOf(id);
-
-                                       if (test.toLowerCase().startsWith(filterstring)) {
-                                               this.filteredItemsBuffer.add(id);
-                                       }
-                               }
-                       }
-               }
-
-               prevFilter = filterstring;
-
-               if (filteredItemsBuffer.size() > pageLength) {
-                       int first = page * pageLength;
-                       int last = first + pageLength;
-                       if (filteredItemsBuffer.size() < last) {
-                               last = filteredItemsBuffer.size();
-                       }
-                       return filteredItemsBuffer.subList(first, last);
-               } else {
-                       return filteredItemsBuffer;
-               }
-       }
-
-       public int getMatchCount() {
-               return filteredItemsBuffer.size();
-       }
-}