Controls with Values [was Possible additions to JavaFX to facilitate forms and validations]

Richard Bair richard.bair at oracle.com
Mon Dec 12 10:32:36 PST 2011


On Dec 8, 2011, at 5:50 PM, Daniel Zwolenski wrote:

> Can't I just do:
> 
> PersonView {
>    WritableValue<String> getFirstNameField();
>    WritableValue<String> getLastNameField();
>    WritableValue<Gender> getGenderField();
> }
> 
> I should be able to do this today, and implement it trivially (the PersonViewImpl for getFirstNameField() would return textField.textProperty(), for example). I don't think it really adds an argument for HasValue itself, which still seems to be really only beneficial to tools and frameworks (which is still a good thing).
> 
> Yea, nice, although WritableValue isn't observable and doesn't support binding.

Doh! However if we had a Bindable interface (as Knut proposed on the Bidirectional binding thread) or just use Property instead of WritableValue, it would still work. The point being you don't need a HasValue for the PersonViewImpl interface to still decouple the view completely from the controller. Is that right? It still seems the primary benefit to a HasValue is in the framework code.

As I see it, right now we have two leading ideas to solving this:

	- HasValue: an interface with a valueProperty() (and maybe getValue() and setValue() methods). Every control which "has a value" will implement this interface to delegate the "value property" to an existing property. For example TextField would delegate "value" to the "text" property.

	- Bindable: an interface. Basically "Property" but with a different name. Indeed, you would have Bindable implement everything in Property, and then have Property inherit from both ReadOnlyProperty and Bindable.

The reasons I don't like HasValue:
	- We will for the first time define "aliased" properties in our API: the "value" property and the "text" property on TextField will be exactly the same property. This will complicate tooling (for example, Scene Builder) because it will either show both properties to the user who will wonder what the difference is, or it will only show one to the user and the user will be left wondering which they should use. Drat.
	- The "HasFoo" name is a new naming convention for JavaFX. Do we want to do this? It usually takes a pretty compelling argument to go down the road of a new naming convention (in fact, if we'd have just used "value" consistently everywhere: ListView.value instead of ListView.items, TextField.value instead of TextField.text, and so forth, then this would have been a much easier decision!)

The reasons I don't like Bindable:
	- Complicates the already complex property inheritance matrix. Plus, there are other bind methods (like bindBidirectional(Property<?> other, StringConverter sc)) that are on the specific property types rather than on the generic Property, and the generic Bindable couldn't use those. So it becomes less useful.

I'm not too terribly bothered by the conceptual difference (a control has a property vs. a control is bindable). I think both concepts are equally valid and useful and it is just a matter of preference one way or the other.

I wonder if there is some other solution to the problem? Could we instead use an annotation to indicate what property on a control is the "data model" for the control? Annotations are by far the easiest reflection API to use IMO, so it isn't unreasonable for tools to resort to annotations (in fact, toolability is one of the primary use cases for an annotation). So what about something like @ValueProperty in javafx.scene.control, and we can then apply it to whatever property on the control is to be considered the "value" of the control?

>  Also implementing it 'trivially' for a ChoiceBox is not quite true because of the whole selection model not being writable thing, but this is back to the ChoiceBox API debate, rather than the HasValue debate.

Right. 

> There is another problem though, with a ChoiceBox the "value" is supposed to be limited strictly to those items contained in the selection list. It isn't a ComboBox -- there is no possibility to add custom items. Yet when you add a "value" property to ChoiceBox, as the ChoiceBox author, you have to accept that sometimes people will set something that isn't in the list. SO basically to make ChoiceBox usable with binding, we have to give up the invariant that the selected item is always one of the items in the list. Unavoidable it seems.
> 
> I think the same argument on the value not being in the list applies to selectionModel.select(T), so whatever rules are being used there should carry over. 
> 
> Looks like Jonathan has already put something in place for the ComboBox free-type text issue. He's got a 'StringConverter' in there that maps the entered text to a 'value' (and there's a valueProperty already there for us). I haven't quite worked out what happens if the text doesn't map to a value but I'm guessing a null value in this case.
> 
>  * <p>Because a ComboBox can be {@link #editableProperty() editable}, and the
>  * default means of allowing user input is via a {@link TextField}, a 
>  * {@link #converterProperty() string converter} property is provided to allow
>  * for developers to specify how to translate a users string into an object of
>  * type T, such that the {@link #valueProperty() value} property may contain it.
>  * By default the converter simply returns the String input as the user typed it,
>  * which therefore assumes that the type of the editable ComboBox is String. If 
>  * a different type is specified and the ComboBox is to be editable, it is 
>  * necessary to specify a custom {@link StringConverter}.


I don't see an issue in JIRA about the ChoiceBox needing to support bidirectional binding -- is there one already I'm missing? I think we should break that out into a separate discussion from the HasValue proposal. I think we can discuss a solution and get a fix in for ChoiceBox independently. What do you think?

Thanks
Richard



More information about the openjfx-dev mailing list