Gooey Event Proxy
In the Gooey MvnC prequel, we consider an MVC-type separation for programming a Swing UI panel, and convention-over-configuration to automate events, threading and beans binding.
Now as an illustration of the above intent, we implement a minimalistic helper class to create dynamic proxies for event listeners wired to event handler methods in our controller.
A part of "Gooey Beans, part of a trilogy in 42 parts"
In our controller, we implement event handler methods as follows.
Our helper creates dynamic proxies as event listeners
registered on our components, as follows.
where our GEventProxy below will invoke methods in our controller
eg. usernameFocusLost() when focusLost() is invoked on a proxy listener
registered on a component named "username".
Salient Samples
public class LoginController implements GEventController {
LoginView view = new LoginView();
LoginModel model = new LoginModel();
GEventHelper eventHelper = new GEventHelper(this, view, model);
...
void usernameFocusLost() {
... // check that username is valid
}
void cancelActionPerformed() {
... // handle cancel button pressed
}
SwingWorker okActionPerformed() {
... // worker for OK button pressed to login
}
}
public class GEventHelper {
protected GEventController controller;
protected Map<Field, Component> components = new HashMap();
protected Map<Component, GBeanProperty> bindings = new HashMap();
public GEventHelper(GEventController controller, Component view, GBean model) {
this.controller = controller;
initComponents(view); // populate components map
bind(model); // create bindings/listeners
connectController();
}
...
public void connectController() {
for (Component component : components.values()) {
if (GInputComponentAdapterFactory.isInputComponent(component)) {
GInputComponentAdapterFactory.create(component).addActionListener(
(ActionListener) createListenerProxy(component,
ActionListener.class));
GInputComponentAdapterFactory.create(component).addFocusListener(
(FocusListener) createListenerProxy(component,
FocusListener.class));
... // other events
}
}
}
protected Object createListenerProxy(Component source, Class listenerType) {
return Proxy.newProxyInstance(
source.getClass().getClassLoader(),
new Class[]{listenerType},
new GEventProxy(controller, source));
}
...
}
public class GEventProxy implements InvocationHandler {
...
protected void invoke(Method method, Object[] args) {
for (Method eventMethod : eventMethods.values()) {
if (eventMethod.getName().equalsIgnoreCase(
component.getName() + method.getName())) {
invokeHandler(eventMethod, args);
break;
}
}
}
}





