package org.j3de.events;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.PickShape;
import javax.media.j3d.SceneGraphPath;
import org.j3de.behavior.FocusAware;
import org.j3de.behavior.FocusEvent;
import org.j3de.behavior.FocusListener;
import org.j3de.events.J3deFocusListener;
public class EventDispatcher {
private BranchGroup root;
private List focusAwareList;
public EventDispatcher(BranchGroup root) {
this.root = root;
focusAwareList = new Vector();
}
public void addFocusAware(FocusAware focusAware) {
focusAwareList.add(new EventDispatcherFocusListener(focusAware));
}
public void removeFocusAware(FocusAware focusAware) {
// This only works, becaue EventDispatcherFocusListener overrides Object.equals(Object obj)
int index = focusAwareList.indexOf(focusAware);
EventDispatcherFocusListener eventListener = (EventDispatcherFocusListener)focusAwareList.get(index);
eventListener.deactivate();
focusAwareList.remove(index);
}
public void addEventSource(EventSource source, int focusAware) {
EventDispatcherFocusListener eventListener = (EventDispatcherFocusListener)focusAwareList.get(focusAware);
eventListener.addEventSource(source);
}
public void removeEventSource(EventSource source, int focusAware) {
EventDispatcherFocusListener eventListener = (EventDispatcherFocusListener)focusAwareList.get(focusAware);
eventListener.removeEventSource(source);
}
/** Implements event dispatching for a single FocusAware */
private class EventDispatcherFocusListener implements FocusListener, J3deEventDispatcher {
private FocusAware focusAware;
private Map focusedListeners;
private List eventSources;
private boolean activated;
public EventDispatcherFocusListener(FocusAware focusAware) {
this.focusAware = focusAware;
this.eventSources = new Vector();
this.focusedListeners = new HashMap();
this.activated = true;
focusAware.addFocusListener(this);
}
public void deactivate() {
focusAware.removeFocusListener(this);
activated = false;
}
private void addListeners(Object listener) {
if (listener == null)
return;
// Get all interfaces listener implements
Class listenerclass = listener.getClass();
while (listenerclass != Object.class) {
Class[] interfaces = listenerclass.getInterfaces();
// find all interfaces that extend EventListener. If a listener
// interface is not contained in focused Listeners add it
for (int i=0; i
if (EventListener.class.isAssignableFrom(interfaces[i])) {
if (!focusedListeners.containsKey(interfaces[i])) {
System.out.println("Adding listener " + interfaces[i] + " : " + listener);
focusedListeners.put(interfaces[i], listener);
}
}
}
listenerclass = listenerclass.getSuperclass();
}
}
public void focusChanged(FocusEvent event) {
SceneGraphPath scp = root.pickClosest(event.getPickShape());
// inform component, that it looses focus
J3deFocusListener focusListener = (J3deFocusListener)focusedListeners.get(J3deFocusListener.class);
if (focusListener != null)
focusListener.focusLost();
// create a new empty listener map
this.focusedListeners = new HashMap();
if (scp != null) {
// Add listeners of the picked nodes user data
addListeners(scp.getObject().getUserData());
// Add listeners from all nodes in SceneGraphPath, begin with
// the node nearest to the picked node
for (int i=scp.nodeCount()-1; i>-1; i--) {
addListeners(scp.getNode(i).getUserData());
}
}
// inform component, that it gains focus
focusListener = (J3deFocusListener)focusedListeners.get(J3deFocusListener.class);
if (focusListener != null)
focusListener.focusGained();
}
public void addEventSource(EventSource source) {
source.addJ3deEventDispatcher(this);
}
public void removeEventSource(EventSource source) {
source.removeJ3deEventDispatcher(this);
}
public void dispatchEvent(J3deEvent event) throws EventDispatcherDeactivatedException,
InvalidListenerInterfaceException {
// only dispatch events if activated
if (activated) {
// get the listener interface the event wants to dispatch to
Class interfaceclass = event.getListenerInterface();
// interface has to be a EventListener interface
if (!EventListener.class.isAssignableFrom(interfaceclass))
throw new InvalidListenerInterfaceException(interfaceclass.getName() + " is not of type java.util.EventListener");
// look up the current active listener
EventListener focusedListener = (EventListener)focusedListeners.get(interfaceclass);
// if there is a listener registered : dispatch the event
if (focusedListener != null)
event.dispatch(focusedListener);
} else
throw new EventDispatcherDeactivatedException("EventDispatcher has been deactivated");
}
public boolean equals(Object obj) {
if (obj instanceof FocusAware)
return focusAware.equals(obj);
else
return super.equals(obj);
}
}
}