blob: 378d2e9ade0b8c09da75215719b7312d562f0a4b [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document id="wtkx-primer">
<properties>
<title>BXML Primer</title>
</properties>
<body>
<p>
BXML is an XML-based markup language for simplifying the construction of Java object
hierarchies. While it is most often used to define the user interface of an Apache Pivot
application, it is not limited to user interface construction, and can actually be used to
create hierarchies of any object type.
</p>
<p>
This document introduces the BXML language and explains how it can be used to create and
configure a collection of Java objects.
</p>
<h3>BXMLSerializer</h3>
<p>
The <tt>org.apache.pivot.beans.BXMLSerializer</tt> class is used to load a structure
defined in a BXML file. This class implements the
<tt>org.apache.pivot.serialization.Serializer</tt> interface, which defines the
<tt>readObject()</tt> method for reading an object value from an input stream:
</p>
<source type="java">
<![CDATA[
public interface Serializer<T> {
public T readObject(InputStream inputStream)
throws IOException, SerializationException;
public void writeObject(T object, OutputStream outputStream)
throws IOException, SerializationException;
public String getMIMEType(T object);
}
]]>
</source>
<p>
For example, the following code snippet loads a Window object declared in a file named
"my_window.bxml":
</p>
<source type="java">
<![CDATA[
BXMLSerializer bxmlSerializer = new BXMLSerializer();
Window window = (Window)bxmlSerializer.readObject(getClass().getResource("my_window.bxml"));
]]>
</source>
<p>
<tt>BXMLSerializer</tt> does not implement <tt>writeObject()</tt>, but does provide some
additional convenience methods for reading BXML as well as for localizing the deserialized
structure using resource bundles.
</p>
<h3>Namespaces</h3>
<p>
In BXML, an XML namespace represents a Java package. Declaring a namespace associates the
namespace prefix with the package, similar to how the import keyword is used in Java.
</p>
<p>
For example, the following simple BXML associates the package "com.foo" with the "foo"
namespace prefix:
</p>
<source type="xml">
<![CDATA[
<foo:Bar xmlns:foo="com.foo"/>
]]>
</source>
<p>
If this file were deserialized using <tt>BXMLSerializer</tt>, an instance of
<tt>com.foo.Bar</tt> would be returned by the call to <tt>readObject()</tt>. The following
BXML, which maps the <tt>com.foo</tt> package to the default namespace, would produce the
same results with slightly less verbose markup:
</p>
<source type="xml">
<![CDATA[
<Bar xmlns="com.foo"/>;
]]>
</source>
<p>
More complex examples may use classes defined in multiple packages; multiple namespace
prefixes can be used for this purpose.
</p>
<h3>The "bxml" Namespace</h3>
<p>
The "bxml" namespace prefix is reserved and defines a number of elements and attributes
that are used for internal processing. It is generally declared on the root element of a
BXML document:
</p>
<source type="xml">
<![CDATA[
<Bar xmlns:bxml="http://pivot.apache.org/bxml"
xmlns="com.foo">
...
</Bar>
]]>
</source>
<p>
The "bxml" namespace includes the following:
</p>
<ul>
<li>
<p>
The <tt>bxml:id</tt> attribute, which is used to assign a variable name to an element
declared in a BXML file. For example, the following markup would associate an instance of the
<tt>Foo</tt> class with the ID "myFoo". This variable is added to the document's variable
namespace (which is different from the XML namespace used to import Java packages), and
can then be referenced elsewhere in the file or by code that deserializes the file,
via the <tt>BXMLSerializer#getNamespace()</tt> method:
</p>
<source type="xml">
<![CDATA[
<Foo bxml:id="myFoo"/>
]]>
</source>
</li>
<li>
<p>
The <tt>&lt;bxml:include&gt;</tt> tag, which is used to include external resources, including
nested BXML documents. For example, the following markup would embed the contents of the
"my_include.bxml" file in the current document:</p>
<source type="xml">
<![CDATA[
<bxml:include src="my_include.bxml"/>
]]>
</source>
<p>
BXML includes are often used for partitioning content into manageable pieces (for example,
when working on large applications or with multiple developers, or when defining reusable
content templates). By default, each include is assigned its own variable namespace to
avoid naming collisions with ancestor documents; however, this behavior can be overridden
by adding an "inline" attribute with a value of "true" to the <tt>&lt;bxml:include&gt;</tt>
tag.
</p>
</li>
<li>
<p>
The <tt>&lt;bxml:script&gt;</tt> tag, which defines a block of script code within
a BXML file. For example, the following script block defines a function named
<tt>foo()</tt>, which can then be called from other script blocks in the document:
</p>
<source type="xml">
<![CDATA[
<bxml:script>
function foo() {
....
}
</bxml:script>
]]>
</source>
<p>
The default scripting language is JavaScript, but any JVM-compatible scripting language can
be used. The <tt>language</tt> processing instruction is used to specify a different
language; for example, Groovy:
</p>
<source type="xml">
<![CDATA[
<?language groovy?>
]]>
</source>
<p>
Script blocks can also be defined in event handler attributes and elements. Scripting and
event handling are discussed in more detail below.
</p>
</li>
<li>
<p>
The <tt>&lt;bxml:define&gt;</tt> tag, which is used to declare objects that will exist
outside of the hierarchy but may be referred to elsewhere.
</p>
<p>
For example, the following define block declares an instance of <tt>Foo</tt> named "myFoo"
that is not processed as part of the document flow (in other words, would not be added to
its parent element, if it had one) but can be referred to by variable name later in the
document:
</p>
<source type="xml">
<![CDATA[
<bxml:define>
<Foo bxml:id="myFoo"/>
</bxml:define>
]]>
</source>
</li>
<li>
<p>
The <tt>&lt;bxml:reference&gt;</tt> tag, used to dereference a page variable. For
example, the <tt>Foo</tt> instance in the previous example could be dereferenced as
follows elsewhere in the document:
</p>
<source type="xml">
<![CDATA[
<bxml:reference id="myFoo"/>
]]>
</source>
<p>
Wherever this tag appears, it will effectively be replaced by the value of the "myFoo"
variable.
</p>
<p>
The variable deference operator ("$") can also be used to dereference page variables. This
is discussed in more detail below.
</p>
</li>
</ul>
<h3>Elements</h3>
<p>
In BXML, an XML element that does not begin with the reserved "bxml" namespace prefix
represents one of the following:
</p>
<ul>
<li><p>A class instance</p></li>
<li><p>A property of a class instance</p></li>
<li><p>A "static" property</p></li>
</ul>
<p>Each of these is discussed in more detail below.</p>
<h3>Class Instances</h3>
<p>
If an element's tag name begins with an uppercase letter (and it is not a "static"
property setter; see below), it is considered a class instance. When
<tt>BXMLSerializer</tt> encounters such an element, it creates an instance of that class. As
discussed above, the XML namespace prefix is used to determine the Java package to which
the class belongs.
</p>
<p>
For example, the following BXML would produce an instance of the
<tt>org.apache.pivot.wtk.Label</tt> class populated with the text "Hello, World!":
</p>
<source type="xml">
<![CDATA[
<Label text="Hello, World!" xmlns="org.apache.pivot.wtk" />
]]>
</source>
<p>
Class instance elements in a BXML file will often represent instances of Java bean types.
Internally, <tt>BXMLSerializer</tt> uses an instance of
<tt>org.apache.pivot.beans.BeanAdapter</tt> to wrap the instantiated class and invoke its
setter methods. This class implements the <tt>org.apache.pivot.collections.Dictionary</tt>
interface and allows a caller to get and set bean property values as key/value pairs.
</p>
<p>
However, if the element represents a type that already implements the <tt>Dictionary</tt>
interface (such as <tt>org.apache.pivot.collections.HashMap</tt>), it is not wrapped and
its dictionary methods are used directly. For example, the following BXML creates an
instance of <tt>org.apache.pivot.collections.HashMap</tt> and sets its "foo" and "bar"
values to "123" and "456", respectively:
</p>
<source type="xml">
<![CDATA[
<HashMap foo="123" bar="456"/>
]]>
</source>
<p>
How the "foo" and "bar" attributes are handled is discussed in more detail below.
</p>
<h3>Instance Properties</h3>
<p>
Elements whose tag names begin with a lowercase letter represent instance properties. An
instance property element may represent one of the following:
</p>
<ul>
<li><p>A property setter</p></li>
<li><p>A read-only sequence</p></li>
<li><p>A read-only dictionary</p></li>
<li><p>An event listener list</p></li>
</ul>
<h4>Property Setters</h4>
<p>
If the element represents a property setter, the contents of the element (which must be
either a text node or a nested class instance element) are passed as the value to the
setter for the property. For example, the following BXML creates an instance of the
<tt>Label</tt> class and sets the value of the label's "text" property to "Hello, World!":
</p>
<source type="xml">
<![CDATA[
<Label xmlns="org.apache.pivot.wtk">
<text>Hello, World!</text>
</Label>
]]>
</source>
<p>
This produces the same result as the earlier example which used an attribute to set the
"text" property:
</p>
<source type="xml">
<![CDATA[
<Label text="Hello, World!" xmlns="org.apache.pivot.wtk"/>
]]>
</source>
<p>
The following example creates an instance of <tt>ListView</tt> and sets the value of its
"listData" property to an instance of <tt>org.apache.pivot.collections.ArrayList</tt>
that has been populated with several instances of
<tt>org.apache.pivot.wtk.content.ListItem</tt>:
</p>
<source type="xml">
<![CDATA[
<ListView xmlns="org.apache.pivot.wtk"
xmlns:collections="org.apache.pivot.collections"
xmlns:content="org.apache.pivot.wtk.content">
<listData>
<collections:ArrayList>
<content:ListItem text="A"/>
<content:ListItem text="B"/>
<content:ListItem text="C"/>
</collections:ArrayList>
</listData>
</ListView>
]]>
</source>
<h4>Read-Only Sequences</h4>
<p>
If the property represents a read-only sequence (a bean property whose getter returns an
instance of <tt>org.apache.pivot.collections.Sequence</tt> and has no corresponding setter
method), the contents of the element are added to the sequence. For example, the "tabs"
property of the <tt>org.apache.pivot.wtk.TabPane</tt> class is a read-only sequence
representing the tab pane's tab components. Tabs can be added to a <tt>TabPane</tt> in
BXML as follows:
</p>
<source type="xml">
<![CDATA[
<TabPane xmlns="org.apache.pivot.wtk">
<tabs>
<Label text="Foo"/>
<Label text="Bar"/>
</tabs>
</TabPane>
]]>
</source>
<h4>Read-Only Dictionaries</h4>
<p>
A property element may also represent a read-only dictionary (a bean property whose getter
returns an instance of <tt>org.apache.pivot.collections.Dictionary</tt> but has no
corresponding setter method). For example, the "userData" property of the
<tt>org.apache.pivot.wtk.Component</tt> class represents a read-only dictionary:
</p>
<source type="xml">
<![CDATA[
<Label text="Hello, World!"
xmlns="org.apache.pivot.wtk">
<userData foo="123" bar="456"/>
</Label>
]]>
</source>
<p>
The attribute values are put into the dictionary using the attribute names as keys.
</p>
<h4>Listener Lists</h4>
<p>
Finally, the property may represent an event listener list (an instance of
<tt>org.apache.pivot.util.ListenerList</tt>). If so, the sub-elements represent
listeners of the appropriate type and are added to the listener list. This is discussed
in more detail in the <a href="#scripting">Scripting</a> section.
</p>
<h4>Default Properties</h4>
<p>
A class may define a "default property" using the <tt>@DefaultProperty</tt> annotation
defined in the <tt>org.apache.pivot.beans</tt> package. If present, the sub-element
representing the default property can be omitted from the markup. For example, the
<tt>TabPane</tt> component discussed above defines the "tabs" property as the default, so
the &lt;tabs&gt;sub-element is not actually required:
</p>
<source type="xml">
<![CDATA[
<TabPane xmlns="org.apache.pivot.wtk">
<Label text="Foo"/>
<Label text="Bar"/>
</TabPane>
]]>
</source>
<p>
Taking advantage of default properties can significantly reduce the verbosity of BXML
markup.
</p>
<h3>Static Properties</h3>
<p>
An element may also represent a "static" property setter (sometimes called an
"attached property"). Static properties are properties that only make sense in a
particular context. They are not intrinsic to the class to which they are applied, but
are defined by another class (generally the parent container of a component).
</p>
<p>
Static properties are prefixed with the name of class that defines them.
For example, The following BXML invokes the static setter for the TabPane class's
"tabData" property:
</p>
<source type="xml">
<![CDATA[
<TabPane xmlns:content="org.apache.pivot.wtk.content"
xmlns="org.apache.pivot.wtk">
<Label text="Tab 1">
<TabPane.tabData>
<content:ButtonData text="First Tab"/>
</TabPane.tabData>
</Label>
</TabPane>
]]>
</source>
<p>
This translates roughly to the following in Java:
</p>
<source type="java">
<![CDATA[
TabPane tabPane = new TabPane();
Label label = new Label();
label.setText("Tab 1");
ButtonData buttonData = new ButtonData();
buttonData.setText("First Tab");
TabPane.setTabData(label, buttonData);
tabPane.getTabs().add(label);
]]>
</source>
<p>
The call to <tt>TabPane.setTabData()</tt> attaches the "tabData" property to the
<tt>Label</tt> instance. The tab pane then uses the value of this property as the button
data for the label's tab in the tab pane's button bar. Other containers, including
<tt>Accordion</tt> and <tt>TablePane</tt>, define similar properties.
</p>
<h3>Attributes</h3>
<p>
An attribute in BXML may represent one of the following:
</p>
<ul>
<li><p>A property of a class instance</p></li>
<li><p>A "static" property</p></li>
<li><p>An event listener</p></li>
</ul>
<h4>Instance Properties</h4>
<p>
If an attribute represents an instance property, the attribute value is passed as the
argument to the setter method. If the type of the property is a string, the value is
passed as-is; otherwise, <tt>BXMLSerializer</tt> attempts to convert the value to the
appropriate type using the <tt>BeanAdapter#coerce()</tt> method. For example, given the
following simple bean class:
</p>
<source type="java">
<![CDATA[
package com.foo;
public class MyBean {
public String getFoo() { ... }
public void setFoo(String foo) { ... }
public int getBar() { ... }
public void setBar(int bar) { ... }
}
]]>
</source>
<p>
the following BXML would instantiate the bean and invoke the "foo" and "bar" setters,
passing a string to <tt>setFoo()</tt> and an int to <tt>setBar()</tt>:
</p>
<source type="xml">
<![CDATA[
<MyBean foo="hello" bar="123"/>
]]>
</source>
<p>
Note that, if the parent element represents an untyped class (a class that implements
the <tt>Dictionary</tt> interface directly, such as
<tt>org.apache.pivot.collections.HashMap</tt>), the type of the attribute cannot be
determined, and no conversion takes place - the values are simply passed as strings.
</p>
<h4>Static Properties</h4>
<p>
Like elements, attributes may also represent static property setters. For example, The
following BXML invokes the static setter for the TabPane class's "tabData" property:
</p>
<source type="xml">
<![CDATA[
<TabPane xmlns:content="org.apache.pivot.wtk.content"
xmlns="org.apache.pivot.wtk">
<Label text="Tab 1" TabPane.tabData="First Tab"/>
</TabPane>
]]>
</source>
<p>
This translates roughly to the following in Java:
</p>
<source type="java">
<![CDATA[
TabPane tabPane = new TabPane();
Label label = new Label();
label.setText("Tab 1");
TabPane.setTabData(label, "First Tab");
tabPane.getTabs().add(label);
]]>
</source>
<h4>Event Listeners</h4>
<p>
Finally, an attribute may represent an event listener. Event listener attribute values
contain script code that is executed in response to the event. This is discussed in more
detail in the <a href="#scripting">Scripting</a> section.
</p>
<h3>Resolution Operators</h3>
<p>
Property setter attributes (either bean or static) in BXML support several resolution
operators that extend their capabilities:
</p>
<ul>
<li><p>Object dereference</p></li>
<li><p>Resource resolution</p></li>
<li><p>URL resolution</p></li>
</ul>
<h4>Object Dereference</h4>
<p>
The object deference operator allows a caller to replace an attribute value with
an instance of a named object before the corresponding setter method is invoked. Any
attribute whose value begins with the "$" is considered an object reference.
</p>
<p>
For example, a table view header must be associated with an instance of <tt>TableView</tt>;
in Java, this is done via the <tt>setTableView()</tt> method. In BXML, the object
dereference operator is used. The following BXML defines an instance of
<tt>ScrollPane</tt>, setting a <tt>TableView</tt> as its view component and a
<tt>TableViewHeader</tt> as the column header. The table view is associated with the
header via the "tableView" attribute:
</p>
<source type="xml">
<![CDATA[
<ScrollPane xmlns="org.apache.pivot.wtk"
xmlns:bxml="http://pivot.apache.org/bxml">
<view>
<TableView bxml:id="tableView">
...
</TableView>
</view>
<columnHeader>
<TableViewHeader tableView="$tableView"/>
</columnHeader>
</ScrollPane>
]]>
</source>
<h4>Resource Resolution</h4>
<p>
In BXML, resource substitution can be performed at load time for localization purposes.
When given an instance of <tt>org.apache.pivot.util.Resources</tt>, <tt>BXMLSerializer</tt>
will replace instances of resource names with their locale-specific values. Resource
names are identified by a "%" prefix, as shown below:
</p>
<source type="xml">
<![CDATA[
<Label text="%myText"/>
]]>
</source>
<p>
The associated resource file might contain something like the following:
</p>
<source type="jscript">
<![CDATA[
{ myText:"This is my text!"
}
]]>
</source>
<p>
producing a label containing the text "This is my text!".
</p>
<h4>URL Resolution</h4>
<p>
Attributes can also be used to specify URLs. An attribute that begins with the "@"
character is converted to a URL whose path is interpreted as relative to the location of
the BXML source file. For example, the following BXML would load an image from the same
directory as the BXML file into an <tt>ImageView</tt> component. This BXML translates to a
call to the <tt>ImageView#setImage(java.net.URL)</tt> method:
</p>
<source type="xml">
<![CDATA[
<ImageView image="@foo.png"/>
]]>
</source>
<p>
Without the "@" operator, bean properties would have no context by which to determine the
path to such a resource.
</p>
<h3><a name="scripting">Scripting</a></h3>
<p>
The <tt>&lt;bxml:script&gt;</tt> tag allows a caller to import scripting code into or
embed script within a BXML file. Any JVM scripting language can be used, including
JavaScript, Groovy, and Clojure, among others.
</p>
<p>
For example, the following BXML defines a JavaScript block that defines a variable
named "foo". The value of this variable is used to populate the <tt>Label</tt> instance
that is declared as the window's content:
</p>
<source type="xml">
<![CDATA[
<Window xmlns:bxml="http://pivot.apache.org/bxml"
xmlns="org.apache.pivot.wtk">
<bxml:script>
var foo = "Hello, World!";
</bxml:script>
<Label text="$foo"/>
</Window>
]]>
</source>
<p>
The script could also have been defined in an external file:
</p>
<source type="xml">
<![CDATA[
<Window xmlns:bxml="http://pivot.apache.org/bxml"
xmlns="org.apache.pivot.wtk">
<bxml:script src="foo.js"/>
<Label text="$foo"/>
</Window>
]]>
</source>
<p>
In either case, any global variables declared in a script are added to the BXML file's
variable namespace and become available for use by the object dereference operator,
the &lt;bxml:reference&gt; tag, and to callers via <tt>BXMLSerializer#getNamespace()</tt>,
discussed in more detail below.
</p>
<h3>Listener List Elements</h3>
<p>
Script code can also be used to define event handlers in BXML. Event handlers can often be
defined more succinctly in script than in Java. For example, given the following BXML:
</p>
<source type="xml">
<![CDATA[
<PushButton xmlns="org.apache.pivot.wtk"
xmlns:bxml="http://pivot.apache.org/bxml"
bxml:id="pushButton" buttonData="Click Me!"/>
]]>
</source>
<p>
the Java code to obtain a reference to a <tt>PushButton</tt> and attach a button press
listener to it might look like this:
</p>
<source type="java">
<![CDATA[
PushButton pushButton = (PushButton)bxmlSerializer.getNamespace().get("pushButton");
pushButton.getButtonPressListeners().add(new ButtonPressListener() {
public void buttonPressed(Button button) {
// Handle event
}
});
]]>
</source>
<p>
While this is simple enough, it can become cumbersome in any non-trivial application
where many such event are defined. A similar event handler might be defined in JavaScript
as follows:
</p>
<source type="xml">
<![CDATA[
<PushButton xmlns="org.apache.pivot.wtk"
xmlns:bxml="http://pivot.apache.org/bxml"
buttonData="Click Me!">
<buttonPressListeners>
function buttonPressed(button) {
// Handle event
}
</buttonPressListeners>
</PushButton>
]]>
</source>
<p>
This version is quite a bit easier to read, and creates a strong association between
the button and the handler. It also doesn't require the button to have an ID.
</p>
<p>
When script is declared within a listener list element, <tt>BXMLSerializer</tt> creates a
special scope that is local to the handler. As a result, any variables or functions
defined within the script block do not pollute the page's global namespace and are only
visible within the block. However, the script code can still see and access global variables
declared elsewhere in the page. This is somewhat analogous to defining an anonymous inner
class as a listener in Java.
</p>
<p>
Also, though it isn't obvious from this simple example, script-based event handlers are
not required to provide implementations for every method defined by the listener interface.
Any omitted methods are simply processed by a default no-op handler.
</p>
<h3>Event Listener Attributes</h3>
<p>
Event listeners can also be declared in attributes, using a syntax similar to that used for
static property setters. The attribute name for an event listener consists of the name of
the interface that defines the event plus the name of the event, separated by a period.
Like listener list elements, a special scope is created for listener attributes that is
local to the handler; any variables defined within the attribute are only visible within
the handler.
</p>
<p>
For example, the above button press listener can be declared in an attribute as follows:
</p>
<source type="xml">
<![CDATA[
<PushButton xmlns="org.apache.pivot.wtk"
xmlns:bxml="http://pivot.apache.org/bxml"
buttonData="Click Me!"
ButtonPressListener.buttonPressed="handleEvent(arguments[0])"/>
]]>
</source>
<p>
Note that the handler function is passed a value of <tt>arguments[0]</tt>. The
<tt>arguments</tt> array contains the arguments that were originally passed to the event
listener method, and only exists within the scope of the event handler.
<tt>arguments[0]</tt> contains the first argument passed to the listener method, which in
this case is a reference to the button that fired the event.
</p>
<p>
Attribute-based event handlers are well suited to short handler code that, ideally, fits
on a single line. Longer event handler code may be better suited to an element-based
listener list, or, depending on the level of complexity, implementation in a Java or
other compiled language.
</p>
<h3>Accessing Named Objects</h3>
<p>
As previously discussed, the <tt>BXMLSerializer#getNamespace()</tt> method allows a caller
to retrieve a named object instance from a BXML file once the root object has been loaded.
For example, the following code loads a hypothetical BXML file containing a <tt>Window</tt>
and a <tt>Label</tt> instance, obtains a reference to the label, changes its text to
"Welcome to Pivot!", and opens the window:
</p>
<source type="java">
<![CDATA[
public void startup(Display display, Map<String, String> properties)
throws Exception {
BXMLSerializer bxmlSerializer = new BXMLSerializer();
Window window =
(Window)bxmlSerializer.readObject(getClass().getResource("window.bxml"));
Label label = (Label)bxmlSerializer.getNamespace().get("label");
label.setText("Welcome to Pivot!");
window.open(display);
}
]]>
</source>
<p>
<tt>getNamespace()</tt> returns a value that implements the <tt>Dictionary</tt> interface,
so callers can also use the <tt>put()</tt> or <tt>remove()</tt> methods to modify the
serializer's namespace before the BXML file is loaded (effectively "parameterizing"
the BXML).
</p>
<h3>The Bindable Interface</h3>
<p>
The <tt>org.apache.pivot.beans.Bindable</tt> interface can be used to simplify integration
between BXML markup and compiled code. <tt>Bindable</tt> defines a single method,
<tt>initialize()</tt>, that is called on the root element of a BXML document once the
document has been completely loaded. It allows the implementing class to get access to the
document's namespace (i.e. page variables), the resources that were used to load it, and the
location it was loaded from, to perform any necessary post-processing (for example,
registering event listeners).
</p>
<p>
Note that only the root element will be called to <tt>initialize()</tt>, because the
bindable properties (namespace, resources, and location) apply to the document as a whole,
not to individual sub-elements. However, this includes the root elements of any BXML files
included using the &lt;bxml:include&gt; tag, allowing <tt>Bindable</tt> implementations to
effectively implement the "code behind" the markup of each BXML file used by an
application.
</p>
<h4>@BXML</h4>
<p>
If any of the <tt>Bindable</tt>'s member variables are tagged with the
<tt>org.apache.pivot.beans.BXML</tt> annotation, they will be automatically populated
with the corresponding variables defined in the BXML file. For example, given the
following BXML:
</p>
<source type="xml">
<![CDATA[
<Window xmlns="org.apache.pivot.wtk"
xmlns:bxml="http://pivot.apache.org/bxml">
<Label bxml:id="label" text="Hello, World!"/>
</Window>
]]>
</source>
<p>
a Java member variable declared as follows will be automatically populated with the
declared <tt>Label</tt> instance when the BXML file is deserialized:
</p>
<source type="java">
<![CDATA[
@BXML private Label label;
]]>
</source>
<p>
As a result, the <tt>@BXML</tt> annotation can significantly simplify the process of
working with loaded BXML data in Java code. However, it is important to note that, because
BXML binding relies on reflection to set the member variables, it can only be used with
trusted code or to set the values of public fields. For untrusted code, the namespace
value passed to the <tt>initialize()</tt> method can be used to access named objects
defined in a BXML file.
</p>
<h3>Summary</h3>
<p>
BXML provides a number of features that help simplify the process of building a user
interface. It can be used to instantiate objects and set member variables as well as
define script logic for working with those objects. It is a powerful and efficient way to
construct the user interface of a Pivot application.
</p>
</body>
</document>