Affichage des articles dont le libellé est listproperty. Afficher tous les articles
Affichage des articles dont le libellé est listproperty. Afficher tous les articles

jeudi 28 novembre 2013

FXForm: two releases and a lot of new features

We have added a bunch of cool features to FXForm, let's have a look!

Get ready for JavaFX 8

FXForm is now ready for JavaFX 8. We have adopted the following versioning conventions:

  • FXForm 2.2.x for JavaFX 2.2 (latest version: 2.2.4)
  • FXForm 8.0.x for JavaFX 8.0 (latest version: 8.0.1)
The version 8.0 of FXForm comes with the support of new types: LocalDate and Color using the new DatePicker and ColorPicker controls.


Improved data validation

We have improved the data validation layer of FXForm by adding the support of class level constraint and a finer granularity in constraint handling.

Class level constraint validation

FXForm now support class level constraints. This can be used to specify cross-field constraints.
The class level constraint violations are reported in the form. See below an example with the validation of a repeat password field:


In this case, our bean was simply annotated with the @PasswordMatch annotation which is a custom constraint validating that both password fields are equals. See Creating custom constraints for more informations about this.

Strict constraint versus warning constraint


Sometimes you want a constraint to be strict, sometimes you want it to be just a warning. FXForms allows you to specify this in your constraint declaration by using the group attribute of the constraint. By default a constraint is considered as strict. If you want your constraint to be a warning, use the Warning group provided by FXForm: 


In this case the @Max constraint will be treated as a warning. The main difference between a warning and a strict constraint is that with a warning, the model value will be updated even if the user input violates the constraint, which is not the case for as strict constraint.
Elements in the form that violates a constraint get a different style class for strict constraints and warning, so that the user feedback can be different in both cases.


In this example, the element editor is red and its label is bold when a strict constraint is violated and the element editor is orange when a warning is violated.

Multiple bean source

You can now edit multiple beans in the same form using the MultipleSourceBean


All features work as for a simple bean, including filters (reorder, exclude,...) and custom factories.

@Adapter

A custom adapter can now be specified directly on a field using the @Adapter annotation. If specified, FXForm will use the adapter provided by the annotation to bind the field property with the view property. See customizing bindings in FXForm2 for more informations about adapters.

Better handling of bound and read-only properties

FXForm introduces a notion of "editable" on the Node (see FXFormNode) which indicates whether a Node manipulated by FXForm allows the user to provide input.

FXForm now automatically disables editable nodes when bound to a property that is already bound or that is read-only. If the node is not editable (for example a Label), then it remains enabled.

New NodeSkin

FXForm now provides a NodeSkin. This NodeSkin can be used if you want to be responsible for creating the view of your form. You can then give your Node to the NodeSkin and FXForm will lookup for the required nodes and bind them to your bean. The lookup is based on the node ids. See wiki to understand how FXForm does the mapping between bean fields and nodes.

If your view is implemented in FXML, you can still use the FXMLSkin.

ListProperty support

Certainly one of the most funny (and useful!) feature of the latest release. FXForm now creates a TableView for ListProperty fields. Columns are populated automatically by analyzing the generic type of the ListProperty and extracting fields. When you click on a row, a popup shows, with -guess what- an FXForm :) This popup allows the edition of the selected item.



This feature is pretty powerful, since you can now edit pretty much your whole tree of model objects using just an FXForm. We might also add a default support for SetProperty and MapProperty in the future.

You can find the full release notes here. Thanks to usander, peterbecker and pjean for their appreciated feedback on the project.

Have fun with FXForm :)

jeudi 20 juin 2013

ListProperty vs ObjectProperty



In the world of JavaFX, when you need to use an ObservableList with the Property pattern, you write the following :

ObjectProperty<ObservableList<T>>

To be notified when the list content is modified, you can register a ListChangeListener on the ObservableList referenced by the ObjectProperty using the getter.
You can also register a ChangeListener on the ObjectProperty to be notified when the instance of ObservableList referenced by the ObjectProperty is modified.

You will end up with something like that :




  • If you add an element or more, your ListChangeListener will be notified.
  • If you change your ObservableList instance, your ChangeListener will be called.
But if the ObservableList instance referenced by the ObjectProperty has changed, and you try to add some elements to the new list instance, you won't be notified. This is because your ListChangeListener  is still registered on the previous ObservableList instance. So in your ChangeListener you have to unregister your ListChangeListener from the old ObservableList instance and register it to the new one. It's a little bit boring to do each time...



A major issue we discovered, is that if you replace an empty ObservableList by an other empty ObservableList, the ChangeListener is not notified, as we can see on this unit test, so that you can't correctly re-register the ListChangeListener on the new instance:



Why ? cause the equals method implementation return true between the two ObservableList.

So as you see... using an ObservableList with the Property pattern, is not really cool.

This is a problem, isn't it ??



Oh Legolas wants to help us. So listen what he says:

Replace our ObjectProperty<ObservableList<T> by a ListProperty<T>. ListProperty implements both Property<ObservableList> and ObservableList and makes the whole wrapping really transparent for the developer, taking care of the previous ListChangeListener manipulation automatically !
With that, if you want to be notified when the content of the List is modified, you just need to register the ListChangeListener once.

Like that :






When you do this, adding an element will notify the listener, and changing the ObservableList instance will call the listener to. And if you add an element after changing the list instance, no problem! the listener will also be notified of the change in the new list instance. No need to register a new Listener on the new List, the ListProperty manages it for you !

This unit test show us the ListChangeListener is called 5 times, once on each change.



Now you are ready to replace your ObjectProperty<ObservableList> by ListProperty ! Have fun