While BXML is often used to declare the structure of an application, the application's behavior is still defined in code (either Java or a JVM-compatible scripting language). Most application logic is executed in response to an "event" triggered by some external source, such as user input or the completion of an asynchronous operation running in a background thread.
Loading the UI
In general, a Pivot application will load its user interface in the startup() method of the main application class. This method, along with the shutdown(), suspend(), and resume() methods, is defined by the Application interface, which all Pivot applications must implement.
The StockTracker class implements the Application interface for the Stock Tracker application. StockTracker's startup() method is shown below:
@Override public void startup(Display display, Map<String, String> properties) throws Exception { String language = properties.get(LANGUAGE_KEY); Locale locale = (language == null) ? Locale.getDefault() : new Locale(language); Resources resources = new Resources(StockTrackerWindow.class.getName(), locale); BXMLSerializer bxmlSerializer = new BXMLSerializer(); window = (StockTrackerWindow)bxmlSerializer.readObject(getClass().getResource("stock_tracker_window.bxml"), resources); window.open(display); }
This code creates an instance of BXMLSerializer and loads the BXML source for the main window. It then opens the main window, causing the application to appear on the screen.
Adding Event Listeners
At this point, the application is visible and the user can begin interacting with it. Pivot applications respond to user actions by firing "events". For example, Pivot components fire such events as "mouse moved", "button pressed", or "selected index changed". A caller signals its interest in a particular event by implementing an interface that defines an event handler method and adding itself as an event lister on the event source.
In the following code snippet taken from StockTrackerWindow#initialize(), two event handlers are created: a selection change listener on the stock quote table view and a button press listener on the Yahoo! Finance link button. The first listenener is called when the selection changes in the quote table view, and the second when the user clicks on the link:
@Override public void initialize(Map<String, Object> namespace, URL location, Resources resources) { ... stocksTableView.getTableViewSelectionListeners().add(new TableViewSelectionListener.Adapter() { @Override public void selectedRangesChanged(TableView tableView, Sequence<Span> previousSelectedRanges) { ... } }); ... addSymbolButton.setAction(addSymbolAction); removeSymbolsButton.setAction(removeSymbolsAction); ... yahooFinanceButton.getButtonPressListeners().add(new ButtonPressListener() { @Override public void buttonPressed(Button button) { ... } }); }
Some listener interfaces, such as ButtonPressListener, define only a single event handler method, but others (including TableViewSelectionListener) define more than one and serve as a grouping of related events. Interfaces with multiple handler methods generally define an inner Adapter class that can be used to simplify subclassing, as shown above.
Note that, though these handlers are implemented as anonymous inner classes, this is not required - any class that implements the appropriate listener interface can register as a listener. It is also possible to define listeners in script within the BXML file itself; this is discussed in more detail in the Scripting section.
Actions
Though the "add symbol" and "remove symbol" operations could be performed in a button press listener attached to their respective buttons, they have been abstracted in the Stock Tracker example application into "actions". An action in Pivot is a class that extends the abstract org.apache.pivot.wtk.Action class. This class defines a single abstract perform() method that is called to invoke the action:
private Action addSymbolAction = new Action(false) { @Override @SuppressWarnings("unchecked") public void perform(Component source) { ... } };
Actions can be assigned to multiple elements within an application (for example, to a toolbar button, a menu item, and to a keystroke combination). This allows the same code to be executed in response to multiple user gestures without the need to write redundant event listeners. Actions also support an enabled state that is mirrored by any component attached to the action; this allows an application to easily manage the set of allowed actions given the current application state.
Next: Web Queries