|
Introduction: the spark that lit the whole thing
So I happened to pass by Michael Yuan's Java blog where I could read:
@SwingAsynch
private double getPayment (...) {
// Takes a long time to return
}
And, to be honest, I liked the idea of using annotations for thread
programming in Swing. So I decided to build a simple research, experimental,
project to be able to do that too. I'll call it UITopics.
Now to do thread programming in Swing I can write something like this:
@TopicListener( topicName="application/compute", isAsynchronous=true )
public void doSomething( TopicManager aTopicManager, ActionEvent anEvent )
{
// Takes a long time to return
}
Well, it's not exactly the same, but it's somewhat more flexible and powerful.
So let me explain how to use UITopics (and, please, if you've feedback on this
I'll greatly appreciate hearing from you).
Talking topics: What topics are
The whole idea of UITopics is talking topics. Topics are just strings of
your liking. Say "application/compute" or "application/fatalErrors" or
"application/log" or "Java is cool!!" or whatever other string you may
think of.
The idea is to deliver events through topics. Either Swing events or
any other events of your liking (as far as they extend java.util.EventObject).
Note that sending events through topics (and queues) is nothing new in UI programming.
Dave Walend's SomniFugi, for instance, just
does that (and many other things), too, by exposing a JMS interface for GUI programming.
Talking topics: What topic listeners are
And the idea is also to receive events using topic listeners.
Topic listeners are any sort of Java object of your liking.
The only requirements needed to build a topic listener are:
- At least one method must be tagged with the @TopicListener annotation.
- The first argument must be a TopicManager.
- The second argument must be an event. Any event. (Say ActionEvent,
WindowEvent, EventObject, MouseEvent).
So, for instance, this is a valid topic listener:
public class MyClass
extends WhateverOtherClass
implements WhateverYouWantInterface
{
@TopicListener( topicName="application/errors" )
public void whateverMethod( TopicManager aTM, ActionEvent anAE )
{
System.out.println("An error was received");
}
@TopicListener( topicName="application/eventlog", isAsynchronous=true )
public void logEvent( TopicManager aTM, EventObject anEvent )
{
System.out.println("Event: " + anEvent
+ " received through topic : application/eventlog." );
}
}
So this basically means that:
- ActionEvents coming through topic "application/errors" will
be processed in the Swing thread by the method "whateverMethod".
- Any event coming through topic "application/eventlog" will
be processed in a worker thread (isAsynchronous=true) by the method
"logEvent".
Well, you have to tell a TopicManager which instances of the
MyClass class will receive events. I mean, events are not delivered
automagically to all MyClass instances, you have to specify which
instances will receive events. By using code like this:
TopicManager tm = new TopicManager();
MyClass myInstance = new MyClass();
MyClass anotherInstance = new MyClass();
tm.addTopicListener( myInstance );
And, of course, events from that topic manager will only be sent
to the "myInstance" instance, and not to "anotherInstance" (because
that was not added as a listener).
I know this is a little bit weird and that I don't explain myself
too well. But take it easy with me and keep reading. It takes a little
time to change paradigms. I'll show a whole example below, later on.
Talking topics: sending events
So, who sends events to topics? How is this done?. I thought of
two ways to send events: using Swing components and doing it by hand.
Sending events with Swing components
Say you have a JButton and you want it to deliver ActionEvents and
MouseEvents through the "application/eventlog" topic. This is done
by writing:
JButton myButton = new JButton("Press me");
TopicManager tm = new TopicManager();
tm.addEventSource("application/eventlog", myButton,
ActionListener.class, MouseListener.class );
This basically means that all ActionEvents and MouseEvents
generated by the button are automatically routed to
all topic listeners listening on the "application/eventlog"
topic.
Not too difficult. Note though that you use "Listeners"
(i.e., "ActionListener.class, MouseListener.class") and not
events (i.e., not "ActionEvent.class, MouseEvent.class").
(I may be able to correct that in the future, but it's good
for me, anyway).
Sending events by hand
If you have a TopicManager at hand you may send events to
topics yourself. Like this:
TopicManager tm ...
tm.sendEvent( "application/events", new ActionEvent(...) );
That event will be posted to all topic listeners listening
for ActionEvents on topic "application/events".
Summary
So, to summarize (clarify?) UITopics looks like this:
So, where is the source for this?
Well, I'm still entering it at Java.net (I hope they approve the project).
As soon as they approve it I'll post it for you to play with.
Happy Swinging meanwhile,
Antonio
|