![]() ![]() ![]()
|
SophiaFramework UNIVERSE 5.1 |
Responder system has important features such as responder tree, responder space, event handling, or rendering.
In this section, these features of the responder system are described.
Reference: Elements of the Responder System
Responder tree is a tree structure for managing responders.
The responder located at the top of the responder tree is called "root responder".
If a root responder is bound with a distributer and a renderer, each responder of its responder tree can receive an event and draw itself on the device screen.
![]() |
Root |
|---|---|
SFYApplication contains the root(SFZRoot) bound with a renderer and a distributer as a default root responder. | |
![]() |
CAUTION |
|---|---|
Since a newly created responder has no parent responder, it is temporarily a root responder until connected to a responder tree. | |
Example 9.24. Making a responder tree
SFCError USRApplication::MakeTree(Void)
{
SFZRootSmp root;
SFZDialogSmp dialog;
SFZTextButtonControlSmp button;
SFZWindowSmp window;
SFZTextLabelControlSmp label;
SFCError error(SFERR_NO_ERROR);
// in actual applet development, making root will be omitted since default root will be used
// * default root will be automatically made in constructor of SFYApplication class
if ((root = SFZRoot::NewInstance(&error)) != null) {
if ((dialog = SFZDialog::NewInstance(&error)) != null) {
if ((error = dialog->SetParent(root)) == SFERR_NO_ERROR) {
if ((button = SFZTextButtonControl::NewInstance(&error)) != null) {
if ((error = button->SetParent(dialog)) == SFERR_NO_ERROR) {
...
}
}
}
}
if (error == SFERR_NO_ERROR) {
if ((window = SFZWindow::NewInstance(&error)) != null) {
if ((error = window->SetParent(root)) == SFERR_NO_ERROR) {
if ((label = SFZTextLabelControl::NewInstance(&error)) != null) {
if ((error = label->SetParent(window)) == SFERR_NO_ERROR) {
...
}
}
}
}
}
}
return error;
}
![]() |
CAUTION |
|---|---|
In the actual applet development using an application class inheriting from SFYApplication, since SFYApplication contains the root(SFZRoot) by default, making another root(SFZRoot) will be omitted. | |
A responder tree is drawn on the device screen in the following order relation:
![]() |
ToFront() function |
|---|---|
If the SFYResponder::ToFront function of a window which has child responders such as a button or a label is called, not only the window but also its child responders such as a button or a label will be moved foremost together. | |
Reference: Root Responder | Renderer | Distributer | Root(Basic) | SFZRoot | SFYDistributer | SFYRenderer | SFYResponder::SetDistributer | SFYResponder::SetRenderer
Responder space is a rectangular region inside the device screen to draw a responder tree bound with a renderer.
The responder space will be set in the argument of the SFYRenderer::Initialize function when the renderer is initialized.
By default, the responder space will be set to the device screen region obtained by calling the SFXDevice::GetScreenSize function.
Though a subset region of the device screen can be set as a responder space, a responder tree will be drawn only inside the responder space.
![]() |
Real region of the root |
|---|---|
|
SFYApplication contains the root(SFZRoot) as a default root responder bound with the renderer and the distributer. Though the real region of the root is equalized with the responder space in the default settings, it can be set to a region larger or smaller than the responder space. Even if the real region of the root is set to a region larger than the responder space, its responder tree will be drawn only within the responder space. | |
![]() |
Changing of the responder space |
|---|---|
Though the real region of the root can be updated dynamically, the responder space set in the initialization of the renderer cannot be changed. | |
Reference: SFYRenderer::Initialize | SFYRenderer | SFZRoot | Responder Tree | Renderer | Distributer | Root | Real Region
The abstract of how each event is handled in the responder system is as follows:
![]() |
Tip |
|---|---|
| Reference: default implementation of the SFYApplication::HandleEvent function. | |
The BREW applet(called "applet" in the below) has an event-driven mechanism, which means that an event triggered by user operation or external interruption is dispatched and handled.
From the applet boot-up to its termination, a variety of events such as bootup, termination, suspend, resume, or key are dispatched from the BREW environment to the applet.
The following figure shows a typical life cycle of an applet.
Figure 9.16. Life cycle of an applet

