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

Daniel Zwolenski zonski at googlemail.com
Thu Dec 8 14:27:46 PST 2011


It seems I hit reply instead of reply-all on this email earlier - sorry
about that. Embedded below is an email from myself (the most indented one),
which was then replied-to by Richard (the less indented one) and my latest
comments (the not indented one).

*(Dan said)* After googling the definition of 'recapitulate' (turns out it
> doesn't mean to give up twice), here is a summary:
>
>
> *(Richard said)*
>

>
Hehehe :-). After I typed it I rechecked the definition just to make sure I
> had the right word. It does sound like giving up twice, I hadn't recognized
> that before :-)
>
> *What*:
>
> Add a way to consistently access the primary 'value' of Controls where
> such a value can be identified. The 'value' is whatever attribute of that
> Control a developer would most consider it's defining data attribute (e.g.
> text for TextField, selected for CheckBox).
>
> *Why:*
>
>    1. *Detect value changes*: a consistent valueProperty will make it
>    significantly easier to observe Controls and watch for changes made by the
>    user. This is particularly useful for creating 'forms', allowing the
>    developer to detect when a form has 'dirty' data and needs to be saved
>    (e.g. attempting to close the window shows a prompt "Save changes?") and
>    also to auto-validate a form field when it is changed and provide the user
>    with some visual feedback (e.g. a red 'X' or border highlight).
>
>    2. *Facilitate cleaner binding*: a consistent valueProperty will allow
>    for simpler, more intuitive binding between Controls and model properties
>    (e.g. a PresentationModel). For example, to bind a ChoiceBox currently the
>    developer must bind to
>     choiceBox.getSelectionModel().selectedItemProperty(), whereas the proposal
>    will allow for choiceBox.valueProperty(). This is more intuitive but also
>    removes the problem of watching for changes in the actual selectionModel
>    itself (the choiceBox.valueProperty will do this internally). Additionally
>    a consistent API will also allow for easier development of generic,
>    reflection based field binding tools (e.g. automagically bind all fields on
>    a PresentationModel to the correspondingly named Controls on the view).
>
>    3. *Facilitate bidirectional binding*: several Controls (in particular
>    those with a SelectionModel) provide only read-only access to their 'value'
>    fields and instead have additional methods for changing the value (such as
>    select(value) and clearSelection()) . The proposed valueProperty should be
>    able to hide this from the developer (i.e. the internal implementation can
>    map to the appropriate selection model call), providing a simple read-write
>    property with full binding support. This is of particular usefulness for
>    FXML where mapping to the relevant method call would be very messy.
>
> I think the benefit in having a HasValue is that it allows frameworks to
> work with controls in a generic manner. I'm not sure it actually adds
> benefit to developers directly. So for example, the fact that
> TextField.text is used in one place and Slider.value in another I don't
> think causes confusion for developers, but it does cause confusion for
> automated tools. So I probably would have worded the argument such that
> having tools that can deal with controls in an abstract manner is important
> because it enables the following use cases (a "form" framework which
> manages blah, or whatnot). So for example each of the argument lead ins
> ("Detect value changes", "Facilitate cleaner binding", "Facilitate
> bidirectional binding") don't require HasValue -- they are satisfied with
> the current design. Not trying to nitpick, just refine the argument so it
> is clear exactly what we're going after here. From a gut sense it seems
> there is something valuable (ha ha) in the proposal, but I'm trying to work
> it down to the essence.
>

> The argument in #2 I think is not very strong because HasValue isn't
> required to fix this. That is, we can add a "value" property to ChoiceBox
> without having a HasValue interface, so it doesn't address the question
> "why is HasValue important?".
>

True. The only thing that is arguably 'more intuitive' is the ChoiceBox,
where the concept of a 'value' is added. This could definitely be done by
looking at the ChoiceBox/ComboBox in isolation.

So generally, yes, the proposal of a generic HasValue thing is of most
benefit to framework development that wants to access fields in a generic
way.

There is a style of MVP design pattern however where this generic HasValue
would be of benefit to the developer. I could create an interface for my
view like so:

PersonView
{
    HasValue<String> getFirstNameField();
    HasValue<String> getLastNameField();
    HasValue<Gender> getGenderField();
}


And then my Presenter can interact with it in a
view-implementation-agnostic way (i.e. just set the values as needed). If
the view chooses to implement the HasValue<Gender> with a ComboBox a
ChoiceBox or some custom built HasValue implementing control, then the
controller doesn't change. Very nice view/presenter separation.

Of course this pattern has developed in the absence of observable
properties and both aim to solve similar problems. It's not yet clear (to
me anyway) whether this 'View interface' pattern is superseeded by JFX
properties. To a certain extent, FXML doesn't facilitate the above pattern
(it could but would need some changes) so there will be a natural lean away
from it and towards observable presentation model style patterns.

