B - the bean typepublic class BeanPathAdapter<B>
extends java.lang.Object
. separated field path to be traversed on a bean until
the final field name is found (last entry in the .
separated field path). Each field will have a corresponding <code>Property</code>
that is automatically generated and reused in the binding process. Each
<code>Property</code> is bean-aware and will dynamically update it's values and
bindings as different beans are set on the adapter. Bean's set on the adapter
do not need to instantiate all the sub-beans in the path(s) provided as long
as they contain a no-argument constructor they will be instantiated as
path(s) are traversed.
// Assuming "age" is a double field in person we can bind it to a
// Slider#valueProperty() of type double, but we can also bind it
// to a TextField#valueProperty() of type String.
Person person = new Person();
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
Slider sl = new Slider();
TextField tf = new TextField();
personPA.bindBidirectional("age", sl.valueProperty());
personPA.bindBidirectional("age", tf.valueProperty());
// Binding a bean (Person) field called "address" that contains another
// bean (Address) that also contains a field called "location" with a
// bean (Location) field of "state" (the chain can be virtually endless
// with all beans being instantiated along the way when null).
Person person = new Person();
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
TextField tf = new TextField();
personPA.bindBidirectional("address.location.state", tf.valueProperty());
// Assuming "address" is an "Address" field in a "Person" class we can bind it
// to a ComboBox#valueProperty() of the same type. The "Address" class should
// override the "toString()" method in order to show a meaningful selection
// value in the example ComboBox.
Address a1 = new Address();
Address a2 = new Address();
a1.setStreet("1st Street");
a2.setStreet("2nd Street");
ComboBox<Address> cb = new ComboBox<>();
cb.getItems().addAll(a1, a2);
Person person = new Person();
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
personPA.bindBidirectional("address", cb.valueProperty(), Address.class);
// Assuming "allLanguages" is a collection/map field in person we can
// bind it to a JavaFX observable collection/map
Person person = new Person();
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
ListView<String> lv = new ListView<>();
personPA.bindContentBidirectional("allLanguages", null, String.class,
lv.getItems(), String.class, null, null);
// Assuming "languages" is a collection/map field in person we can
// bind it to a JavaFX observable collection/map selections
Person person = new Person();
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
ListView<String> lv = new ListView<>();
personPA.bindContentBidirectional("languages", null, String.class, lv
.getSelectionModel().getSelectedItems(), String.class, lv
.getSelectionModel(), null);
// Assuming "languages" and "allLanguages" are a collection/map
// fields in person we can bind "languages" to selections made from
// the items in "allLanguages" to a JavaFX observable collection/map
// selection Person person = new Person();
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
ListView<String> lv = new ListView<>();
personPA.bindContentBidirectional("languages", null, String.class, lv
.getSelectionModel().getSelectedItems(), String.class, lv
.getSelectionModel(), "allLanguages");
// Assuming "hobbies" and "allHobbies" are a collection/map // fields in person and each element within them contain an // instance of Hobby that has it's own field called "name" // we can bind "allHobbies" and "hobbies" to the Hobby "name"s // for each Hobby in the items/selections (respectively) to/from // a ListView wich will only contain the String name of each Hobby // as it's items and selections Person person = new Person(); BeanPathAdapterpersonPA = new BeanPathAdapter<>(person); ListView lv = new ListView<>(); // bind items personPA.bindContentBidirectional("allHobbies", "name", Hobby.class, lv.getItems(), String.class, null, null); // bind selections that reference the same instances within the items personPA.bindContentBidirectional("languages", "name", Hobby.class, lv.getSelectionModel().getSelectedItems(), String.class, lv.getSelectionModel(), "allHobbiess");
Person person = new Person();
Hobby hobby1 = new Hobby();
hobby1.setName("Hobby 1");
Hobby hobby2 = new Hobby();
hobby2.setName("Hobby 2");
person.setAllHobbies(new LinkedHashSet<Hobby>());
person.getAllHobbies().add(hobby1);
person.getAllHobbies().add(hobby2);
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
ListView<String> lv = new ListView<>();
personPA.bindContentBidirectional("allHobbies", "name", Hobby.class,
lv.getItems(), String.class, null, null);
ListView<String> lv2 = new ListView<>();
personPA.bindContentBidirectional("allHobbies", "name", Hobby.class,
lv2.getItems(), String.class, null, null);
// When the bean collection/map field is empty/null and it is
// bound to a non-empty observable collection/map, the values
// of the observable are used to instantiate each item bean
// and set the item value (Hobby#setName in this case)
Person person = new Person();
final ObservableList<String> oc = FXCollections.observableArrayList("Hobby 1",
"Hobby 2", "Hobby 3");
BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
ListView<String> lv = new ListView<>(oc);
personPA.bindContentBidirectional("allHobbies", "name", Hobby.class,
lv.getItems(), String.class, null, null);
ListView<String> lv2 = new ListView<>(); // <-- notice that oc is not passed
personPA.bindContentBidirectional("allHobbies", "name", Hobby.class,
lv2.getItems(), String.class, null, null);
// Assuming "age" is a double field in person...
final Person person1 = new Person();
person1.setAge(1D);
final Person person2 = new Person();
person2.setAge(2D);
final BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person1);
TextField tf = new TextField();
personPA.bindBidirectional("age", tf.valueProperty());
Button btn = new Button("Toggle People");
btn.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
// all bindings will show relevant person data and changes made
// to the bound controls will be reflected in the bean that is
// set at the time of the change
personPA.setBean(personPA.getBean() == person1 ? person2 : person1);
}
});
// Assuming "dob" is a java.util.Date or java.util.Calendar field
// in person it can be bound to a java.util.Date or
// java.util.Calendar JavaFX control property. Example uses a
// jfxtras.labs.scene.control.CalendarPicker
final Person person = new Person();
final BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
CalendarPicker calendarPicker = new CalendarPicker();
personPA.bindBidirectional("dob", calendarPicker.calendarProperty(),
Calendar.class);
// Assuming "name"/"description" are a java.lang.String fields in Hobby
// and "hobbies" is a List/Set/Map in Person
final Person person = new Person();
final BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
TableView<Hobby> table = new TableView<>();
TableColumn<Hobby, String> nameCol = new TableColumn<>("Hobby Name");
nameCol.setMinWidth(100);
nameCol.setCellValueFactory(new PropertyValueFactory<Hobby, String>("name"));
TableColumn<Hobby, String> descCol = new TableColumn<>("Hobby Desc");
descCol.setMinWidth(100);
descCol.setCellValueFactory(new PropertyValueFactory<Hobby, String>(
"description"));
table.getColumns().addAll(nameCol, descCol);
personPA.bindContentBidirectional("hobbies", null, String.class,
table.getItems(), Hobby.class, null, null);
final BeanPathAdapter<Person> personPA = new BeanPathAdapter<>(person);
// use the following to eliminate unwanted notifications
// personPA.removeFieldPathValueTypes(FieldPathValueType.BEAN_CHANGE, ...)
personPA.fieldPathValueProperty().addListener(
new ChangeListener<FieldPathValue>() {
@Override
public void changed(
final ObservableValue<? extends FieldPathValue> observable,
final FieldPathValue oldValue, final FieldPathValue newValue) {
System.out.println("Value changed from: " + oldValue + " to: "
+ newValue);
}
});
bindBidirectional(String, Property),
bindContentBidirectional(String, String, Class, ObservableList, Class,
SelectionModel, String),
bindContentBidirectional(String, String, Class, ObservableSet, Class,
SelectionModel, String),
bindContentBidirectional(String, String, Class, ObservableMap, Class,
SelectionModel, String)| Type | Property and Description |
|---|---|
javafx.beans.property.ReadOnlyObjectProperty<BeanPathAdapter.FieldPathValue> |
fieldPathValue |
| Modifier and Type | Class and Description |
|---|---|
protected static class |
BeanPathAdapter.FieldBean<PT,BT>
A POJO bean extension that allows binding based upon a
. |
static class |
BeanPathAdapter.FieldBeanOperation
BeanPathAdapter.FieldBean operations |
protected static class |
BeanPathAdapter.FieldHandle<T,F>
Field handle to
BeanPathAdapter.FieldHandle.getAccessor() and
BeanPathAdapter.FieldHandle.getSetter() for a given
BeanPathAdapter.FieldHandle.getTarget(). |
static class |
BeanPathAdapter.FieldPathValue
|
static class |
BeanPathAdapter.FieldPathValueType
BeanPathAdapter.FieldPathValue types used for FieldPathValueProperty
changes |
static class |
BeanPathAdapter.FieldProperty<BT,T,PT>
A <code>Property</code> extension that uses a bean's getter/setter to define
the <code>Property</code>'s value.
|
protected static class |
BeanPathAdapter.FieldStringConverter<T>
Coercible <code>StringConverter</code> that handles conversions between
strings and a target class when used in the binding process
Bindings.bindBidirectional(Property, Property, StringConverter) |
| Modifier and Type | Field and Description |
|---|---|
static char |
COLLECTION_ITEM_PATH_SEPARATOR |
static char |
PATH_SEPARATOR |
| Constructor and Description |
|---|
BeanPathAdapter(B bean)
Constructor
|
| Modifier and Type | Method and Description |
|---|---|
void |
addFieldPathValueTypes(BeanPathAdapter.FieldPathValueType... types)
Adds
BeanPathAdapter.FieldPathValueType(s) BeanPathAdapter.FieldPathValueType(s) that
#notifyProperty() will use |
void |
bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.BooleanProperty property) |
void |
bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.Property<java.lang.Number> property) |
<T> void |
bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.Property<T> property,
java.lang.Class<T> propertyType)
Binds a <code>Property</code> by traversing the bean's field tree
|
void |
bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.StringProperty property) |
<E> void |
bindContentBidirectional(java.lang.String fieldPath,
java.lang.String itemFieldPath,
java.lang.Class<?> itemFieldPathType,
javafx.collections.ObservableList<E> list,
java.lang.Class<E> listValueType,
javafx.scene.control.SelectionModel<E> selectionModel,
java.lang.String selectionModelItemMasterPath)
Binds a <code>ObservableList</code> by traversing the bean's field tree.
|
<K,V> void |
bindContentBidirectional(java.lang.String fieldPath,
java.lang.String itemFieldPath,
java.lang.Class<?> itemFieldPathType,
javafx.collections.ObservableMap<K,V> map,
java.lang.Class<V> mapValueType,
javafx.scene.control.SelectionModel<V> selectionModel,
java.lang.String selectionModelItemMasterPath)
Binds a <code>ObservableMap</code> by traversing the bean's field tree.
|
<E> void |
bindContentBidirectional(java.lang.String fieldPath,
java.lang.String itemFieldPath,
java.lang.Class<?> itemFieldPathType,
javafx.collections.ObservableSet<E> set,
java.lang.Class<E> setValueType,
javafx.scene.control.SelectionModel<E> selectionModel,
java.lang.String selectionModelItemMasterPath)
Binds a <code>ObservableSet</code> by traversing the bean's field tree.
|
javafx.beans.property.ReadOnlyObjectProperty<BeanPathAdapter.FieldPathValue> |
fieldPathValueProperty() |
B |
getBean() |
protected BeanPathAdapter.FieldBean<java.lang.Void,B> |
getRoot() |
boolean |
hasFieldPathValueTypes(BeanPathAdapter.FieldPathValueType... types)
Determines if the
BeanPathAdapter.FieldPathValueType(s) are being used by the
#notifyProperty() |
protected static <T> java.lang.Class<T> |
propertyValueClass(javafx.beans.property.Property<T> property)
Provides the underlying value class for a given <code>Property</code>
|
void |
removeFieldPathValueTypes(BeanPathAdapter.FieldPathValueType... types)
Removes
BeanPathAdapter.FieldPathValueType(s) BeanPathAdapter.FieldPathValueType(s) that
#notifyProperty() will use |
void |
setBean(B bean)
Sets the root bean of the
BeanPathAdapter. |
<T> void |
unBindBidirectional(java.lang.String fieldPath,
javafx.beans.property.Property<T> property)
Unbinds a <code>Property</code> by traversing the bean's field tree
|
public final javafx.beans.property.ReadOnlyObjectProperty<BeanPathAdapter.FieldPathValue> fieldPathValueProperty
public static final char PATH_SEPARATOR
public static final char COLLECTION_ITEM_PATH_SEPARATOR
public BeanPathAdapter(B bean)
bean - the bean the BeanPathAdapter is forpublic void bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.BooleanProperty property)
public void bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.StringProperty property)
public void bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.Property<java.lang.Number> property)
public <E> void bindContentBidirectional(java.lang.String fieldPath,
java.lang.String itemFieldPath,
java.lang.Class<?> itemFieldPathType,
javafx.collections.ObservableList<E> list,
java.lang.Class<E> listValueType,
javafx.scene.control.SelectionModel<E> selectionModel,
java.lang.String selectionModelItemMasterPath)
phoneNumbers (relative to the getBean()) where
phoneNumbers is a <code>Collection</code> that contains
PhoneNumber instances which in turn have a field called
areaCode then an item path can be passed in addition to the
field path with areaCode as it's value.fieldPath - the . separated field paths relative to
the getBean() that will be traverseditemFieldPath - the . separated field paths relative to
each item in the bean's underlying <code>Collection</code> that
will be traversed (empty/null when each item value does not
need traversed)itemFieldPathType - the <code>Class</code> of that the item path points tolist - the <code>ObservableList</code> to bind to the field class type of
the propertylistValueType - the class type of the <code>ObservableList</code> valueselectionModel - the <code>SelectionModel</code> used to set the values within the
<code>ObservableList</code> only applicable when the
<code>ObservableList</code> is used for selection(s) and therefore
cannot be updated directly because it is read-onlyselectionModelItemMasterPath - when binding to <code>SelectionModel</code> items, this will be the
optional path to the collection field that contains all the
items to select frompublic <E> void bindContentBidirectional(java.lang.String fieldPath,
java.lang.String itemFieldPath,
java.lang.Class<?> itemFieldPathType,
javafx.collections.ObservableSet<E> set,
java.lang.Class<E> setValueType,
javafx.scene.control.SelectionModel<E> selectionModel,
java.lang.String selectionModelItemMasterPath)
phoneNumbers (relative to the getBean()) where
phoneNumbers is a <code>Collection</code> that contains
PhoneNumber instances which in turn have a field called
areaCode then an item path can be passed in addition to the
field path with areaCode as it's value.fieldPath - the . separated field paths relative to
the getBean() that will be traverseditemFieldPath - the . separated field paths relative to
each item in the bean's underlying <code>Collection</code> that
will be traversed (empty/null when each item value does not
need traversed)itemFieldPathType - the <code>Class</code> of that the item path points toset - the <code>ObservableSet</code> to bind to the field class type of
the propertysetValueType - the class type of the <code>ObservableSet</code> valueselectionModel - the <code>SelectionModel</code> used to set the values within the
<code>ObservableSet</code> only applicable when the
<code>ObservableSet</code> is used for selection(s) and therefore
cannot be updated directly because it is read-onlyselectionModelItemMasterPath - when binding to <code>SelectionModel</code> items, this will be the
optional path to the collection field that contains all the
items to select frompublic <K,V> void bindContentBidirectional(java.lang.String fieldPath,
java.lang.String itemFieldPath,
java.lang.Class<?> itemFieldPathType,
javafx.collections.ObservableMap<K,V> map,
java.lang.Class<V> mapValueType,
javafx.scene.control.SelectionModel<V> selectionModel,
java.lang.String selectionModelItemMasterPath)
phoneNumbers (relative to the getBean()) where
phoneNumbers is a <code>Collection</code> that contains
PhoneNumber instances which in turn have a field called
areaCode then an item path can be passed in addition to the
field path with areaCode as it's value.fieldPath - the . separated field paths relative to
the getBean() that will be traverseditemFieldPath - the . separated field paths relative to
each item in the bean's underlying <code>Collection</code> that
will be traversed (empty/null when each item value does not
need traversed)itemFieldPathType - the <code>Class</code> of that the item path points tomap - the <code>ObservableMap</code> to bind to the field class type of
the propertymapValueType - the class type of the <code>ObservableMap</code> valueselectionModel - the <code>SelectionModel</code> used to set the values within the
<code>ObservableMap</code> only applicable when the
<code>ObservableMap</code> is used for selection(s) and therefore
cannot be updated directly because it is read-onlyselectionModelItemMasterPath - when binding to <code>SelectionModel</code> items, this will be the
optional path to the collection field that contains all the
items to select frompublic <T> void bindBidirectional(java.lang.String fieldPath,
javafx.beans.property.Property<T> property,
java.lang.Class<T> propertyType)
fieldPath - the . separated field paths relative to
the getBean() that will be traversedproperty - the <code>Property</code> to bind to the field class type of the
propertypropertyType - the class type of the <code>Property</code> valuepublic <T> void unBindBidirectional(java.lang.String fieldPath,
javafx.beans.property.Property<T> property)
fieldPath - the . separated field paths relative to
the getBean() that will be traversedproperty - the <code>Property</code> to bind to the field class type of the
propertypublic B getBean()
BeanPathAdapterpublic void setBean(B bean)
BeanPathAdapter. Any existing
properties will be updated with the values relative to the paths within
the bean.bean - the bean to setprotected final BeanPathAdapter.FieldBean<java.lang.Void,B> getRoot()
BeanPathAdapter.FieldBeanpublic final javafx.beans.property.ReadOnlyObjectProperty<BeanPathAdapter.FieldPathValue> fieldPathValueProperty()
protected static <T> java.lang.Class<T> propertyValueClass(javafx.beans.property.Property<T> property)
property - the <code>Property</code> to checkpublic void addFieldPathValueTypes(BeanPathAdapter.FieldPathValueType... types)
BeanPathAdapter.FieldPathValueType(s) BeanPathAdapter.FieldPathValueType(s) that
#notifyProperty() will usetypes - the BeanPathAdapter.FieldPathValueType to addpublic void removeFieldPathValueTypes(BeanPathAdapter.FieldPathValueType... types)
BeanPathAdapter.FieldPathValueType(s) BeanPathAdapter.FieldPathValueType(s) that
#notifyProperty() will usetypes - the BeanPathAdapter.FieldPathValueType(s) to removepublic boolean hasFieldPathValueTypes(BeanPathAdapter.FieldPathValueType... types)
BeanPathAdapter.FieldPathValueType(s) are being used by the
#notifyProperty()types - the BeanPathAdapter.FieldPathValueType(s) to check forBeanPathAdapter.FieldPathValueType(s) exist