It is troublesome to appropriately dispatch a variety of events which the applet receives.
Since the distributer of the responder system automatically dispatches each event to appropriate handler functions, the program structure is very simple.
Immediately after a user boots up an applet, the instance of an application class inheriting from SFYApplication will be created in the applet.
The instance of an application class will make the root(SFZRoot), which is bound with a distributer and a renderer.
Next, the SFEVT_APP_START event will be dispatched from the BREW environment to the applet, and the applet initialization will begin.
![]() |
Note |
|---|---|
| Initialization processing such as creating a window is executed in the constructor of an application class or the handler for the SFEVT_APP_START event. | |
When a user terminates an applet by selecting the QUIT option in a menu or by pressing the POWER key, the SFEVT_APP_NO_CLOSE event is dispatched from the BREW environment to the applet.
When this event is received, the applet must return "false" to terminate itself(i.e., if "true" is returned, the applet will not terminate).
Then the SFEVT_APP_STOP event will be dispatched from the BREW environment to the applet, and the applet will begin to terminate.
If the SFEVT_APP_STOP event handling finishes normally, a distributer, a renderer, and responders such as a window or a root will be released, and an application class itself will be also automatically released.
![]() |
Note |
|---|---|
| Finalization such as destroying a window is executed in the destructor of the application class or the handler for the SFEVT_APP_STOP event. | |
Figure 9.18. Sequence diagram: Terminating an applet

In the above figure, the SFCApplication::Terminate function to terminate the applet will be executed after a user presses the button for termination on window(win1).
* The renderer and the root are omitted from the figure since they are hardly related with this sequence.
The tracer manages rules to dispatch an event to appropriate responders.
The default dispatching rules are registered into a distributer of the responder system as standard tracer.
If the tracer is not changed explicitly, each event will be dispatched according to the standard tracer rules. And a responder inherits the tracer rules from its parent responder.
![]() |
Customizing the standard tracer |
|---|---|
In general, the default settings are enough. There is no need to customize the standard tracer in almost all applet developments. | |
Three elements of a dispatching rule to register into the tracer are as follows:
Distributing condition
For the distributing condition, specify the state of a responder where an event will be dispatched.
One of the following can be specifiled:
The key event is dispatched to focused responders since distributing condition is set to "Focus[SFYTracer::STATE_FOCUS]".
The bootup, termination, suspend, or resume event for an applet is dispatched to all responders since the distributing condition is set to "All[SFYTracer::STATE_ALL]".
![]() |
Method to receive the BREW-defined event whose dispatching rule is registered into the standard tracer with "distributing condition: None[SFYTracer::STATE_NONE]" |
|---|---|
|
The BREW-defined event whose dispatching rule is registered into the standard tracer with "distributing condition: None[SFYTracer::STATE_NONE] will be distributed to no responder including the root(SFZRoot) which the SFYApplication class contains by default. This is because the rules of the standard tracer are registered into the SFYDistributer instance. To receive this event, you have to register its handler directly into the SFYDistributer instance as follows:
| |
Figure 9.19. SFEVT_KEY event: Distributing condition

The SFEVT_KEY event is dispatched to focused responders.
Figure 9.20. Dispatching the SFEVT_APP_RESUME event

The SFEVT_APP_RESUME event is dispatched to all responders.
Processing order
For the processing order, specify the priority order to boot up handlers.
One of the following can be specifiled:
Overloading condition
For the overloading condition, specify whether or not the handler processes an event duplicately.
One of the following can be specifiled:
The key event is set to "from foreground to background [SFYTracer::ORDER_FORWARD]" for the Processing order. Therefore, it will be processed by the handlers of focused responders from foreground to background. If more than one handler are registered into the same responder, they will be booted up in the reverse order to be registered. Since it is set to "No" for the Overloading condition, event handling ends there if the event is handled by a handler.
The SFEVT_APP_RESUME event is set to "from background to foreground [SFYTracer::ORDER_BACKWARD]" for the Processing order. Therefore, it will be processed by the handlers of focused responders from background to foreground. If more than one handler are registered into the same responder, they will be booted up in the reverse order to be registered. Since it is set to "Yes" for the Overloading condition, the next handler, if any, will be booted up after the event is processed by a handler.
Figure 9.21. SFEVT_KEY event: Processing order and Overloading condition

