aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/vaadin/data/util/converter/ConverterUtil.java31
-rw-r--r--src/com/vaadin/ui/AbstractField.java4
-rw-r--r--src/com/vaadin/ui/Label.java86
-rw-r--r--tests/server-side/com/vaadin/tests/data/bean/Person.java10
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java59
5 files changed, 164 insertions, 26 deletions
diff --git a/src/com/vaadin/data/util/converter/ConverterUtil.java b/src/com/vaadin/data/util/converter/ConverterUtil.java
index 8be8ae799e..5fe3101db2 100644
--- a/src/com/vaadin/data/util/converter/ConverterUtil.java
+++ b/src/com/vaadin/data/util/converter/ConverterUtil.java
@@ -3,11 +3,12 @@
*/
package com.vaadin.data.util.converter;
+import java.io.Serializable;
import java.util.Locale;
import com.vaadin.Application;
-public class ConverterUtil {
+public class ConverterUtil implements Serializable {
public static <UITYPE, MODELTYPE> Converter<UITYPE, MODELTYPE> getConverter(
Class<UITYPE> uiType, Class<MODELTYPE> modelType) {
@@ -110,4 +111,32 @@ public class ConverterUtil {
}
+ /**
+ * Checks if the given converter can handle conversion between the given
+ * presentation and model type
+ *
+ * @param converter
+ * The converter to check
+ * @param presentationType
+ * The presentation type
+ * @param modelType
+ * The model type
+ * @return true if the converter supports conversion between the given
+ * presentation and model type, false otherwise
+ */
+ public static boolean canConverterHandle(Converter<?, ?> converter,
+ Class<?> presentationType, Class<?> modelType) {
+ if (converter == null) {
+ return false;
+ }
+
+ if (!modelType.isAssignableFrom(converter.getModelType())) {
+ return false;
+ }
+ if (!presentationType.isAssignableFrom(converter.getPresentationType())) {
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/src/com/vaadin/ui/AbstractField.java b/src/com/vaadin/ui/AbstractField.java
index 3c78c21b53..b74dba6d65 100644
--- a/src/com/vaadin/ui/AbstractField.java
+++ b/src/com/vaadin/ui/AbstractField.java
@@ -701,8 +701,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements
// Check if the current converter is compatible.
if (newDataSource != null
- && (getConverter() == null || !newDataSource.getType()
- .isAssignableFrom(getConverter().getModelType()))) {
+ && !ConverterUtil.canConverterHandle(getConverter(), getType(),
+ newDataSource.getType())) {
// Changing from e.g. Number -> Double should set a new converter,
// changing from Double -> Number can keep the old one (Property
// accepts Number)
diff --git a/src/com/vaadin/ui/Label.java b/src/com/vaadin/ui/Label.java
index 12b9aeab66..12e1f9590e 100644
--- a/src/com/vaadin/ui/Label.java
+++ b/src/com/vaadin/ui/Label.java
@@ -7,7 +7,8 @@ package com.vaadin.ui;
import java.lang.reflect.Method;
import com.vaadin.data.Property;
-import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ConverterUtil;
import com.vaadin.terminal.gwt.client.ui.label.ContentMode;
import com.vaadin.terminal.gwt.client.ui.label.LabelState;
@@ -76,9 +77,13 @@ public class Label extends AbstractComponent implements Property<String>,
@Deprecated
public static final ContentMode CONTENT_DEFAULT = ContentMode.TEXT;
- private static final String DATASOURCE_MUST_BE_SET = "Datasource must be set";
+ /**
+ * A converter used to convert from the data model type to the field type
+ * and vice versa. Label type is always String.
+ */
+ private Converter<String, Object> converter = null;
- private Property<String> dataSource;
+ private Property<String> dataSource = null;
/**
* Creates an empty Label.
@@ -113,7 +118,9 @@ public class Label extends AbstractComponent implements Property<String>,
* @param contentMode
*/
public Label(String content, ContentMode contentMode) {
- this(new ObjectProperty<String>(content, String.class), contentMode);
+ setValue(content);
+ setContentMode(contentMode);
+ setWidth(100, Unit.PERCENTAGE);
}
/**
@@ -126,15 +133,7 @@ public class Label extends AbstractComponent implements Property<String>,
public Label(Property contentSource, ContentMode contentMode) {
setPropertyDataSource(contentSource);
setContentMode(contentMode);
- setWidth(100, UNITS_PERCENTAGE);
- }
-
- @Override
- public void updateState() {
- super.updateState();
- // We don't know when the text is updated so update it here before
- // sending the state to the client
- getState().setText(getValue());
+ setWidth(100, Unit.PERCENTAGE);
}
@Override
@@ -149,24 +148,34 @@ public class Label extends AbstractComponent implements Property<String>,
* @return the Value of the label.
*/
public String getValue() {
- if (dataSource == null) {
- throw new IllegalStateException(DATASOURCE_MUST_BE_SET);
+ if (getPropertyDataSource() == null) {
+ // Use internal value if we are running without a data source
+ return getState().getText();
}
- return dataSource.getValue();
+ return ConverterUtil.convertFromModel(getPropertyDataSource()
+ .getValue(), String.class, getConverter(), getLocale());
}
/**
* Set the value of the label. Value of the label is the XML contents of the
* label.
*
- * @param newValue
+ * @param newStringValue
* the New value of the label.
*/
- public void setValue(Object newValue) {
- if (dataSource == null) {
- throw new IllegalStateException(DATASOURCE_MUST_BE_SET);
+ public void setValue(Object newStringValue) {
+ if (newStringValue != null && newStringValue.getClass() != String.class) {
+ throw new Converter.ConversionException("Value of type "
+ + newStringValue.getClass() + " cannot be assigned to "
+ + String.class.getName());
+ }
+ if (getPropertyDataSource() == null) {
+ getState().setText((String) newStringValue);
+ requestRepaint();
+ } else {
+ throw new IllegalStateException(
+ "Label is only a Property.Viewer and cannot update its data source");
}
- dataSource.setValue(newValue);
}
/**
@@ -215,7 +224,13 @@ public class Label extends AbstractComponent implements Property<String>,
((Property.ValueChangeNotifier) dataSource).removeListener(this);
}
- // Sets the new data source
+ if (!ConverterUtil.canConverterHandle(getConverter(), String.class,
+ newDataSource.getType())) {
+ // Try to find a converter
+ Converter<String, ?> c = ConverterUtil.getConverter(String.class,
+ newDataSource.getType());
+ setConverter(c);
+ }
dataSource = newDataSource;
// Listens the new data source if possible
@@ -331,7 +346,6 @@ public class Label extends AbstractComponent implements Property<String>,
protected void fireValueChange() {
// Set the error message
fireEvent(new Label.ValueChangeEvent(this));
- requestRepaint();
}
/**
@@ -340,6 +354,10 @@ public class Label extends AbstractComponent implements Property<String>,
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
*/
public void valueChange(Property.ValueChangeEvent event) {
+ // Update the internal value from the data source
+ getState().setText(getValue());
+ requestRepaint();
+
fireValueChange();
}
@@ -418,4 +436,26 @@ public class Label extends AbstractComponent implements Property<String>,
return res.toString();
}
+ /**
+ * Gets the converter used to convert the property data source value to the
+ * label value.
+ *
+ * @return The converter or null if none is set.
+ */
+ public Converter<String, Object> getConverter() {
+ return converter;
+ }
+
+ /**
+ * Sets the converter used to convert the label value to the property data
+ * source type. The converter must have a presentation type of String.
+ *
+ * @param converter
+ * The new converter to use.
+ */
+ public void setConverter(Converter<String, ?> converter) {
+ this.converter = (Converter<String, Object>) converter;
+ requestRepaint();
+ }
+
}
diff --git a/tests/server-side/com/vaadin/tests/data/bean/Person.java b/tests/server-side/com/vaadin/tests/data/bean/Person.java
index 2cb3a29368..f7bad31d0e 100644
--- a/tests/server-side/com/vaadin/tests/data/bean/Person.java
+++ b/tests/server-side/com/vaadin/tests/data/bean/Person.java
@@ -130,4 +130,14 @@ public class Person {
this.birthDate = birthDate;
}
+ public static Person createTestPerson1() {
+ return new Person("Foo", "Bar", "yeah@cool.com", 46, Sex.MALE,
+ new Address("Street", 1123, "Turku", Country.FINLAND));
+ }
+
+ public static Person createTestPerson2() {
+ return new Person("Maya", "Dinkelstein", "maya@foo.bar", 18,
+ Sex.FEMALE, new Address("Red street", 12, "Amsterdam",
+ Country.NETHERLANDS));
+ }
}
diff --git a/tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java b/tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java
new file mode 100644
index 0000000000..e79bd84741
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java
@@ -0,0 +1,59 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.server.component.label;
+
+import junit.framework.TestCase;
+
+import com.vaadin.Application;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.MethodProperty;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.Label;
+
+public class LabelConverters extends TestCase {
+
+ public void testLabelSetDataSourceLaterOn() {
+ Person p = Person.createTestPerson1();
+ Label l = new Label("My label");
+ assertEquals("My label", l.getValue());
+ assertNull(l.getConverter());
+ l.setPropertyDataSource(new MethodProperty<String>(p, "firstName"));
+ assertEquals(p.getFirstName(), l.getValue());
+ p.setFirstName("123");
+ assertEquals("123", l.getValue());
+ }
+
+ public void testIntegerDataSource() {
+ Application.setCurrentApplication(new Application());
+ Label l = new Label("Foo");
+ Property ds = new MethodProperty<Integer>(Person.createTestPerson1(),
+ "age");
+ l.setPropertyDataSource(ds);
+ assertEquals(String.valueOf(Person.createTestPerson1().getAge()),
+ l.getValue());
+ }
+
+ public void testSetValueWithDataSource() {
+ try {
+ MethodProperty<String> property = new MethodProperty<String>(
+ Person.createTestPerson1(), "firstName");
+ Label l = new Label(property);
+ l.setValue("Foo");
+ fail("setValue should throw an exception when a data source is set");
+ } catch (Exception e) {
+ }
+
+ }
+
+ public void testLabelWithoutDataSource() {
+ Label l = new Label("My label");
+ assertEquals("My label", l.getValue());
+ assertNull(l.getConverter());
+ assertNull(l.getPropertyDataSource());
+ l.setValue("New value");
+ assertEquals("New value", l.getValue());
+ assertNull(l.getConverter());
+ assertNull(l.getPropertyDataSource());
+ }
+}