Wiki Markup |
---|
{scrollbar}
h1. |
Data
...
Binding
...
and
...
Model-View-Controller
...
Framework
...
As
...
the
...
XUL
...
framework
...
progressed,
...
Pentaho
...
developed
...
a
...
need
...
for
...
a
...
clean,
...
underlying
...
model-view-controller
...
(MVC)
...
architecture
...
application.
...
MVC
...
provides
...
for
...
a
...
clean
...
separation
...
between
...
application
...
data
...
(models),
...
view
...
logic
...
(controllers)
...
and
...
the
...
user
...
interface
...
(views).
...
This
...
separation
...
creates
...
loosely
...
coupled
...
components
...
that
...
are
...
easier
...
to
...
maintain
...
and
...
test.
...
For
...
a
...
more
...
in-depth
...
look
...
at
...
building
...
Pentaho
...
XUL
...
applications
...
with
...
the
...
MVC
...
pattern,
...
please
...
refer
...
to
...
the
...
...
...
...
...
.
At the heart of any MVC application framework lies a method for synchronizing data between the models and views. Many frameworks leave this "housekeeping" to the developer. XUL bindings offer a more developer-friendly approach.
What's in a Binding?
A XUL binding object consists of four primary and two optional pieces of data:
- Two XulEventSource objects – one "Source," the other "Target" – and a property for each to "Bind" together.
- A binding strategy (one-way, bi-directional, or bind-once).
A converter object to manage data translation between the two is also an option.
Creating a Binding Object
There are several methods for creating a binding object in the XUL framework. Some are as simple as calling bind() with four strings from an event handler. All of those methods are covered in the aforementioned MVC document. Below is the most basic representation of a binding:
Code Block |
---|
Binding bind = new DefaultBinding(sourceObject, "firstName", targetObject, "value");
{code}
|
When
...
added
...
to
...
a
...
binding
...
context
...
(explained
...
later
...
in
...
this
...
guide)
...
it
...
will
...
synchronize
...
data
...
between
...
sourceObject
...
and
...
targetObject
...
by
...
way
...
of
...
firstName
...
and
...
value
...
respectively.
...
Because
...
Java
...
lacks
...
first-class
...
support
...
for
...
properties,
...
and
...
it's
...
bad
...
form
...
to
...
write
...
objects
...
with
...
direct
...
member
...
access,
...
a
...
binding
...
accesses
...
data
...
by
...
way
...
of
...
the
...
JavaBean
...
standard.
...
At
...
the
...
JavaBean
...
level,
...
the
...
binding
...
looks
...
something
...
like
...
this:
...
Code Block |
---|
sourceObject.getFirstName() => targetObject.setValue()
sourceObject.setFirstName() <= targetObject.getValue()
{code}
h2. Binding Strategies
By default, a binding object represents a synchronization |
Binding Strategies
By default, a binding object represents a synchronization bi-directionally.
...
Any
...
change
...
to
...
the
...
source
...
will
...
update
...
the
...
target
...
and
...
visa-versa.
...
You
...
can
...
optionally
...
prescribe
...
for
...
a
...
one-way
...
binding
...
between
...
source
...
and
...
target
...
as
...
such:
...
Code Block |
---|
binding.setBindingType(Binding.Type.ONE_WAY);
{code}
Where * |
Where ONE_WAY
...
is
...
a
...
type
...
defined
...
in
...
Binding.Type
...
enumeration.
...
A
...
one-way
...
binding
...
will
...
send
...
data
...
from
...
the
...
source
...
to
...
the
...
target
...
but
...
not
...
the
...
other
...
way
...
around.
...
Future
...
versions
...
will
...
introduce
...
the
...
concept
...
of
...
a
...
"bind-once"
...
strategy
...
that
...
will
...
in
...
essence
...
"flash"
...
a
...
snapshot
...
of
...
data
...
between
...
objects
...
at
...
the
...
time
...
of
...
the
...
binding's
...
instantiation.
...
Conversions
You can further extend the flexibility of your bindings by providing a BindingConvertor object to manage the translation of data between objects:
BindingConvertor.java
Code Block |
---|
public abstract class BindingConvertor<V, R> {
...
public abstract R sourceToTarget(V value);
public abstract V targetToSource(R value);
}
{code}
|
Below
...
is
...
a
...
simple
...
implementation
...
that
...
binds
...
the
...
value
...
of
...
a
...
XulTextbox
...
with
...
the
...
selectedIndex
...
of
...
a
...
XulMenuList
...
.
...
When
...
a
...
user
...
enters
...
a
...
numeric
...
string
...
into
...
the
...
text
...
box,
...
it
...
will
...
be
...
converted
...
into
...
an
...
integer
...
before
...
being
...
passed
...
to
...
the
...
setSelectedIndex
...
method
...
of
...
the
...
menu
...
list:
...
Code Block |
---|
Binding binding = new DefaultBinding(textbox, "value", dropdown, "selectedIndex");
BindingConvertor conversion = new BindingConvertor<String, Integer>(){
@Override
public Integer sourceToTarget(String value) {
return Integer.parseInt(value);
}
@Override
public String targetToSource(Integer value) {
return value.toString();
}
}
binding.setConversion(conversion);
{code}
h2. Types of Bindings
So far you have seen DefaultBinding used. This binding is toolkit neutral and all operations done through it happen in the same thread in which the property change event occors. However this can cause problems in both Swt and Swing where UI operations are happening outside of the "event" thread. To correct this you can use SwtBinding or SwingBinding.
However, creating these "flavored" bindings are we call them has the side effect of making your code non-portable. To get around this we have created a BindingFactory for bindings that can be configured outside of your Xul code, Spring injected for instance.
h2. Binding Factories
DefaultBindingFactory (creates the platform neutral bindings)
SwingBindingFactory (forces all events where a XulComponent is the target to happen in the event thread.)
SwtBindingFactory (forces all events where a XulComponent is the target to happen in the event thread.)
GwtBindingFactory (same as DefautBindingFactory, though compatible with GWT)
|
Types of Bindings
So far you have seen DefaultBinding used. This binding is toolkit neutral and all operations done through it happen in the same thread in which the property change event occors. However this can cause problems in both Swt and Swing where UI operations are happening outside of the "event" thread. To correct this you can use SwtBinding or SwingBinding.
However, creating these "flavored" bindings are we call them has the side effect of making your code non-portable. To get around this we have created a BindingFactory for bindings that can be configured outside of your Xul code, Spring injected for instance.
Binding Factories
DefaultBindingFactory (creates the platform neutral bindings)
SwingBindingFactory (forces all events where a XulComponent is the target to happen in the event thread.)
SwtBindingFactory (forces all events where a XulComponent is the target to happen in the event thread.)
GwtBindingFactory (same as DefautBindingFactory, though compatible with GWT)
Wiki Markup |
---|
{scrollbar} |