Libglade needs to map signals to event listener classes on a per-class
basis. To avoid developing a separate table for these mappings (which
makes maintenance harder), I have augmented the information already in
the classes which handle events (if you can think of a better way,
please let me know). Note: this change doesn't affect any public API,
nor how event handling is actually managed.
Currently, classes which handle events all have a protected method
called initializeEventHandlers(). Each class implements this as:
protected void initializeEventHandlers() {
super.initializeEventHandlers(); // optional
addEventHandler(<signal>, <handler>, this);
addEventHandler(<signal>, <handler>, this);
// etc.
}
Although no map object is actually used, these addEventHandler
statements provide the mapping I need to extend. This is done by
creating a private static EventMap instance and storing this information
plus the event listener class in it. The above code then looks like:
protected void initializeEventHandlers() {
evtMap.initialize(this);
}
private static EventMap evtMap = new EventMap();
static {
evtMap.addEvent(<signal>, <handler>, <listener_class>);
evtMap.addEvent(<signal>, <handler>, <listener_class>);
// etc.
}
public static String getListenerClass(String signal) {
return evtMap.getListenerClass(signal);
}
The EventMap class looks like this:
/*package-private*/class EventMap {
private List events = new ArrayList();
private class Entry {
String signal;
String method;
String listenerClass;
Entry(String s, String m, String l) {
signal = s;
method = m;
listenerClass = l;
}
}
void addEvent(String signal, String method, String listenerClass) {
events.add(new Entry(signal, method, listenerClass));
}
/**
* Connect all event handlers to this event source.
*/
void initialize(GObject source) {
Iterator i = events.iterator();
while (i.hasNext()) {
Entry e = (Entry)i.next();
/* All GTK addEventHandler calls specify source twice
* (the object being invoked and as a cbrev parameter).
* This should probably be eliminated to for performance.
*/
source.addEventHandler(e.signal, e.method, source);
}
}
/**
* Return the name of the event listener class for a given signal.
*/
String getListenerClass(String signal) {
Iterator i = events.iterator();
while (i.hasNext()) {
Entry e = (Entry)i.next();
if (e.signal.equals(signal))
return e.listenerClass;
}
return null;
}
}
Yes, it is called a Map but uses a List, but that doesn't matter because
the List and its interface is completely private. If this impacts
performance in any way, it can be changed later to be an array. I chose
to make initialization faster than listener lookup, since there are
going to be a lot more widget creations than libglade lookups.
If no one complains in a day or so, I'll check these in.
Tom
|