#3 is very interesting because I would have said that the "value" of a
> ListView is the "items" list, not the selection. This is another reason I
> am trying to refine the arguments, because I think there is something
> interesting in that your proposal was that the "value" was the selected
> item whereas my assumption was that it was the data model.
>

Good point. The problem comes back to the ChoiceBox (and ComboBox) I think.
The 'selection' in a ChoiceBox is very different conceptually to the
selection in a TreeView or TableView. I think my comments/arguments make
most sense in the context of ChoiceBox/ComboBox (which, thinking back was
what I first started with, and then List/Table/Tree were organic, and
perhaps wrong, extensions of that thought process). Further thoughts on
this would be good - perhaps List/Tree/Table shouldn't implement HasValue
at all.


>
> That is, I'm thinking of the "value" as the data model object added to a
> control. But the selectedItem is something else entirely. Why do you think
> this is? It seems what you might think of as the "value" depends on
> context. It seems maybe we should divide the world in "value" controls and
> "multi-value" controls (as you first did with HasValue vs. HasValues). But
> the difference would be that the multi-value control is one where it has a
> value (an ObservableList<T> or TreeItem<T> or something) and also some
> selection. And then you have some generic way to interact with both the
> concept of value and selection on such controls.
>
>
>
> And then each Control would implement this interface to map to their
> relevant Control specific property as follows:
>
>    - Accordian => (n/a)
>    - ChoiceBox => selectionModel.selectedItemProperty
>    - HTMLEditor => (n/a - htmlText is not a property?)
>
> Oh crap, that was an oversight! Do you want to file an RFE? Yikes!
>

http://javafx-jira.kenai.com/browse/RT-18436