The SFEVT_KEY event is processed by the handlers of focused responders from foreground to background.
Settings of the standard tracer
The standard tracer is set as follows:
Table 9.3. Standard tracer
| Event type | Distributing condition | Processing order | Overloading condition |
|---|---|---|---|
| SFEVT_APP_START | All | from background to foreground | Yes |
| SFEVT_APP_STOP | All | from foreground to background | Yes |
| SFEVT_APP_RESUME | All | from background to foreground | Yes |
| SFEVT_APP_SUSPEND | All | from foreground to background | Yes |
| from SFEVT_APP_CONFIG to SFEVT_APP_START_WINDOW | No | from foreground to background | No |
| from SFEVT_KEY to SFEVT_KEY_HOOK_RELEASE | Focus | from foreground to background | No |
| from SFEVT_COMMAND to SFEVT_CTL_TEXT_MODECHANGED | Focus | from foreground to background | No |
| from SFEVT_DIALOG_INIT to SFEVT_COPYRIGHT_END | Focus | from foreground to background | No |
| from SFEVT_ALARM to SFEVT_NOTIFY_FAILURE | No | from foreground to background | No |
| from SFEVT_FLIP to SFEVT_SCR_ROTATE | No | from foreground to background | No |
| from SFEVT_CB_CUT to SFEVT_CB_PASTE | No | from foreground to background | No |
![]() |
Warning |
|---|---|
|
A BREW-defined event or user-defined event is distributed to responders according to the tracer rules. A responder-defined event must not be distributed using the tracer. To distribute a user-defined event, register its dispatching rule into the tracer. | |
![]() |
Method to receive the BREW-defined event whose dispatching rule is registered into the standard tracer with "distributing condition: None[SFYTracer::STATE_NONE]" |
|---|---|
|
The BREW-defined event whose dispatching rule is registered into the standard tracer with "distributing condition: None[SFYTracer::STATE_NONE] will be distributed to no responder including the root(SFZRoot) which the SFYApplication class contains by default. This is because the rules of the standard tracer are registered into the SFYDistributer instance. To receive this event, you have to register its handler directly into the SFYDistributer instance as follows:
| |
Example 9.25. Registering a dispatching rule into the tracer
USRResponder::USRResponder(Void) static_throws
{
if (static_try()) {
...
static_throw(RegisterTracer(
SFXEventRange(SFEVT_KEY, SFEVT_KEY, AVK_SOFT1, AVK_SOFT4),
SFYTracer::ORDER_FORWARD, SFYTracer::STATE_ALL, false
));
...
}
}
![]() |
Tip |
|---|---|
A dispatching rule is registerred into the tracer using the RegisterTracer() function. | |
Reference 1: Distribute Type | Callback Type | Event List | BREW-Defined Event | Responder-Defined Event | Handler List | Handler | State | SFYResponder::RegisterHandler | SFYResponder::UnregisterHandler | SFYResponder::ClearHandler | SFYResponder::Distribute | SFYResponder::InvokeBackward | SFYApplication::InvokeBackward | SFYApplication::RegisterHandler | SFYApplication::UnregisterHandler | SFYApplication::ClearHandler | SFYApplication::Distribute | SFYResponder::InvokeForward | SFYApplication::InvokeForward | SFYHandler | SFXEvent | SFXEventRange
Reference 2: Distributer | Tracer | SFYResponder::RegisterTracer | SFYResponder::UnregisterTracer | SFYResponder::ClearTracer | SFYApplication::RegisterTracer | SFYApplication::UnregisterTracer | SFYApplication::ClearTracer | SFYDistributer | SFYTracer
Handler is a function which actually processes an event dispatched to a responder.
For the same event, more than one handler can be registered into the same responder.
For instance, when more than one handler are registered for the SELECT key event of SFEVT_KEY event type into window, the handler to be registered last will be booted up since its processing order of dispatching rule of the standard tracer is "from foreground to background".
If this handler returns "true", event handling will end there. On the contrary if it returns "false", the handler to be registered second-to-last will be booted up. Event handling regarding to this window continues until any handler returns "true" or there is no handler to be booted up.
![]() |
Positional relationship of the handlers |
|---|---|
The handler registered first is placed backmost, and the handler registered last is placed foremost. | |
Example 9.26. Registering a handler
USRResponder::USRResponder(Void) static_throws
{
if (static_try()) {
...
static_throw(RegisterHandler(
SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
XANDLER_INTERNAL(OnKey)
));
...
}
}
![]() |
Tip |
|---|---|
| A handler is registered using the SFYResponder::RegisterHandler function. | |
Example 9.27. Implementing a handler
XANDLER_IMPLEMENT_BOOLEVENT(USRResponder, OnKey, invoker, event)
{
switch (event.GetP16()) {
case AVK_SELECT:
TRACE("select key was pressed.");
return true;
case AVK_CLR:
TRACE("clear key was pressed.");
return true;
default:
TRACE("unknown key was pressed.");
return true;
}
return false;
}
![]() |
IMPORTANT | ||||
|---|---|---|---|---|---|
|
The handler will return "true" if the event is handled. Otherwise, it will return "false". If some handlers return "true", the responder system will boot up the renderer to redraw the responder tree if necessary.
| |||||
![]() |
Event of the callback type |
|---|---|
The event which is sent using the InvokeForward() or InvokeBackward() function is said to be of the callback type. A responder-defined event is of the callback type. | |
Reference 1: Handler | Event List | BREW-Defined Event | Responder-Defined Event | Handler List | Tracer | SFYResponder::RegisterHandler | SFYResponder::UnregisterHandler | SFYResponder::ClearHandler | SFYApplication::RegisterHandler | SFYApplication::UnregisterHandler | SFYApplication::ClearHandler | SFYHandler | SFXEvent | SFXEventRange
Reference 2: Callback Type | SFYResponder::InvokeForward | SFYResponder::InvokeBackward | SFYApplication::InvokeForward | SFYApplication::InvokeBackward
Reference 3: Distribute Type | SFYResponder::Distribute | SFYResponder::RegisterTracer | SFYResponder::UnregisterTracer | SFYResponder::ClearTracer | SFYApplication::RegisterTracer | SFYApplication::UnregisterTracer | SFYApplication::ClearTracer | SFYTracer
If the distributer finishes event handling for an event and one of handlers returns "true", the responder system will boot up the renderer to redraw the responder tree if necessary.
![]() |
Tip |
|---|---|
| For more details, see the default implementation of the SFYApplication::HandleEvent function. | |
The renderer will make the drawing event occur only in the responders to be redrawn by calculating the state and the positional relation of each responder.
In each event loop, only the necessary drawing handlers are called and executed. As a result, performance will not deteriorate even if it is complex rendering.
![]() |
Drawing of the "invisible" responder |
|---|---|
Even if contents of a responder such as a text or a color are changed during an event loop, the drawing handler of the responder, which is in the "invisible" state or hidden by other responders, will not be booted up. | |
The screen is rendered in the final stage of each event loop.
If the event handler returns "true", the distributer will boot up the renderer, which will check whether rendering regions are registered or not. At this time, the drawing event will occur only in the responders including the region to be redrawn.
If the drawing event occurs in a responder, the drawing handler to draw the responder will be booted up.
Figure 9.22. If an event is handled

