| <?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><bxml:include></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><bxml:include></tt> |
| tag. |
| </p> |
| </li> |
| |
| <li> |
| <p> |
| The <tt><bxml:script></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><bxml:define></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><bxml:reference></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 <tabs>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><bxml:script></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 <bxml:reference> 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 <bxml:include> 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> |