Package talx
The Think-and-Link project provides an email client aimed at people with aquired cognitive deficits.
See:
Description
|
Class Summary |
| Email |
Creates the user interface and transport system. |
Package talx Description
The Think-and-Link project provides an email client aimed at people with aquired cognitive deficits.
The Think-and-Link system architecture is divided into the following:
- Model
- View
- Controller
- Features
The Controller
The controller is encapsulated in the controller package and all of its
sub-packages. The controller provides the basic behavior for the system.
The Model
The model is encapsulated in the model package and all of its sub-packages.
The model consists of the following APIs:
- The model API
- The message pipeline API
- The persistant store API
The Message Pipeline API
The message pipeline API is encapsulated in the model.filters package.
The message pipelines are created by stacking incoming filters or
outgoing filters.
The Persistant Store API's
The Game Store is handled in the model.GameManager class, while the
Message Store is accessed through the model.TransportToolkit class.
The transport toolkit uses the tal store protocal,
encapsulated in the model.store package.
Additionally, the model.mail package contains classes that interface
between the toolkit and the message store.
The View
The view consists of the application desktop containing five top level
components:
- Inbox
- Reader
- Composer
- Dialogs
- Games
Desktop
The desktop is encapsulated in the view package. That package contains
general support for the think-and-link frame and the interfaces
for the top-level components. Components that maintain the tal look-and-feel
are found in the view.components package. Top level components should
use subclasses of these components rather than their swing counterparts.
Inbox
The inbox is encapsulated in the view.inbox package.
The inbox presents the user with information about the messages available
in the store.
Reader
The reader is encapsulated in the view.reader package.
The reader allows the user to read a MimeMessage.
Composer
The composer is encapsulated in the view.composer package.
The composer allows the user to compose a message.
Dialogs
The dialog system uses the view.DialogManager class and the
related frame and dialog subclasses.
The dialog system provides confirmation dialogs and system status messages.
Games
The games system is encapsulated in the games package.
The games system provides access to play-by-email two-player games.
Features
Features can contain elements to perform the following functions:
- Generate actions from raw input gestures through the AWT event listener API
- Respond to generated actions by linking into the controller's chain of responsibility
- Control desktop marques through the desktop's marque API
- Respond to system state changes through the controller listener interface
- Filter incoming and outgoing messages through the model.filter API
Communication
Think and link has rigidly defined methods of communication between components.
It is a violation of the think and link specification to use communication methods
outside of the allowable methods.
The runtime control-flow diagram is shown below.
The black arrows indicate communication through class API's.
The colored arrows represent event listener communication:
- Orange -
The orange arrows from the settings object indicate calls to the settings API.
These are colored because the settings objects are immutable, so the communication
has the flavor of event listener, where the event occurs at startup only.
- Blue -
The blue arrows represent the filter listeners. A feature can subscribe to the
last incoming filter or the last outgoing filter. Thus, a feature (unless it is
also a filter) cannot filter messages, but it can hear messages coming and going.
- Yellow -
The yellow lines represent the store listeners. These represent actions on messages.
- Green -
The green lines represent action events. In general, the controller will only hear
actions that are delivered via the ActionDispatcher object.
- Red -
The red lines represent controller listeners. All classes that are created in the
start-up sequence (or in a game initialization sequence)are automatically
subscribed to the controller. Since access to the controller is restricted, the
only way to hear controller events is by implementing controller listener as a
class that gets gets constructed in the start-up sequence.
- Purple -
The purple lines represent AWT event listeners. The think-and-link system does not
provide direct support for listening to raw input, so features that rely on this
must use the AWT event listener support mechanisms.
Controller-View Communication
When the controller is created, it automatically registers all top-level view objects
as controller listeners. Also, any features that implement the controller
listener interface are automatically subscribed.
Communication between the view and the controller must
be in the form of a change to the GUIState model object which is broadcast through
a controller change event. View objects are expected to react only to controller
change events and not to react to other controller events. The controller should
be able to beleive that once a controller change event has occured and the controller
has been synced, the view components accurately conform to the new GUIState.
The view components do not communicate with the controller directly. However, the
user uses the view components to communicate with the controller through action events.
Therefore, it is the responsibility of every top-level view component to register all
user input controls as action generators with the ActionDispatcher. This allows pass-through
of user actions to the controller.
Controller-Model Communication
The currently valid visual model is kept in the controller. The object itself is
immutable, but the controller replaces it as necessary and broadcasts the change
to all controller listeners. The controller freely uses the model's API
to manipulate the message and game stores and send and retreive messages.
The model can also communicate with the controller via action events.
For example, the transport toolkit sends action events whenever the
store contents change, and the command filter in the model's incoming message
pipe converts remote game moves and test commands to action events.
View-Model Communication
The view components automatically receive updated visual models from the controller.
It is a violation of the think and link specification for the view to attempt to
use the model's transport API to send messages directly.
Thus, information can only pass from the model into the view, and not the other
way around.
At system startup, the settings object is available to all components. Changing
the settings object is not a reliable form of communication because components
may decide to cache the individual settings as an implementation detail.
So, the settings object should be considered read-only by any system component.
Feature-Controller Communication
Features can register as action generators with the action dispatcher. When a feature
generates an action event, that event will be dispatched to the controller which can
choose to act on it or not. features can generate events based on anything, including
tapping into raw user input, observing visual model changes, observing message transport
events, timers, or any other internal or external event. Due to the dynamic nature
of feature loading, the controller should not attempt to detect the presence of any
particular feature. Thus, feature-controller communication is purely passive in both
directions.
Features that want to hear changes in the visual model, can implement the controller
listener interface. Features that implement controller listener will automatically
be subscribed to the controller when they are created. The controller listener
interface allows the feature to react to purely visual changes through the controller
change events or to logical state changes through the change finished event.
It is a violation of the spirit of the think and link system for features to intuit
state changes based on user actions.
Additionally, components in the controller can place objects in the visual model that
a particular feature may be expected to utilize. In general, such communication is
in the form of an interceptor communicating with itself. An interceptor is a feature
that also resides in the controller.
(See the controller package description for more information about interceptors.)
Feature-Model Communication
Features can utilize the model's transport API in any way available. Due to the dynamic
nature of feature loading, the model should not attempt to detect the presence of any
particular feature. Thus, the feature-model communication is entirely one-way.
In particular, features may want to monitor store changes by becoming a model store
listener.
Feature-View Communication
Communication between feature and view components is prohibited. Features that provide
additional visual information, must use the marque API provided by the desktop object.
This API does not allow the feature to directly manipulate the marque. Rather, such
features should be realized as interceptors and change the marque's text key in the
model in response to their own actions.
Feature Example
Suppose you are developing a help feature that suggests to the user that they do not
include more than 2 spaces in a row.
The feature would implement the interceptor and controller listener interfaces.
Then, the feature could implement the following use case:
- In the constructor, the feature registers as an AWTEventListener in the AWT system.
- Also in its constructor, the feature obtains a marque key from the desktop.
- The feature's eventDispatched method hears a consecutive third space has been typed.
- The feature sends an "unwelcome space" action command to the ActionDispatcher.
- The action is passed through the controller's chain of responsibility and gets to
the feature's claim() method.
- The claim method changes the GUIState to associate the marque key with the text
"Oops, you have extra space", fires a controller change for the visual component,
and claims the action.
- Later, the user sends or cancels the composition.
- The feature's controllerChangeFinished method sees that the COMPOSE_WINDOW flag has been reset
- The controllerChangeFinished method fires a "clear unwelcome space" action command.
- The action is passed through the controller's chain of responsibility and gets to
the feature's claim() method.
- The claim method associated null with the marque key in the GUIState,
fires a controller change for the visual component, and claims the event.
- The marque sees a null value for its key and hides itself.
This level of communication is necessary because when the feature hears the third
space, it cannot be privledged with respect to the Controller object, but it does
enjoy exclusive use of the controller API when its claim() method is called.
Hence, the call-back mechanism must be used as described.
Start-Up Sequence
The Think-and-link system goes through the following steps when the Email constructor is called:
- The Settings file is located and the settings object is created.
Failure of this step results in system failure.
- The transport toolkit object is created and the local message store is openned.
Failure of this step results in system failure.
- The game manager is created and the players are checked for uniqueness.
Failure of this step results in system failure.
- The view is created:
- The main frame is created.
- The custom cursors are created (loaded from the image files)
- The set of subcontainers is created: Right, Left, Desktop (Center) and Marque holders.
- The top level components are dynamically created from the settings object.
- The main frame is made visible.
Failure of this step results in system failure.
- The controller is created and passes a reference for itself to the desktop.
This allows the desktop's marque API to deliver marques that are subscribed to the controller.
Failure of this step would result in system failure, but could only be caused by a null desktop.
- The system begins monitoring for the main frame to close.
If the frame closes, then the shutdown sequence will begin
as soon as the start-up sequence has ended.
Failure of this step does not result in system failure.
- The outgoing filter stack is dynamically created from the settings object.
The outgoing filters have the following constructor parameters avaialable:
the transport toolkit, the game manager, the view desktop and their parameter string.
Failure of this step does not result in system failure.
- The incoming filter stack is dynamically created from the settings object.
The incoming filters have the following constructor parameters avaialable:
the transport toolkit, the game manager, the view desktop, the last outgoing filter
and their parameter string.
Failure of this step does not result in system failure.
- The features are dynamically created from the settings object.
The features have the following constructor parameters avaialable:
the transport toolkit, the game manager, the view desktop,
the last outgoing filter, the last incoming filter and their parameter string.
Failure of this step does not result in system failure.
- The outgoing filter objects are searched for
interceptors, controller listeners and delayed features.
Interceptors are placed in the controller's chain of responsibility.
Controller listeners are subscribed to the controller events.
Delayed features are initialized.
- The feature objects are searched for
interceptors, controller listeners and delayed features.
Interceptors are placed in the controller's chain of responsibility.
Controller listeners are subscribed to the controller events.
Delayed features are initialized.
- The incoming filter objects are searched for interceptors and controller listeners.
Interceptors are placed in the controller's chain of responsibility.
Controller listeners are subscribed to the controller events.
- The controller is initialized:
- The controller attempts to restore the state from the user's state file.
This may fail because the state file is missing.
This may also fail because there is a lock file in the user's directory,
in which case the controller assumes previous catastrophic failure and aborts
the attempt to restore the state.
This may also fail due to a missing message in the store.
If this step fails for any reason, the controller dynamically loads
the initial handler class from the settings and uses the handler to generate
a new initial state.
Failure of this step results in system failure.
- The lock file is created in the user's directory.
- The controller sends out the gui state to all listeners.
- The controller creates a new command interceptor and places it in the
controller chain of resposibility.
- The controller registers itself with the action dispatcher and starts the controller thread.
- The incoming filter objects are searched for delayed features.
Delayed features are initialized.
- The thread waits for a signal from the shut-down sequence.
Shut-Down Sequence
The Think-and-link system goes through the following steps when it detects the main frame closing:
- It waits for the start-up sequence to end.
If the startup sequence does not seem to be ending, the shut down sequence begins.
- The incoming filter stack objects are released from first to last.
- The action dispatcher is cleared (ie, its reference to the controller is removed).
- The outgoing filter stack objects are released.
- The feature objects are released.
- The message store is closed.
- The start-up thread is signalled to return control to the calling program.
Note that the Email constructor blocks until the entire system has been disposed.
That is, creating a new Email object causes the object to be born, live and die
before the call returns.
- Author:
- Jim Allen, Andrew Fourtier, Harrison Green-Fishback, Jason Prideaux
© 2001-2005 University of Oregon.
Eugene OR 97403, U.S.A. All Rights Reserved.