>
> *Outstanding Issues: *
>
>    - *Naming*: the HasValue name makes a lot of sense to me, but Richard
>    has raised some concerns. I think this is just a question of what you are
>    used to. Anyone using Google frameworks will find the HasX (and IsX) naming
>    convention very familiar (for example just found this:
>    http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/client/ui/HasValue.java?r=4202).
>    I thought Spring and other frameworks used similar stuff but I can't find
>    any examples so perhaps I imagined this (there is a HasGetTransferHandler
>    buried in Swing's DnD and AspectJ has some HasX classes). The floor is open
>    on this one: HasValue, Valuable, ValueProvider, ValueSource, ValueOwner,
>    HasValueProperty, ValueThingThatWeCouldntThinkOfAGoodNameFor?
>
> What else, other than controls, would implement this proposed interface?
> That is, is it really HasValue, or is it SingleValuedControl,
> MultiValuedControl? This gets back to the need to tighten up the use cases
> and arguments. Is the goal to make UI Controls more uniform for tools, or
> is there a larger goal? For example, what happens if I have a layout
> container that implements this interface. Is there some good reason why I
> might want to do that?
>

Well, there's a possible example below with 'ToggleGroup'.

Another possibility that is in the back of my mind but I'm not sure if it
will work cleanly is a 'form' itself. In this case you would have a whole
lot of HasValue fields binding to a bean, which in turn is exposed as the
HasValue of the entire form (which is probably extending one of the Panes
or MigPane).

Also, if the 'View interface' outlined above is used then creating Mock
objects is a definite possibility for testing. i.e. I don't need to create
a real TextField for testing my controller/presenter, I can just create a
mock HasValue and fire different things at it (like invalid text for
testing validation). Frameworks like Spring (and following on Guice and
GWT) have made interfaces-for-everything fairly popular with the general
"it's better for testing" argument as the default and other arguments (such
as multiple-inheritance, aspect injection, etc) just as a bonus.


>
>    - *Toggle/RadioButton and ToggleGroup*: a new issue that has come out
>    of putting the above list together is the binding for toggle button groups.
>    Ideally we would be able to bind to this in much the same way we bind to a
>    ChoiceBox, where the value is the 'item' of the selected button. The toggle
>    group doesn't have the idea of items in it however. Perhaps it should.
>    Thoughts on this?
>
> A good thing to think on. I think most people would agree that from a
> data-representation perspective, a ToggleGroup of RadioButtons is
> essentially just a variation on a ChoiceBox. Having some similarity there
> would be nice.
>

Agreed.


>
> Another thing I wanted to mention was why SelectionModel doesn't allow you
> to bind. The basic issue is that, with binding, all bets are off. If you
> bind a property to something (unidirectionally), then it is off limits to
> the Skin (an attempt to set a property that is unidirectionally bound
> results in an exception). We tried to avoid any API where exposing
> something as a full property would compromise the usability of the control.
> So for example, Button has an "armed" read only property with "arm()" and
> "disarm()" methods. They don't do anything other than set the armed state.
> Why wasn't this just made a mutable property? Because doing so would mean
> somebody could bind armed unidirectionally and then the Button would no
> longer look or act right. Avoiding inconsistent states made the controls
> code a lot easier and more bullet-proof.
>
> I don't remember but I suspect that is another reason why SelectionModel
> is as it is. If we provided a "value" property that mapped to the
> selectedItem, then somebody could bind the value property unidirectionally,
> and any attempt to change selection on the SelectionModel would be broken.
> Is that really what we want? What is the use case for binding
> (unidirectionally or bidirectionally) the selectedItem? You can listen to
> it as it changes easily enough, but why drive it based on the data model?
>
> And if that is a use case that has to be supported, then we have to
> evaluate the impact on the SelectionModel. That is, any attempts to mutate
> the selection from the Skin code simply won't work (but that's OK if that's
> OK, if you know what I mean). We (meaning all of us on this list) need to
> evaluate what the impact is both semantically and in code. Typically we'd
> put if(!isBound()) checks into the SelectionModel implementations so they
> only change the selectedItem if it isn't bound to avoid the exception in
> that case.
>

I think this one relates back to the fact that in List/Table/Tree the
'selection' is a visual GUI thing, more like 'focus', whereas in
ChoiceBox/ComboBox the selection is a data thing, more like 'items'. Ideas
for one seem to cause conflict with the other. Is there an argument here
for ChoiceBox/ComboBox not using a selection model? Seems almost illogical
that it wouldn't have a selectionModel but in reality it is semantically
different to the normal selectionModel usage.


>
> So to recapitulate :-)
> - The only (?) reason for HasValue is to facilitate frameworks. What kinds
> of frameworks would use it?
> - What else might want to be a HasValue besides a Control? Or would
> SingleValueControl / MultiValueControl be more appropriate to what we're
> trying to do?
> - Why would the value of a ListView be the selected item instead of the
> items?
> - Why would the developer want to bind the selected item of a ListView,
> TreeView, or TableView? (Not bind to, but bind)
>

> Cheers!
> Richard
>
> (Doh, is there a reason this is off the openjfx-dev list? I'm guessing a
> mistake, you can repost if you like)
>

Yep, doh.


More information about the openjfx-dev mailing list