-
Notifications
You must be signed in to change notification settings - Fork 18
CodeRADEvents
CodeRAD apps are event-driven. Events are used for most communication between loosley-coupled components. Some events originate from the user via interaction with the view. Such events are dispatched and propagated up the controller hierarchy until it is either consumed or it reaches the top of the hierachy (i.e. the application controller).
The following diagram depicts this flow in a scenario where the originating UI component doesn’t have a dedicated ViewController. In this scenario a user event occurs, so the event propagates up the UI hierarchy until it reaches the Form, which has a FormController
, so the event is passed to that FormController, which processes it and passes it to its parent controller, which is the ApplicationController.
Note
|
In this diagram we know that none of Containers in the "up-line" between the Component and the Form have a registered ViewController, because if one had, then the event would have been passed to that view controller first, rather than propagating directly to the FormController. |
The next digram shows a more complex scenario where the UI component has its own ViewController.
In this case the event is passed to the component’s ViewController first. It processes the event and passes it up to the FormController, which processes it and propagates it up to the ApplicationController.
Note
|
If the event had been consumed at any step, the propagation would be cancelled. E.g. If the ViewController had consumed the event, then it would not be passed to the FormController for processing. |
The next example adds an additional FormController to the navigation stack. In this case, the event will propagate up through the FormController’s parent FormController before it reaches the ApplicationController.
The most common type of event is one that is triggered by an Action. CodeRAD provides special support for this type of event. See Actions for more information about Actions.
Tip
|
This section describes handling events that do not originate from an action. For action event handling see Actions. |
The most direct way to handle events is to override the actionPerformed() method of a controller. A typical pattern is to check for a particular type of event, and then handle it.
The following is a sample from the Tweetapp demo’s application controller:
public void actionPerformed(ControllerEvent evt) {
with(evt, StartEvent.class, startEvent -> {
if (!startEvent.isShowingForm()) {
startEvent.setShowingForm(true);
if (lookup(TweetAppClient.class).isLoggedIn()) {
new HomePageController(this).show();
} else {
new WelcomePageController(this).show();
}
}
});
super.actionPerformed(evt);
}
Tip
|
This snippet uses the NonNull.with() method, which checks if the evt object is an instance of StartEvent, and, if so, calls the provided callback. |
In the above snippet, we handle the StartEvent, which is triggered when the app starts or resumes from the background.
Important
|
Notice that the call to super.actionPerformed(evt) occurrs at the end of the method. This ensures that we process the event before it is propagated up to the parent controller in the hierarchy.
|
You can also handle events using the addEventListener() method.
For example, we could rewrite the above snippet without overriding the actionPerformed()
method as follows:
@protected
void onStartController() {
// The onStartController() method is run when the controller
// is started. This is a good place to add event listeners.
super.onStartController();
this.addEventListener(evt -> {
with(evt, StartEvent.class, startEvent -> {
if (!startEvent.isShowingForm()) {
startEvent.setShowingForm(true);
if (lookup(TweetAppClient.class).isLoggedIn()) {
new HomePageController(this).show();
} else {
new WelcomePageController(this).show();
}
}
});
});
}
Tip
|
In the above snippet we override the onStartController() method of the controller, which is run when the component is started. This is a good place to add things like event listeners.
|
The easiest way to dispatch an event is using the ActionSupport.dispatchEvent() method. This method will use the event source to determine the target Controller for the event, and deliver it there. Once delivered to the Controller, the event will be processed and propagated up the hierarchy until it is either consumed or it reaches the top.
Button back = new Button();
FontImage.setIcon(back, FontImage.MATERIAL_ARROW_BACK_IOS, -1);
titleBar.add(BorderLayout.WEST, back);
back.addActionListener(evt->{
evt.consume();
ActionSupport.dispatchEvent(new FormController.FormBackEvent(back));
});
The event system is extensible, and is intended to make it easy to add your own event types. See the ControllerEvent javadocs for a list of core event types. They are listed in the Direct known subclasses.
Some common core event types include:
- InitEvent
-
Triggered when the app is first launched.
- StartEvent
-
Triggered when the app is launched (after the InitEvent), or resumed (i.e. returns from the background).
- StopEvent
-
Triggered when the app is stopped or paused (sent to background).
- DestroyEvent
-
Triggered when the app is destroyed.
- FormBackEvent
-
Triggered when a "back" button is pressed. This is handled by the nearest FormController to the event site.
- FormShownEvent
-
Triggered when the FormController’s Form is shown.
- ExitSectionEvent
-
Triggered when request is made to "exit" the current section of the app. Typically in response to a button. This is handled by the AppSectionController, and usually navigates back to the nearest FormController that is a parent of the AppSection.