Data binding

From JAXXWiki

Data binding is JAXX's ability to bind an arbitrary expression to a property, and to have the property update in real time as the value of the expression changes.

Contents

Overview

Data bindings are established using pairs of curly braces ({}) in XML attributes. Within the curly braces you may insert any Java expression, and the value of the expression is used as the attribute value.

<JTextField id='textField' text='Sample Text'>
<JLabel text='You entered: {textField.getText()}'/>

It shouldn't be surprising that the JLabel initially contains the text You entered: Sample Text. More interesting is the fact that editing the contents of the text field automatically causes the label's text to update in real-time.

Real-time updates

JAXX scans through the data binding expression to find its dependencies. In the above example, it finds a constant string "You entered: ", which it ignores because it will never change, and the token textField.getText(). JAXX recognizes that textField is a JTextField, and that the getText() method will return a different value when the field's Document is updated.

It attaches a DocumentListener to listen to changes to the document, and reevaluates the expression whenever the listener receives an event. It also attaches a PropertyChangeListener to the text field's document property, because changing the document also requires the expression to be reevaluated. Changing the document also necessitates removing listeners from the old document and re-adding them to the new document.

On the off chance that you decide to change the textField property itself, JAXX pays attention to that as well. Updating the textField property from a script will remove listeners from the old objects, add them to the new objects, and update the expression.

The end result is that the JLabel updates automatically whenever the JTextField changes.

Use with complex data types

XML attributes are always strings, and so to assign a Java property using an XML attribute you must be able to express its value using a string. For string-valued properties like text and title, that's no problem. For properties with obvious string representations -- int, boolean and the like -- this is also not a problem.

But what if you need to ass 2000 ign a component's border or font? What about the hundreds of other properties with complex data types that cannot be obviously expressed as strings?

Data binding allows you to express a value using arbitrary Java code, so its utility here is obvious. You can express the values directly with Java code (a string format you are already familiar with), rather than having to learn a new, complex representation for these types.

Example:

<JPanel border='{BorderFactory.createTitledBorder("Data Binding")}'>
  <JLabel text='Custom Font' font='{new Font("Century Gothic", 0, 24)}'/>
</JPanel>

Listening to fields

The problem

For get methods, there is usually an event of some kind that JAXX can listen to in order to kno 2000 w when the return value of the method has changed (or at least potentially changed). For fields, though, there is no such possibility. Java code cannot even in theory fire events when fields are changed.

Unfortunately, there are spots where being able to listen to field updates would be very convenient. Consider the following:

<script>
  boolean mouseOver;
</script>

<JLabel text='{mouseOver ? "Mouse Over!" : "Mouse Out"}' 
    foreground='{mouseOver ? Color.RED : Color.BLACK}' 
    font='{mouseOver ? new Font("Arial", Font.ITALIC, 18) : new Font("Arial", 0, 12)}'
    onMouseEntered='mouseOver = true'
    onMouseExited='mouseOver = false'/>

This example is perhaps a bit contrived, but it still reflects a useful ability. Without the ability to have field updates trigger data binding, though, we would have to add a getter and setter for mouseOver and fire property change events.

The solution

JAXX handles this case by instrumenting the code. In the mouseEntered and mouseExited event handlers, it recognizes that we are updating a field and adds synthetic PropertyChangeEvent broadcasts. The impact on performance is generally negligible.

Limitations

Data binding parses through Java code looking for methods and fields that it knows how to listen for changes to. If a method represents a property which fires PropertyChangeEvent (a bound property), JAXX discovers this via introspection. For non-bound properties or other types of methods altogether, the TagHandler for the tag must know how to deal with the method. The TagHandler for JTextField, for instance, knows that getText() must be handled via a DocumentListener on the Document.

If a method is not 'known' as described above, JAXX has no idea how to listen to it or if it even makes sense to listen to.

As field updates are handled by instrumenting the JAXX code, changing fields outside of JAXX (i.e. from ordinary Java code) bypasses JAXX's listeners and the changes will not be detected.