If an event is handled during the event loop, the renderer will be booted up automatically.
When all handlers return "false" during the event loop or there is no region to be redrawn, the renderer will not be booted up. As a result, no responder will be redrawn.
After the SFYResponder::Render function is called, it will boot up the renderer, which will make the drawing event occur only in the responder including the region to be redrawn.
If the drawing event occurs, the handler(called "drawing handler") to redraw the responder will be booted up.
At this time, the first drawing handler to be booted up is the one registered into SFYWidget by default. This drawing handler will call the SFYWidget::HandleRenderRequest function after filling the background in the color set with the SFYWidget::SetBackgroundColor function if the transparency attribute of the responder is "false".
After this, developer's own drawing handlers, if any, will be booted up in the registered order.
![]() |
Tip |
|---|---|
| In general, drawing of a responder is described by overriding the SFYWidget::HandleRenderRequest function. | |
Example 9.28. Registering a drawing handler
// register drawing handler
USRResponder::USRResponder(Void) static_throws
{
if (static_try()) {
...
static_throw(RegisterHandler(
SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST),
XANDLER_INTERNAL(OnRenderRequest)
));
...
}
}
![]() |
Tip |
|---|---|
Since the drawing handler is a kind of handler, it is registered using the SFYResponder::RegisterHandler function. | |
Example 9.29. Implementing a drawing handler
// implement drawing handler
XANDLER_IMPLEMENT_VOIDRENDER(USRResponder, OnRenderRequest, invoker, reason, graphics)
{
graphics->FillRectangle(GetLocalBound(), SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00));
return;
}
![]() |
Tip |
|---|---|
The drawing handler will get the SFXGraphics instance as argument and draw the corresponding responder in its local region. | |
In the responder system, when redrawing of a responder is needed before the renderer is booted up, only register the redraw region with the SFYResponder::Invalidate function.
The actual redrawing is described within the drawing handler, which will be booted up at the end of each event loop.
For instance, if the text string of a label control is changed with the USRResponder::SetText() function in the code below, this label control must be redrawn since its content is updated.
Here, only register the redraw region into the renderer using the SFYResponder::Invalidate function. Drawing of the label is described in the drawing handler.
The renderer booted up will validate whether or not the redraw regions are registered until then, and call only the drawing handlers for the redraw region actually displayed on the device screen.
![]() |
Drawing of the "invisible" responder |
|---|---|
Even if contents of a responder such as a text or a color are changed during an event loop, the drawing handler of the responder, which is in the "invisible" state or hidden by other responders, will not be booted up. | |
Example 9.30. Registering the redraw region
// register drawing handler USRResponder::USRResponder(Void) static_throws { if (static_try()) { ... static_throw(RegisterHandler( SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST), XANDLER_INTERNAL(OnRenderRequest) )); ... } } Void USRResponder::SetText(SFXAnsiStringConstRef param) { SFCError error(SFERR_NO_ERROR); if (!param.equals(_text)) { if ((error = _text.Set(param)) == SFERR_NO_ERROR) { Invalidate(); // here not draw label but register redraw region only } } return error; } // implement drawing handler(actual redrawing processing is described in drawing handler) XANDLER_IMPLEMENT_VOIDRENDER(USRResponder, OnRenderRequest, invoker, reason, graphics) { SFXRectangle local; // redrawing processing is described in drawing handler local.Set(GetLocalBound()); graphics->FillRectangle(local, SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00)); graphics->DrawSingleText(_text, local, SFXRGBColor(0x00, 0x00, 0x00, 0x00)); return; }
![]() |
IMPORTANT |
|---|---|
In the USRResponder::SetText() function where redrawing is needed, only registering the redraw region is described. Actual drawing is described in the drawing handler booted up at the end of event loop. | |
![]() |
Hint on performance improvement |
|---|---|
|
The SFYResponder::Invalidate function has the overload function with the rectangle argument. If a subset rectangular region of the responder is specified as the redraw region, since there is more possibility that it will be included in the union of responders placed foreground, the drawing performance may improve. | |
![]() |
Redrawing of the standard responder of SophiaFramework UNIVERSE |
|---|---|
In case of the standard responder of SophiaFramework UNIVERSE, even if the visual element such as state, attribute, region, parent-child or sibling relationship, ID, type, reference, text, font, color and so on is changed by executing its function(mainly, the prefix is "Set"), the related responders will be automatically redrawn as such. Therefore, there is no need to register the redraw region when the standard responder of SophiaFramework UNIVERSE is used. | |
The renderer is not automatically booted up in a callback outside the event loop such as a network or timer processing.
To redraw a responder on the device screen in the callback processing, the renderer needs to be booted up explicitly by calling the SFYResponder::Render function after registering redraw regions.
If the responder has already been terminated at the redraw, call the SFYResponder::Render function of its parent responder, or the SFYApplication::Render function of its application class.
Figure 9.24. Drawing inside callback 1: in case the Render() function is not called

