GWT Tk Controller Design

Nov 14, 2006by Mat Gessel

Introduction

I've been exploring a different way to handle events in GWT. In a nutshell, the design combines traits of Swing event handling and classic MVC controllers.

This all began when I encountered the following problems:

  1. different platforms require different event handling
  2. event handlers need access to event objects (e.g. for preventDefault() & stopPropagation())

Analysis

Browser specific event handling

In GWT, the basic recipe for accommodating browser differences is to delegate variations in code to "impl" classes. When you need to handle variations in behavior you can delegate events to the impl classes. If you have two widgets that require the same event handling you can create a class encapsulating the behavior and delegate events to it from the impl classes, e.g. Widget.onBrowserEvent() -> WidgetImplMozilla.doEvent() -> BehaviorImplMozilla.doEvent(). After coding this delegation pattern several times will want to add delegation support to a base class to limit code duplication.

DOM event object access

GWT event interfaces do not provide access to the event objects. I am unsure whether this was a design goal, or just a side-effect of keeping the design simple. Some classes (e.g. TextBoxBase) provide methods to act on the current event to address anticipated needs (e.g. cancelKey(), setKey()). However, GWT does not meet all the needs of users (e.g. canceling a "Tab" keypress on a button).

Approaches to access event objects:

  1. Modify the source for listener collections and listener interfaces to expose the events.
    Requires continual maintenance as GWT is released.
    Limits reuse in the GWT community.
  2. Subclass the widget and move listener code into onBrowserEvent().
    Results in a proliferation of classes.
  3. Create duplicate listener interfaces which expose the event object; subclass widgets as needed to add extended event listener support.
    Results in a proliferation of classes.
    If you need to handle additional event types on a 3rd party widget that employs this approach you have to subclass again or modify the source.
  4. Create a generic event listener facility which exposes the event object and notifies for all event types. Rather than create a listener interface with a method for every possible event, you can declare a generic onBrowserEvent() handler. The widget class can ask the listener which events it is interested in and only notify for those events. Switching on the event type in the listener.onBrowserEvent() method can be lessened by creating a separate listener for each event type.

Design

This design combines traits of Swing event handling and classic MVC controllers.

Class responsibilities

Widget

Controller

Structural overview (click to zoom)
Structural Overview

Design features and details

Static structure (click to zoom)
Static Structure

Controller instantiation (click to zoom)
Controller Instantiation

Controller activation (click to zoom)
Controller Activation

Event processing (click to zoom)
Event Processing

Consequences

Legacy event support (click to zoom)
Legacy Event Support

Looking Forward

Controller injection

It may be possible to write a custom generator which parses annotations in the class doc and injects a controller into the generated class. Widgets would be instantiated via GWT.create(). Controllers typically have a default constructor.

Legacy listener implementations could also be injected this way. The listener interface would be inherited, but not implemented (the class would be abstract).

Resources

Discussion in GWT group