Pivot: A Practical Example, Part 2 - Event Handling
WTKX files do not include any code - all logic in a Pivot application is implemented in Java. Most of this 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.
In general, a Pivot application will load its user interface and wire up event handlers 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.
Loading the UI
The Application interface in the Stock Tracker demo is implemented by the StockTracker class. The code in this file is referred to throughout the course of this section. A snippet of code from StockTracker's startup() method is shown below:
ApplicationContext applicationContext = ApplicationContext.getInstance();
// Set the locale
String language = applicationContext.getProperty(LANGUAGE_PROPERTY_NAME);
locale = (language == null) ? Locale.getDefault() : new Locale(language);
// Set the application context title
ResourceBundle resourceBundle =
ResourceBundle.getBundle(StockTracker.class.getName(), locale);
applicationContext.setTitle(resourceBundle.getString("stockTracker"));
// Load the application's UI
ComponentLoader.initialize();
ComponentLoader componentLoader = new ComponentLoader(locale);
Component content = componentLoader.load("pivot/tutorials/stocktracker/stocktracker.wtkx",
getClass().getName());
This code does the following:
Gets a reference to the application context, a singleton class that provides access to a number of system-level features and properties
Retrieves the "langauge" argument that was provided to the application context when it was created - for desktop applications, this is a command-line argument; in the browser, it is either passed as a query string argument or as an applet parameter
Creates a locale instance corresponding to the language argument
Obtains a resource bundle for the current locale
Sets the application context title (reflected in the frame title when running in a desktop application context)
Creates a new component loader using the current locale
Loads the Stock Tracker user interface from stocktracker.wtkx
This last step creates the component hierarchy defined in the WTKX files and performs any necessary resource substitutions. The result is a new component instance that can be set as the content of a window and shown to the user.
- Login or register to post comments
- 10843 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)




