diff options
Diffstat (limited to 'server/src/main')
-rw-r--r-- | server/src/main/java/com/vaadin/data/BeanBinder.java | 19 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/data/Binder.java | 121 | ||||
-rw-r--r-- | server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java | 11 |
3 files changed, 130 insertions, 21 deletions
diff --git a/server/src/main/java/com/vaadin/data/BeanBinder.java b/server/src/main/java/com/vaadin/data/BeanBinder.java index dd5790b8b6..64436c26a8 100644 --- a/server/src/main/java/com/vaadin/data/BeanBinder.java +++ b/server/src/main/java/com/vaadin/data/BeanBinder.java @@ -20,7 +20,6 @@ import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Locale; import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; @@ -28,8 +27,6 @@ import java.util.function.Predicate; import com.vaadin.data.util.BeanUtil; import com.vaadin.data.util.converter.Converter; import com.vaadin.data.validator.BeanValidator; -import com.vaadin.ui.Component; -import com.vaadin.ui.UI; /** * A {@code Binder} subclass specialized for binding <em>beans</em>: classes @@ -177,7 +174,7 @@ public class BeanBinder<BEAN> extends Binder<BEAN> { if (BeanValidator.checkBeanValidationAvailable()) { finalBinding = finalBinding.withValidator(new BeanValidator( - getBinder().beanType, propertyName, getLocale())); + getBinder().beanType, propertyName, findLocale())); } PropertyDescriptor descriptor = getDescriptor(propertyName); @@ -242,20 +239,6 @@ public class BeanBinder<BEAN> extends Binder<BEAN> { throw new RuntimeException(exception); }); } - - private Locale getLocale() { - Locale l = null; - if (getField() instanceof Component) { - l = ((Component) getField()).getLocale(); - } - if (l == null && UI.getCurrent() != null) { - l = UI.getCurrent().getLocale(); - } - if (l == null) { - l = Locale.getDefault(); - } - return l; - } } private final Class<? extends BEAN> beanType; diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java index 0a7e33c556..88549e12c3 100644 --- a/server/src/main/java/com/vaadin/data/Binder.java +++ b/server/src/main/java/com/vaadin/data/Binder.java @@ -38,7 +38,10 @@ import com.vaadin.server.ErrorMessage; import com.vaadin.server.UserError; import com.vaadin.shared.Registration; import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.AbstractSingleSelect; +import com.vaadin.ui.Component; import com.vaadin.ui.Label; +import com.vaadin.ui.UI; /** * Connects one or more {@code Field} components to properties of a backing data @@ -497,6 +500,25 @@ public class Binder<BEAN> implements Serializable { } } + /** + * Finds an appropriate locale to be used in conversion and validation. + * + * @return the found locale, not null + */ + protected Locale findLocale() { + Locale l = null; + if (getField() instanceof Component) { + l = ((Component) getField()).getLocale(); + } + if (l == null && UI.getCurrent() != null) { + l = UI.getCurrent().getLocale(); + } + if (l == null) { + l = Locale.getDefault(); + } + return l; + } + private void bind(BEAN bean) { setFieldValue(bean); onValueChange = getField() @@ -521,7 +543,7 @@ public class Binder<BEAN> implements Serializable { private ValidationStatus<TARGET> doValidation() { FIELDVALUE fieldValue = field.getValue(); Result<TARGET> dataValue = converterValidatorChain.convertToModel( - fieldValue, ((AbstractComponent) field).getLocale()); + fieldValue, findLocale()); return new ValidationStatus<>(this, dataValue); } @@ -543,8 +565,7 @@ public class Binder<BEAN> implements Serializable { private FIELDVALUE convertDataToFieldType(BEAN bean) { return converterValidatorChain.convertToPresentation( - getter.apply(bean), - ((AbstractComponent) getField()).getLocale()); + getter.apply(bean), findLocale()); } /** @@ -673,6 +694,8 @@ public class Binder<BEAN> implements Serializable { * @param field * the field to be bound, not null * @return the new binding + * + * @see #bind(HasValue, Function, BiConsumer) */ public <FIELDVALUE> Binding<BEAN, FIELDVALUE, FIELDVALUE> forField( HasValue<FIELDVALUE> field) { @@ -686,6 +709,45 @@ public class Binder<BEAN> implements Serializable { } /** + * Creates a new binding for the given single select component. The returned + * binding may be further configured before invoking + * {@link Binding#bind(Function, BiConsumer) Binding.bind} which completes + * the binding. Until {@code Binding.bind} is called, the binding has no + * effect. + * + * @param <SELECTVALUE> + * the item type of the select + * @param select + * the select to be bound, not null + * @return the new binding + * + * @see #bind(AbstractSingleSelect, Function, BiConsumer) + */ + public <SELECTVALUE> Binding<BEAN, SELECTVALUE, SELECTVALUE> forSelect( + AbstractSingleSelect<SELECTVALUE> select) { + return forField(new HasValue<SELECTVALUE>() { + + @Override + public void setValue(SELECTVALUE value) { + select.setSelectedItem(value); + } + + @Override + public SELECTVALUE getValue() { + return select.getSelectedItem().orElse(null); + } + + @Override + public Registration addValueChangeListener( + ValueChangeListener<? super SELECTVALUE> listener) { + return select.addSelectionListener(e -> listener.accept( + new ValueChange<>(select, getValue(), e + .isUserOriginated()))); + } + }); + } + + /** * Binds a field to a bean property represented by the given getter and * setter pair. The functions are used to update the field value from the * property and to store the field value to the property, respectively. @@ -735,6 +797,59 @@ public class Binder<BEAN> implements Serializable { } /** + * Binds a single select to a bean property represented by the given getter + * and setter pair. The functions are used to update the selection from the + * property and to store the selection to the property, respectively. + * <p> + * Use the {@link #forSelect(AbstractSingleSelect)} method instead if you + * want to further configure the new binding. + * <p> + * When a bean is bound with {@link Binder#bind(BEAN)}, the selected item is + * set to the return value of the given getter. The property value is then + * updated via the given setter whenever the selected item changes. The + * setter may be null; in that case the property value is never updated and + * the binding is said to be <i>read-only</i>. A null property value + * corresponds to no selection and vice versa. + * <p> + * If the Binder is already bound to some item, the newly bound select is + * associated with the corresponding bean property as described above. + * <p> + * The getter and setter can be arbitrary functions, for instance + * implementing user-defined conversion or validation. However, in the most + * basic use case you can simply pass a pair of method references to this + * method as follows: + * + * <pre> + * class Person { + * public enum Title { MR, MS, MISS, MRS, DR, PROF }; + * + * public Title getTitle() { ... } + * public void setTitle(Title title) { ... } + * } + * + * NativeSelect<Title> titleSelect = new NativeSelect<>(); + * titleSelect.setItems(Title.values()); + * binder.bind(titleSelect, Person::getTitle, Person::setTitle); + * </pre> + * + * @param <SELECTVALUE> + * the item type of the select + * @param select + * the select to bind, not null + * @param getter + * the function to get the value of the property to the + * selection, not null + * @param setter + * the function to save the selection to the property or null if + * read-only + */ + public <SELECTVALUE> void bind(AbstractSingleSelect<SELECTVALUE> select, + Function<BEAN, SELECTVALUE> getter, + BiConsumer<BEAN, SELECTVALUE> setter) { + forSelect(select).bind(getter, setter); + } + + /** * Binds the given bean to all the fields added to this Binder. To remove * the binding, call {@link #unbind()}. * <p> diff --git a/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java b/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java index 823650f443..81c22cffda 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java +++ b/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java @@ -254,6 +254,17 @@ public abstract class AbstractSingleSelect<T> extends return getSelectionModel().getSelectedItem(); } + /** + * Sets the current selection to the given item or clears selection if given + * {@code null}. + * + * @param item + * the item to select or {@code null} to clear selection + */ + public void setSelectedItem(T item) { + getSelectionModel().setSelectedItem(item); + } + @Override protected AbstractSingleSelectState getState() { return (AbstractSingleSelectState) super.getState(); |