PrevNextUpHome SophiaFramework UNIVERSE 5.3

9.8. Root(Basic)

Root(SFZRoot) is the responder designed to be placed at the highest position of the responder tree.

Bound with the distributer(SFYDistributer) and the renderer(SFYRenderer), the root can send an event to the responder tree and draw it.

An application class inheriting from SFYApplication contains the default root bound with the distributer(SFYDistributer) and the renderer(SFYRenderer).

Though you can define more than one root by constructing new responder trees explicitly, the above default root is enough in the applet development using SFYApplication. You don't have to define your own root in almost all cases.

[Caution] About SFZRoot

There is no need to define and implement the user-defined root by inheriting from SFZRoot since enough functions as the root responder has already been implemented in SFZRoot. In general, SFZRoot is used as it is in the applet development.

Table 9.7. Type of concrete root

Class name Description
SFZRoot General purpose root to place a window, dialog, or menu.
[Important] IMPORTANT

In the concrete root, the SFYResponder::SetDistributer, SFYResponder::SetRenderer, SFYResponder::SetState, and SFYResponder::SetRealBound functions must be always called.

Other functions are optionally called.

9.8.1. General Purpose Root to Place a Window, Dialog, or Menu [SFZRoot]

SFZRoot is the general purpose root to place a window, dialog, or menu.

In the applet develoment using an application class inheriting from SFYApplication, you don't have to declare the root explicitly since the default root(SFZRoot) has already been contained by SFYApplication.

When an application class inheriting from SFCApplication is used or another responder tree is necessary, you have to declare the root explicitly.

Figure 9.29. Execution Result

Execution Result

Following is the code to define and implement an application class, which will support the GUI framework, by inheriting directly from SFCApplication. In SFYApplication, almost the same code is defined and implemented.

[Note] Note

The SFYApplication class has the option function that the saved bitmap to restore the device screen is released at suspend time. In the following, the implementaion of this function is omitted to simplify the code.

For more details, see the internal implementation of the SFYApplication::HandleEvent function.

Example 9.44. Declaration

SFMTYPEDEFCLASS(USRApplication)
class USRApplication: public SFCApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZRootSmp       _root;         // root
    SFYDistributer   _distributer;  // distributer
    SFYRenderer      _renderer;     // renderer 
    SFXBaseEditorPtr _editor;       // text input control editor

    ...

private:
    explicit USRApplication(Void) static_throws;    
    virtual ~USRApplication(Void);
    virtual Bool HandleEvent(SFXEventConstRef event);
    virtual Bool HandleRender(SFXEventConstRef event);
    SFCError Make(Void);
    Bool Do(SFXEventConstRef event);
    Void Dispose(Void);
};

Example 9.45. Implementation 1

SFCError USRApplication::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // initialization

    // create the instance of the text input control editor
    if ((_editor = ::new SFXEditor) != null) {

        // initialize the distributer
        error = _distributer.Initialize();
        if (error == SFERR_NO_ERROR) {

            // initialize the renderer
            // * responder space will be set to the device screen
            error = _renderer.Initialize();
            if (error == SFERR_NO_ERROR) {

                // create the root
                if ((_root = SFZRoot::NewInstance(&error)) != null) {

                    // bind the root with the distributer
                    _root->SetDistributer(&_distributer);

                    // bind the root with the renderer
                    _root->SetRenderer(&_renderer);

                    // set the root's real region to the responder space
                    _root->SetRealBound(_root->GetSuitableBound());

                    // set the root's state to "visible" + "active" + "enable" + "focus" together
                    _root->SetState(true, true, true, true);
                }
            }
        }
    } else {

        error = SFERR_NO_MEMORY;
    }

    return error;
}

Bool USRApplication::Do(SFXEventConstRef event)
{
    // here describe the handling of the event dispatched from the BREW environment

    SFCError  error;
    Bool      result(false);

    // boot up the distributer to distribute the event using the tracer
    // first of all, the SFYDistributer instance bound with the root will receive the event
    // then, the event will be distributed to the responders in the responder tree according to the dispatching rules of the tracer
    // * _root is the root(SFZRoot)
    if ((error = _root->Distribute(event, &result)) == SFERR_NO_ERROR) {

        if (event.GetType() != SFEVT_APP_STOP && event.GetType() != SFEVT_APP_SUSPEND)) {  // if redrawing is necessary

            if (IsRenderable()) {  // if the screen can be redrawn (i.e., if no highest priority event handler is registered)

                 // boot up the renderer to redraw the responder tree below the root
                error = _root->Render();
            }
        }
    }
    if (error != SFERR_NO_ERROR) {

        // call HandleError() in case the fatal error such as insufficient memory during the initialization of the distributer or the renderer occurs
        if (HandleError(event, error)) {

            result = true;
        }
    }
    return result;  // return "true" if the event has been handled, otherwise return "false"
}

Void USRApplication::Dispose(Void)
{
    // finalization: execute these in the order below

    // destroy the instance of the text input control editor
    ::delete _editor;

    // release the responder tree
    _root.Release();

    // terminate the renderer
    _renderer.Terminate();

    // terminate the distributer
    _distributer.Terminate();

    return;
}
[Note] Responder space

Responder space is a rectangular region inside the device screen, where a responder tree bound with a renderer will be drawn.

The responder space is set with the SFYRenderer::Initialize function to initialize the renderer. After this initialization, the responder space cannot be expanded nor reduced dynamically.

By default, the responder space is set to a rectangular region of all device screen.

The USRApplication::Make function, the USRApplication::Do function, and the USRApplication::Dispose function in the above example code are called in the constructor, the event handler, and the destructor respectively as follows:

Example 9.46. Implementation 2

// constructor
USRApplication::USRApplication(Void)
{
    if (static_try()) {
 
        static_throw(Make());
 
        // describe other initialization
 
    }
}

// event handler
Bool USRApplication::HandleEvent(SFXEventConstRef event)
{
    SFCError   error;
    Bool       result(false);

    result = Do(event);
 
    // describe other processing
 
    return result;
}

// handler for drawing full screen
Bool USRApplication::HandleRender(SFXEventConstRef event)
{
    // here describe full screen redrawing
    SFCError  error;
    Bool      result(false);

    if (SFCApplication::HandleRender(event)) { // redraw the device screen

        // redraw the responder tree below the root
        // *1. if possible, redraw using the bitmap to restore the device screen
        // *2. start up the renderer by calling "Render(true)" if the bitmap to restore the device screen is not available in a timing such as receiving the SFEVT_APP_START event
        // *3. in case of "Render(true)", all visible responders' drawing handlers will be called
        error = _root->Render((event.GetType() == SFEVT_APP_START) || (_root->Recover() != SFERR_NO_ERROR));

        if (error == SFERR_NO_ERROR) {

            result = true;
        }
        else {
            // call HandleError() when fatal error such as insufficient memory during initialization of renderer
            HandleError(event, error);
        }
    }
    return result;
}

// destructor
USRApplication::~USRApplication(Void)
{
    Dispose();
 
    // describe other finalization
}