Comments
Jacek Furmankiewicz replied on Mon, 2008/07/07 - 7:22am
The event listener logic is still pretty similar to Swing's. Maybe you could consider defining a straight Java method name in the XML file and hooking up the event listener automatically when the UI is loaded?
GTK+ libGlade (which is very similar conceptually to your solution) allows you to define method names in the XML file. If I remember correctly, it even handles finding the proper method name, regardless of the language (e.g. libGlade works with C/C++/Ruby/Python). They call it simply "signals" (I believe Qt has a similar approach). We can always learn something new and different from non-Java tools. :-)
See here for some info:
http://delirial.com/archives/tutorial-building-guis-for-ruby-programs-with-glade/
E.g. in the Glade XML file they define a signal for an event, e.g.:
and then on the Ruby side they just need to define a method called on_quit:
You bypass the whole event listener paradigm this way and just hook up a 'signal' directly to a method (possibly with a pre-defined signature).
This would go some way towards differentiating Pivot from Swing and giving it some real edge as compared to its older brother.
I adopted the same approach in my SwingBuilder project, see the Wiki and maybe you can pinch some ideas for your solution:
http://code.google.com/p/javabuilders/wiki/JavaBuilderEventHandling
http://code.google.com/p/javabuilders/wiki/SwingBuilderEventHandlers
Greg Brown replied on Mon, 2008/07/07 - 8:03am
in response to: Jacek
> Maybe you could consider defining a straight Java method name in the XML file and hooking up the event listener automatically when the UI is loaded?
There is definitely value in allowing a caller to do something like this. We don't necessarily want to embed code in WTKX, but including a method name would be OK. The question is - where would the method live? Event handlers are defined by interfaces which must be implemented by a class. We have considered allowing a caller to provide a handler class name in WTKX for a given event class (e.g. buttonPressListener="com.foo.MyButtonPressHandler") - the loader would instantiate the class and wire up the listener.
> This would go some way towards differentiating Pivot from Swing and giving it some real edge as compared to its older brother.
We actually like the way event handling works in Swing, for the most part. We eliminated the event objects and came up with what we think is a cleaner way to register for and fire events, but the basic listener model is pretty sound. What do you think the limitations are?
Jacek Furmankiewicz replied on Mon, 2008/07/07 - 8:14am
in response to: gbrown@vmware.com
Just the amount of code that is required for clicking a button to call some Java-side method. 3-5 lines may not seem much, but once you add all the buttons you have in an app, it's a fair amount.
The 'signals' approach reduces it to a simple property value. And it's not really embedding code, think of it more of as defining a signal that can be used to map to a method when the file gets loaded.
The method would have to live in the object that is loading the layout file...I presume the loading engine has a way to get a reference to the object that called it?
Just a suggestion...if it doesn't fit with your philosophy of how the toolkit should work, that's fine. After all, it's your project :-)
Greg Brown replied on Mon, 2008/07/07 - 8:27am
in response to: Jacek
> The method would have to live in the object that is loading the layout file...I presume the loading engine has a way to get a reference to the object that called it?
At the moment, it doesn't - but that is an interesting idea. It could be a bit limiting, though, since handlers are often implemented as inner classes (anonymous or otherwise). The loading class would potentially have to implement a lot of interfaces, and the event handlers would be exposed as public methods (something we generally try to avoid, if possible).
> Just a suggestion...if it doesn't fit with your philosophy of how the toolkit should work, that's fine. After all, it's your project :-)
Understood. Thanks for the suggestion. :-)
Jacek Furmankiewicz replied on Mon, 2008/07/07 - 8:38am
in response to: gbrown@vmware.com
You're welcome.
I don't want to troll pushing my own project (which relies on YAML instead of XML), but just to give you a quick sample of how simple and productive signals can be:
would execute directly on the calling class without any other code needed:
You could easily do something like this in your XML markup. Does it handle all scenarios? No. Does it handle 80% of the most common ones...probably yes. If you have a good solution that follows the 80/20 rule then it's a valuable addition IMHO.
Greg Brown replied on Mon, 2008/07/07 - 8:54am
in response to: Jacek
> You could easily do something like this in your XML markup...If you have a good solution that follows the 80/20 rule then it's a valuable addition IMHO.
Agreed. The ability to hook up event handlers in WTKX will probably be a common request - something like your solution may well work for us.
Jacek Furmankiewicz replied on Mon, 2008/07/07 - 9:09am
in response to: gbrown@vmware.com
Well, it's really a GTK+/Qt solution...I just pinched it from them and made it Java-specific. Gotta give credit where it's due.
P.S. The tricky part is passing event-specific arguments to the method (e.g. FocusListener vs ActionListener), since it may be needed sometimes. You can't always assume everyone will want a zero-arguments method. But if you manage to figure it out in the context of your project, it would be well worth it.
P.S.S. If I have the time (which unfortunately I don't) I may be able to write a PivotBuilder for you using the same reusable engine I have for the SwingBuilder, since I already handle most of these issues in a domain-generic way...ah, if only the day had 30 hours instead of 24.
P.S.S.S. Beg Mikael Grev to write a version of MigLayout for Pivot. :-)
MigLayout is worth its weight in gold.
Gregg Bolinger replied on Mon, 2008/07/07 - 8:22pm
Jacek Furmankiewicz replied on Tue, 2008/07/08 - 2:51am
in response to: gb24413
Ah, if Java only supported embedded free-form text in .java files (no need for external XML or YAML files then). I hear something like this was coming in Java 7, but who knows what will make it in there since all the senior Sun engineers seem to be wasting their valuable time on JavaFX instead.
It kills me that Java is missing such basic things as integrated data binding and properties (Beans Binding blows, I know...I've implemented support for it...you need more code to support bindable properties than the code they supposedly replace)...and yes JavaFX was able to get it added with Chris Oliver working on it in his spare time. To make it worse, the main guy in charge of new Java 7 features is moving away from properties:
http://blogs.sun.com/abuckley/en_US/entry/properties_in_java
Wake up, Alex...properties NEED to be added to Java, but instead of simple get/set replacements they need to have automatically integrated support for firePropertyChange(), so no one should ever need to call it manually. And binding should be integrated right into the language instead of being a clumsy separate library.
Look how simple data binding is in Flex with their annotated variables (even less than properties):
That's literally 1 line of code for an annotation ([Bindable]). In Java to support Beans Binding JSR 295 it's nearly 20 lines, since you need to add PropertyChangeSupport to every bindable class and property.
And Sun is wasting valuable limited resources on JavaFX and moving away from enhancing the core Java languag to keep up the competition? This is one of the most illogical things I've ever seen done by an IT corporation.
Greg Brown replied on Tue, 2008/07/08 - 8:49am
in response to: Jacek
In Pivot, property binding like this is handled by the (pivot.collections) Map interface, which fires change events via the MapListener interface. This allows you to treat a statically typed Java object like a dynamically typed JavaScript object, as long as it implements Map. It requires some glue code to map property keys to getters and setters, but it works well. It's a little easier for Flex to support this since ActionScript objects are already dynamically typed.
In WTKX, you can achieve something similar to your Flex example using markup like this:
<Label textKey="labelText"/>
The data binding section of the Quick Start tutorial talks about this in more detail. I'll be publishing it as an article on Javalobby soon:
https://pivot.dev.java.net/nonav/tutorials/stocktracker.data_binding.html
Jacek Furmankiewicz replied on Tue, 2008/07/08 - 9:09am
in response to: gbrown@vmware.com
[quote=gbrown@vmware.com]It requires some glue code to map property keys to getters and setters[/quote]
That's exactly the issue I have in general...glue code needs to be added to each getter/setter and potentially even the class. I would love it just to work out-of-the-box without the need for extra glue code...I'm dreaming in technicolor, I know...