]> source.dussan.org Git - vaadin-framework.git/commitdiff
Form and Table now sets property to fields Viewer property if one exists. fixes ...
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 16 Nov 2011 13:17:56 +0000 (13:17 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 16 Nov 2011 13:17:56 +0000 (13:17 +0000)
svn changeset:22019/svn branch:6.7

src/com/vaadin/data/util/PropertyFormatter.java
src/com/vaadin/ui/Form.java
src/com/vaadin/ui/Table.java
tests/testbench/com/vaadin/tests/components/form/FormWithPropertyFormatterConnected.java [new file with mode: 0644]

index 3afb1cede8b0efb1ae03717b498dfe5d23ad4b8c..18e1890259600647faae5a12111d2b23f0e39057 100644 (file)
@@ -33,7 +33,7 @@ import com.vaadin.data.Property;
  * @since 5.3.0
  */
 @SuppressWarnings("serial")
-public abstract class PropertyFormatter extends AbstractProperty implements
+public abstract class PropertyFormatter extends AbstractProperty implements Property.Viewer,
         Property.ValueChangeListener, Property.ReadOnlyStatusChangeListener {
 
     /** Datasource that stores the actual value. */
index 8ee702bbb47937748255d5ce773b61974958de90..1a28c679f92ffd792f6eca04154a5e321f09858a 100644 (file)
@@ -491,7 +491,7 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item,
         }
 
         // Configures the field
-        field.setPropertyDataSource(property);
+        bindPropertyToField(id, property, field);
 
         // Register and attach the created field
         addField(id, field);
@@ -755,13 +755,39 @@ public class Form extends AbstractField implements Item.Editor, Buffered, Item,
                 final Field f = fieldFactory.createField(itemDatasource, id,
                         this);
                 if (f != null) {
-                    f.setPropertyDataSource(property);
+                    bindPropertyToField(id, property, f);
                     addField(id, f);
                 }
             }
         }
     }
 