Since callback is a processing outside the event loop, the renderer will not be automatically booted up after it finishes. Therefore, even if redraw regions are registered using the SFYResponder::Invalidate function, nothing will be redrawn on the device screen.
Figure 9.25. Drawing inside callback 2: in case the Render() function is called

Example 9.31. Redrawing through a callback
SFCError USRResponder::OpenConnection(Void)
{
SFCError error(SFERR_NO_ERROR);
_label->SetText(");
...
error = _http.Connect(XALLBACK_INTERNAL(OnConnect));
...
return error;
}
// implement callback for completing http connection
XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(USRResponder, OnConnect, error)
{
if (error == SFERR_NO_ERROR) {
...
}
_label->SetText("OnConnect was called."); // Invalidate() function is called inside SetText() function
Render(); // explicitly redraw(explicitly boot up renderer)
return;
}
![]() |
Method to redraw with high performance |
|---|---|
|
To get the highest performance of redrawing, it is necessary to boot up the renderer only once in each callback. At the end of the callback function, you have to call the SFYResponder::Render function of as low as possible responder in the responder tree, which includes all possible responders to be redrawn as a child responder. | |
![]() |
About executing Render(true) | ||||
|---|---|---|---|---|---|
|
If the argument of the SFYResponder::Render function is specified with "true", the responders to be actually displayed on the device screen are redrawn by force. It is recommended to execute Render(true) if and only if necessary. In general, Render(true) is executed when redrawing is needed since all the responder tree is constructed or re-constructed. This processing is automatically performed inside an application class when the applet boots up, resumes, or gets the control after the text input.
| |||||
|
Copyright(c) 2002 - 2010 Sophia Cradle Incorporated All Rights Reserved. |
![]() ![]() ![]()
|