PrevNextUpHome SophiaFramework UNIVERSE 5.1

9.3. Features of the Responder System

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

9.3.1. Responder Tree

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.

[Note] Root

SFYApplication contains the root(SFZRoot) bound with a renderer and a distributer as a default root responder.

[Caution] CAUTION

Since a newly created responder has no parent responder, it is temporarily a root responder until connected to a responder tree.

Figure 9.15. Structure of the responder tree


Structure of the responder tree

SFZWindow(see the incomplete responder tree on the right side) is temporarily a root responder until setting its parent responder to SFZRoot(see the complete responder tree on the left side).

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] 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:

  • Order relation 1: Child responder is placed more foreground than parent responder.
  • Order relation 2: Older sister responder is placed more foreground than younger sister responder.
  • Order relation 3: Older sister responder is placed more foreground than child responder of younger sister responder.

[Tip] 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

9.3.2. Responder Space

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.

[Note] 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.

[Note] 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

9.3.3. Event Handling

The abstract of how each event is handled in the responder system is as follows:

  1. A BREW-defined event which occurs by interruption such as user operation or external factor will be dispatched from the BREW environment to an applet.
  2. In the applet, the event will be automatically handled by the SFYApplication::HandleEvent function.
  3. The SFYApplication::HandleEvent function will boot up the renderer and pass the event to it.
  4. The renderer will distribute the event to appropriate reponders in the responder tree whose top is the root by using the tracer rules.
  5. The responder which will receive the event will boot up the corresponding handler if necessary.
  6. If responder-defined events or user-defined events occur during the execution of the above handler, their corresponding handlers will be booted up too.
[Tip] Tip
Reference: default implementation of the SFYApplication::HandleEvent function.

9.3.3.1. Life Cycle

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


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.

9.3.3.2. Booting up an Applet

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] 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.

Figure 9.17. Sequence diagram: Booting up an applet


Sequence diagram: Booting up an applet

* The renderer and the root are omitted from the figure since they are hardly related with this sequence.

9.3.3.3. Terminating an Applet

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] 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


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.

9.3.3.4. Standard Tracer

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.

[Note] 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:

  1. Distributing condition
  2. Processing order
  3. Overloading condition

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:

  1. Focus[SFYTracer::STATE_FOCUS]: Dispatch an event to focused responders.
  2. All[SFYTracer::STATE_ALL]: Dispatch an event to all responders.
  3. None[SFYTracer::STATE_NONE]: Dispatch an event to no child responders. In case of the dispatching rule of the tracer for the SFYDistributer class, an event will be dispatched to no responder including the root(SFZRoot).

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]".

[Caution] 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:

  1. Get the SFYDistributer instance using the SFYApplication::GetDistributer function.
  2. Register the handler for this event using the SFYDistributer::RegisterHandler function.
  3. Though this handler may be defined anywhere, not pointer to a responder but "null" will be passed via the "invoker" parameter. Note this matter in case the invoker parameter will be used.

Figure 9.19. SFEVT_KEY event: Distributing condition


SFEVT_KEY event: Distributing condition

The SFEVT_KEY event is dispatched to focused responders.

Figure 9.20. Dispatching the SFEVT_APP_RESUME event


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:

  1. "from background to foreground[SFYTracer::ORDER_BACKWARD]": The handlers registered into a responder placed background are booted up first. If more than one handler are registered into the same responder, they will be booted up in the order to be registered.
  2. "from foreground to background[SFYTracer::ORDER_FORWARD]": The handlers registered into a responder placed foreground are booted up first. If more than one handler are registered into the same responder, they will be booted up in the reverse order to be registered.

Overloading condition

For the overloading condition, specify whether or not the handler processes an event duplicately.

One of the following can be specifiled:

  1. "Yes[true]": The event is duplicately handled. Even if the event is handled by the handler, it will be dispatched to the next responder if any.
  2. "No[false]": The event is not duplicately handled. If the event is handled by the handler, it will not be dispatched to other responders.

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


SFEVT_KEY event: Processing order and Overloading condition

The SFEVT_KEY event is processed by the handlers of focused responders from foreground to background.

  1. The SFEVT_KEY event is dispatched first to the focused SFYControl in the lowest child layer.
  2. If the event is handled by SFYControl, event handling will end there. Otherwise it will be dispatched to SFZWindow, SFYControl's parent.
  3. If the event is handled by SFZWindow, event handling will end there. Otherwise it will be dispatched to SFYApplication(SFZRoot), SFZWindow's parent.
  4. If the event is handled by SFYApplication(SFZRoot), event handling will end there. Otherwise it will be returned to the BREW environment.
  5. When more than one handler for the SFEVT_KEY event are registered into the same responder, handlers are booted up in the reverse order to be registered.

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] 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.

[Caution] 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:

  1. Get the SFYDistributer instance using the SFYApplication::GetDistributer function.
  2. Register the handler for this event using the SFYDistributer::RegisterHandler function.
  3. Though this handler may be defined anywhere, not pointer to a responder but "null" will be passed via the "invoker" parameter. Note this matter in case the invoker parameter will be used.

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] 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

9.3.3.5. Handler

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.

[Note] 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] 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] 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.

[Tip] Tip
For more details, see the default implementation of the SFYApplication::HandleEvent function.
[Tip] 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

9.3.4. Rendering

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] 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.

[Tip] 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.

9.3.4.1. Time of Drawing

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

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.

Figure 9.23. If an event is not handled


If an event is not handled

If an event is not handled during the event loop, the renderer will not be booted up. As a result, no responder will be redrawn.

9.3.4.2. Drawing Handler

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] 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] 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] Tip

The drawing handler will get the SFXGraphics instance as argument and draw the corresponding responder in its local region.

9.3.4.3. Registering a Redrawing 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.

[Tip] 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] 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.

[Tip] 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.

[Tip] 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.

9.3.4.4. Redrawing Explicitly

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


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


Drawing inside callback 2: in case the Render() function is called
  1. Register redraw regions using the SFYResponder::Invalidate function.
  2. Explicitly call the SFYResponder::Render function of a responder which needs to be redrawn.
  3. The renderer will be booted up, and corresponding drawing handlers will be called.
  4. Actually the screen will be redrawn.

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;
}
[Note] 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.

[Caution] 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.

[Tip] 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.