+    /**
+     * Binds an item property to a field. The default behavior is to bind
+     * property straight to Field. If Property.Viewer type property (e.g.
+     * PropertyFormatter) is already set for field, the property is bound to
+     * that Property.Viewer.
+     * 
+     * @param propertyId
+     * @param property
+     * @param field
+     * @since 6.7.3
+     */
+    protected void bindPropertyToField(final Object propertyId,
+            final Property property, final Field field) {
+        // check if field has a property that is Viewer set. In that case we
+        // expect developer has e.g. PropertyFormatter that he wishes to use and
+        // assign the property to the Viewer instead.
+        boolean hasFilterProperty = field.getPropertyDataSource() != null
+                && (field.getPropertyDataSource() instanceof Property.Viewer);
+        if (hasFilterProperty) {
+            ((Property.Viewer) field.getPropertyDataSource())
+                    .setPropertyDataSource(property);
+        } else {
+            field.setPropertyDataSource(property);
+        }
+    }
+
     /**
      * Gets the layout of the form.
      * 
index 5efb2545e0d4eea64283de7b4feda755f03825d1..c16505e57f5f4d4d1f2b3be7a1ad0652dc0226ab 100644 (file)
@@ -3405,7 +3405,7 @@ public class Table extends AbstractSelect implements Action.Container,
                 // Remember that we have made this association so we can remove
                 // it when the component is removed
                 associatedProperties.put(f, property);
-                f.setPropertyDataSource(property);
+                bindPropertyToField(rowId, colId, property, f);
                 return f;
             }
         }
@@ -3413,6 +3413,33 @@ public class Table extends AbstractSelect implements Action.Container,
         return formatPropertyValue(rowId, colId, property);
     }
 
+    /**
+     * Binds an item property to a field generated by TableFieldFactory. The
+     * default behavior is to bind property straight to Field. If
+     * Property.Viewer type property (e.g. PropertyFormatter) is already set for
+     * field, the property is bound to that Property.Viewer.
+     * 
+     * @param rowId
+     * @param colId
+     * @param property
+     * @param field
+     * @since 6.7.3
+     */
+    protected void bindPropertyToField(Object rowId, Object colId,
+            Property property, Field field) {
+        // check if field has a property that is Viewer set. In that case we
+        // expect developer has e.g. PropertyFormatter that he wishes to use and
+        // assign the property to the Viewer instead.
+        boolean hasFilterProperty = field.getPropertyDataSource() != null
+                && (field.getPropertyDataSource() instanceof Property.Viewer);
+        if (hasFilterProperty) {
+            ((Property.Viewer) field.getPropertyDataSource())
+                    .setPropertyDataSource(property);
+        } else {
+            field.setPropertyDataSource(property);
+        }
+    }
+
     /**
      * Formats table cell property values. By default the property.toString()
      * and return a empty string for null properties.
diff --git a/tests/testbench/com/vaadin/tests/components/form/FormWithPropertyFormatterConnected.java b/tests/testbench/com/vaadin/tests/components/form/FormWithPropertyFormatterConnected.java
new file mode 100644 (file)
index 0000000..116dd5b
--- /dev/null
@@ -0,0 +1,90 @@
+package com.vaadin.tests.components.form;\r
+\r
+import com.vaadin.data.Item;\r
+import com.vaadin.data.util.BeanItem;\r
+import com.vaadin.data.util.PropertyFormatter;\r
+import com.vaadin.tests.components.TestBase;\r
+import com.vaadin.ui.AbstractField;\r
+import com.vaadin.ui.Button;\r
+import com.vaadin.ui.Component;\r
+import com.vaadin.ui.DefaultFieldFactory;\r
+import com.vaadin.ui.Field;\r
+import com.vaadin.ui.Form;\r
+import com.vaadin.ui.FormFieldFactory;\r
+\r
+public class FormWithPropertyFormatterConnected extends TestBase {\r
+    @Override\r
+    protected void setup() {\r
+        Form form2 = new Form();\r
+        form2.setFormFieldFactory(new FormFieldFactory() {\r
+\r
+            public Field createField(Item item, Object propertyId,\r
+                    Component uiContext) {\r
+                AbstractField f = (AbstractField) DefaultFieldFactory.get()\r
+                        .createField(item, propertyId, uiContext);\r
+                if (propertyId.equals("age")) {\r
+                    f.setPropertyDataSource(new PropertyFormatter() {\r
+\r
+                        @Override\r
+                        public Object parse(String formattedValue)\r
+                                throws Exception {\r
+                            String str = formattedValue\r
+                                    .replaceAll("[^0-9.]", "");\r
+                            if (formattedValue.toLowerCase().contains("months")) {\r
+                                return Double.parseDouble(str) / 12;\r
+                            }\r
+                            return Double.parseDouble(str);\r
+                        }\r
+\r
+                        @Override\r
+                        public String format(Object value) {\r
+                            Double dValue = (Double) value;\r
+                            if (dValue < 1) {\r
+                                return ((int)(dValue * 12)) + " months";\r
+                            }\r
+                            return dValue + " years";\r
+                        }\r
+                    });\r
+                    f.setImmediate(true);\r
+                }\r
+                return f;\r
+            }\r
+        });\r
+        form2.setItemDataSource(createItem());\r
+        \r
+        addComponent(form2);\r
+        addComponent(new Button("B"));\r
+    }\r
+\r
+    private Item createItem() {\r
+        return new BeanItem<Person>(new Person(0.5));\r
+    }\r
+\r
+    public class Person {\r
+        public Person(double age) {\r
+            super();\r
+            this.age = age;\r
+        }\r
+\r
+        public double getAge() {\r
+            return age;\r
+        }\r
+\r
+        public void setAge(double age) {\r
+            this.age = age;\r
+        }\r
+\r
+        private double age;\r
+    }\r
+\r
+    @Override\r
+    protected String getDescription() {\r
+        return "It should be possible to inject PropertyFormatter and similar classses to fields in form. The test app hooks formatter that displays age in years or months and also accepts value in both (years by default, months if mentioned in the field)";\r
+    }\r
+\r
+    @Override\r
+    protected Integer getTicketNumber() {\r
+        return null;\r
+    }\r
+\r
+}\r