PrevNextUpHome SophiaFramework UNIVERSE 5.3

3.1. SFY Applet

The SFY applet has the application class inheriting from SFYApplication, where the SFY GUI framework is available.

In this section, processing from the SFY applet starting up to its terminating is described.

The sample code in this chapter is available at this site.

[Note] SFC applet

The SFC applet has the application class inheriting from SFCApplication, where no GUI framework is available.

[Note] What is a responder?

In SophiaFramework UNIVERSE, the GUI component is called "responder"(SFYResponder).

3.1.1. Starting up an Applet

The development of the SFY applet starts with implementing the SFCApplet::Boot function and the Factory function.

The SFCApplet::Boot function is booted up first in the applet. In this function, the license code is set to be validated with the class ID of this applet. If the "id"(Class ID) argument equals that of the applet, "AEECLSID_HELLOWORLD", the Factory function will be returned.

Next, the Factory function will be executed to create the instance of the "helloworld" application class.

[Tip] Tip
Only one application instance per applet can be created.
[Note] ClassID and its license code

An applet will not boot up if the regular license code is not set. And the license code must correspond to the class ID of the applet.

The class ID and the corresponding license code of an applet in the Example folder or the Tutorial folder is available for testing your applet on the BREW-enabled phone at the development time.

However, there is no need to set the license code when testing your applet on BREW simulator.

Example 3.1. Boot loader and Factory function

//
//  helloworld.cpp
//

#include "helloworld.hpp"

// boot loader
SFCApplet::FactorySPP SFCApplet::Boot(AEECLSID id, SFXAnsiStringPtr license)
{
    // here describe the license code for this applet
    // this license code must correspond to the class ID of this applet
    *license = "heap://"
      "TIXDRQXNU5WHU8Y3Z9WOHWQR6Z3VPSDHDV5CR1S4XASPWLUHWAS7Z5Z2TGS3XMSAT3UPUQTLTARCYPSF"
      "UEJZ6ROSJWGUQSEYKR6V2U4VESMTQLHKZ6X7Y2VKXHWIX3XBU0Z7VHWHXIZBSGT5SPU3XLX0Z1Y4R3TC"
      "U6WGT9WHWIVNYHYCUCR9T3SMTEWPRNVAX1Y4VPW2YCY9YQV5R7Z9UIVHT6SDUPU2SIW6VCRCWBR2S4WQ"
      "UPYFWCYGT4VIT1WHXGYPTQSFYPWNV3ULRNWFW7RBRFVKUKS2YQSQYHW1TPUPXBZ6UEY2WOYKR7S3TAU4"
      "TQS6UHVFVEVLU3R5SDSKW7RPTNTPVQU2T4R8Z4VLUGEW3U98TLDR8/";

    return (id == AEECLSID_HELLOWORLD) ? (&helloworld::Factory) : (null);
}

// factory function
SFCInvokerPtr helloworld::Factory(Void)
{
    return ::new helloworld; // create the instance of the helloworld application class
}

3.1.2. Defining the Application

The application class of the helloworld applet inherits from SFYApplication.

XANDLER_DECLARE_VOIDRENDER(OnRenderRequest) declares the drawing handler.

XANDLER_DECLARE_BOOLEVENT(OnKey) declares the key handler.

[Note] What is a handler?

A handler is the function to be called when the corresponding event occurs.

For example, there is the drawing handler to handle the drawing event, or the key handler to handle the key event[SFEVT_KEY].

Reference: Handler | Handler List | Event | Event List

Example 3.2. Define the helloworld application class

//
//      helloworld.hpp
//

#ifndef __HELLOWORLD_HPP
#define __HELLOWORLD_HPP

#include <SophiaFramework.hpp>
#include "helloworld.bid"

//
// define the helloworld class
//

SFMTYPEDEFCLASS(helloworld)  //  macro to generate the useful types
class helloworld : public SFYApplication {

    SFMSEALCOPY(helloworld)  //  macro to prohibit the developer from copying this instance
public:
    static SFCInvokerPtr Factory(Void);
private:
    explicit helloworld(Void) static_throws;
    virtual ~helloworld(Void);

    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest) // declare the drawing handler
    XANDLER_DECLARE_BOOLEVENT(OnKey)            // declare the key handler 
};

#endif // __HELLOWORLD_HPP //
[Caution] Application name including the capital alphabets(BREW 4.0 or above)

In general, the application class name such as "helloworld" will be the same with the applet name.

From BREW 4.0, the capital alphabets cannot be used for the applet name.

When you use the capital alphabet for the application class name such as "HelloWorld"or "USRApplication", you have to convert the capital alphabets into the small alphabets in the applet name.

[Tip] SFMTYPEDEFCLASS macro

SFMTYPEDEFCLASS is the macro to generate user-defined types for the helloworld application class automatically.

[Tip] SFMSEALCOPY macro

SFMSEALCOPY is the macro to prevent the application instance from being copied(i.e., the "helloworld" instance must not be copied in the above code).

[Tip] XANDLER_DECLARE_VOIDRENDER macro

XANDLER_DECLARE_VOIDRENDER is the macro to declare the drawing handler.

[Tip] XANDLER_DECLARE_BOOLEVENT macro

XANDLER_DECLARE_BOOLEVENT is the general purpose macro to declare the handler which returns the value of the Bool type.

3.1.3. Implementing the Constructor

In the constructor of the helloworld application class, the drawing handler and the key handler are registered with the SFYApplication::RegisterHandler function. By these operations, the drawing handler or the key handler will be called when the helloworld application class(root) receives the drawing event or the key event.

To register the handler with the SFYApplication::RegisterHandler function, specify the range of the events to be handled by this handler with the SFXEventRange class, and the pointer to this handler with the XANDLER_INTERNAL macro.

In the following example, the OnRenderRequest function and the OnKey function are registered as the handler for the drawing event and the handler for the key event[SFEVT_KEY], respectively.

For the OnRenderRequest function, the drawing event of (SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) is specified.

For the OnKey function, the key events from (SFEVT_KEY, SFP16_BEGIN) to (SFEVT_KEY, SFP16_END) are specified.

Example 3.3. Implement the Constructor

// constructor
helloworld::helloworld(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)
        ));
    }
    if (static_try()) {
        static_throw(RegisterHandler(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            XANDLER_INTERNAL(OnKey)
        ));
    }
}
[Tip] SFYApplication::RegisterHandler function

The SFYApplication::RegisterHandler function is used to register a handler into the application, which essentially equals registering it into the root (SFZRoot) which the application class contains by default.

[Note] Event

An event(SFXEvent) consists of an event type and two parameters(i.e., P16 parameter and P32 parameter).

A handler to handle the corresponding event will be registered into the responder with the SFYApplication::RegisterHandler or the SFYResponder::RegisterHandler function.

There are three kind of events as follows:

  1. BREW-defined event of BREW SDK
  2. Responder-defined event of SophiaFramework UNIVERSE
  3. User-defined event

The event type name of the BREW-defined event has the SF prefix before the corresponding event type name of BREW SDK.

For instance, the SFEVT_KEY event(key event[SFEVT_KEY]) is the BREW-defined event.

On the other hand, the event type name for the responder-defined event has the SFEVT_RESPONDER_ prefix.

For instance, the SFEVT_RESPONDER_RENDER event(drawing event) is the responder-defined event.

[Note] Notation of the event

In this manual, an event is described with one of the following three notations depending on the situation.

  1. event type name
  2. (event type name, P16 parameter)
  3. (event type name, P16 parameter, P32 parameter) [or SFXEvent(event type name, P16 parameter, P32 parameter)]

[Tip] SFXEventRange

To register the handler into the responder, a range of events must be specified in the argument of RegisterHandler() with SFXEventRange.

Events from (sEventType, sP16, *) to (eEventType, eP16, *) are specified as follows:

// events from (sEventType, sP16) to (sEventType, sP16)
SFXEventRange(sEventType, eEventType, sP16, eP16) 

Key events from (SFEVT_KEY, SFP16_BEGIN) to (SFEVT_KEY, SFP16_END) are specified as follows:

// all key events
SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END)

When only the (EventType, P16) event should be handled, it is specified as below

// (EventType, P16) event
SFXEventRange(EventType, EventType, P16, P16) 

In case of the drawing event, it is specified as follows:

// (SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) drawing event
SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST)

[Tip] XANDLER_INTERNAL macro

The XANDLER_INTERNAL macro macro is used to get the handler referring to the internal instance(i.e., this instance), which is to be specified in the argument of the RegisterHandler function.

[Caution] Return statement

In general, the return statement should not be described in the constructor nor in the destructor with C++.

The following bug is confirmed when GCC is used. If the return statement is described in the constructor or destructor, the compiler will freeze when a particular inheritance relation exists.

3.1.4. Implementing the Destructor

In the destructor of the helloworld application class, which is automatically called at the applet termination triggered by the SFCApplication::Terminate function, the finalization of the applet will be described.

Example 3.4. Implement the destructor

// destructor
helloworld::~helloworld(Void)
{
}
[Caution] Return statement

In general, the return statement should not be described in the constructor nor in the destructor with C++.

The following bug is confirmed when GCC is used. If the return statement is described in the constructor or destructor, the compiler will freeze when a particular inheritance relation exists.

3.1.5. Implementing the Event Handler

Let's implement the drawing handler and the key handler which are declared in the "helloworld" application class.

3.1.5.1. Implementing the Drawing Handler

The drawing handler to draw the string "HellowWorld" on the device screen by calling the SFXGraphics::DrawSingleText function is implemented as below.

[Important] Caution:

* In the SFY applet with the GUI framework, drawing must be performed within the drawing handler.

Example 3.5. Implement the drawing handler

// implement drawing handler
XANDLER_IMPLEMENT_VOIDRENDER(helloworld, OnRenderRequest, invoker, reason, graphics)
{
    unused(invoker);
    unused(reason);

    // draw in the local region of this responder whose left-top is the origin
    // in case of the application class, drawing will be performed in the local region of the root

    // the local region of the root is same with that of the device screen

    // since the virtual region is not set, 
    // the real region for actual drawing is same as the local region(the device screen)

    // the responder's background is filled in the color set with SFYWidget::SetBackgroundColor()[default: white]

    // draw "Hello World" in black at the center
    graphics->DrawSingleText("Hello World", 
                              GetLocalBound(), 
                              SFXRGBColor(0x00, 0x00, 0x00, 0x00));

    // draw "Right Bottom" in blue at the right-bottom
    graphics->DrawSingleText("RightBottom", 
                              GetLocalBound(), 
                              SFXRGBColor(0x00, 0x00, 0xAA, 0x00), 
                              IDF_ALIGN_BOTTOM | IDF_ALIGN_RIGHT);

    // draw "Left Top+(10,30)" with underline in green at (10, 30)
    graphics->DrawSingleText("LeftTop+(10,30)", 
                              SFXGrid(10, 30), 
                              SFXRGBColor(0x00, 0xAA, 0x00, 0x00), 
                              IDF_TEXT_UNDERLINE);

    return;
}
[Tip] XANDLER_IMPLEMENT_VOIDRENDER macro

XANDLER_IMPLEMENT_VOIDRENDER is the macro to implement the drawing handler. When the drawing event is received, the drawing handler implemented by this macro will be booted up.

The invoker, reason, and graphics arguments represent the responder calling this handler, the P16 parameter, and the graphics object respectively.

In the above example, the invoker is the pointer of the SFYResponderPtr type to the root[SFZRoot] which the helloworld application class contains by default, and the reason is SFP16_RENDER_REQUEST.

[Tip] unused macro

unused is the macro to avoid displaying the warnig messages.

[Tip] SFXGraphics::DrawSingleText()

The SFXGraphics::DrawSingleText function draws a single line of string at the specified position.

On the other hand, the SFXGraphics::DrawMultipleTextCenter, SFXGraphics::DrawMultipleTextLeft, or SFXGraphics::DrawMultipleTextRight function draws the multiple lines of the specified string.

[Tip] SFYApplication::GetLocalBound function

The application class of the SFY applet has one root[SFZRoot] by default.

The region gotten by calling the SFYApplication::GetLocalBound function is the local region of the root. In default setting, this region is the same with the device screen.

In the above example, to make the story brief, drawing is performed in this region. In general, drawing will be performed in the local region of the responder such as a window, which is the child responder of the root.

[Note] Background color of the responder

In the responder inheriting from SFYWidget, the background color can be set with the SFYWidget::SetBackgroundColor function.

As far as the transparency attribute is not set with the SFYResponder::SetPropertyTransparent function, the local region of the responder is filled in the background color set with the SFYWidget::SetBackgroundColor function during the internal processing of SFYWidget before its own drawing handler is booted up.

In the above example, its background color is not set with the SFYWidget::SetBackgroundColor function. Therefore, it is the white color[SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00)].

Since neither the transparency attribute nor the background color is not set to the root[SFZRoot] which the helloworld application class contains internally, the "Hello World" string is drawn in black with the background in white.

[Important] IMPORTANT: Four kind of the responder regions

In the responder, there are four kinds of the responder regions as follows:

  1. Real region.  The visible rectangular region of the responder represented with the relative coodinate system that has the left-top of the local region of the parent responder as the origin. The size of the real region is the same with that of the global region.

    Reference: Real Region | SFYResponder::SetRealBound | SFYResponder::GetRealBound

  2. Virtual region.  All rectangular region of the responder represented with the relative coodinate system that has the left-top of its real region as the origin. The size of the virtual region is the same with that of the local region.

    Reference: Virtual Region | SFYResponder::SetVirtualBound | SFYResponder::GetVirtualBound

  3. Local region.  All rectangular region of the responder represented with the relative coodinate system that has the left-top of its responder region as the origin. The size of the local region is the same with that of the virtual region.

    Reference: Local Region | SFYResponder::GetLocalBound

  4. Global region.  The rectangular region same with the real region of the responder, which is represented in the absolute coordinate system with the left-top of device screen as origin (0, 0). The size of the global region is the same with that of the real region. If necessary, the global region will be given to the standard BREW interface.

    Reference: Global Region | SFYResponder::GetGlobalBound

[Note] Handle the drawing event

The drawing event will boot up the drawing handler to draw the corresponding responder on the device screen.

The drawing event will be sent to the responders to be redrawn after the SFYResponder::Render function is called in one of the following cases.

  1. At the end of the event loop
  2. At the applet start / resume or the end of a highest priority event handler
  3. In the callback, which is outside the event loop.

Then, the drawing handler will be booted up.

Drawing is performed in the local region of the responder via the "graphics" object.

The above OnRenderRequest drawing handler will be booted up at the end of the event loop of the SFEVT_APP_START event.

[Note] Drawing region of the application class

Drawing is performed in the local region (in this case, the device screen) of the root[SFZRoot] which the application class contains by default.

Figure 3.1. Execution result

Execution result

3.1.5.2. Implementing the Key Handler

The following is the code to terminate this applet when the the SFEVT_KEY event of the "SELECT" key(AVK_SELECT) is received.

Example 3.6. Implement the Key Handler

// Key handler
XANDLER_IMPLEMENT_BOOLEVENT(helloworld, OnKey, invoker, event)
{
    unused(invoker);
    switch (event.GetP16()) {

        case AVK_SELECT: // when the SELECT key is pressed

            Terminate(); // terminate the "helloworld" application (and this applet will be terminated automatically)

            return true; // return "true" since the key event has been handled
    }

    return false; // return "false" since the key event has not been handled
}
[Tip] XANDLER_IMPLEMENT_BOOLEVENT macro

XANDLER_IMPLEMENT_BOOLEVENT is the general purpose macro to implement the handler returning the Bool type.

In the above example, the handler for the key event[SFEVT_KEY] dispatched from the BREW environment is implemented.

When the key event is received, the handler implemented by this macro will be booted up.

[Important] Responder-related operation for the application class

The responder-related operation for the application class is delegated to the root[SFZRoot] which the application class contains dy default.

[Note] Terminating an applet

To terminate an applet, call the SFCApplication::Terminate function.

For more details on terminating the applet, see ending the applet.

[Important] Return value of the key handler

If the key handler handles the key event, it will return "true". Otherwise will return "false".

[Note] Handle the key event

The key event[SFEVT_KEY] will be dispatched immediately when the key of the mobile phone is pushed. Then it will be dispatched to the focused responders by the rules of the tracer.

Next, the key handler first registered into the foremost focused responder will be booted up first of all.

If the key handler handles the key event, event handling will end there. Otherwise, if there are other key handlers registered, the second registered key handler will be booted up.

If the key handlers don't handle the key event, event handling will continue in the second foreground focused responder.

3.1.6. Defining and Accessing the Global Variable

Since the instance of the application class can be accessed anywhere in the applet by calling the SFYApplication::GetInstance function, the global variable can be defined in the application class.

Example 3.7. Define and Access the Global Variable

//
// define the helloworld class
//
SFMTYPEDEFCLASS(helloworld)  //  macro to generate the useful types
class helloworld : public SFYApplication
{
    SFMSEALCOPY(helloworld)  //  macro to prohibit the developer from copying this instance

public:

    static SFCInvokerPtr Factory(Void);

private:

    explicit helloworld(Void) static_throws;
    virtual ~helloworld(Void);

    // define the "global_something_val" global variable 
    SInt32 global_something_val;

public:

    // declare GetGlobalSomethingVal() to access the "global_something_val" global variable 
    SInt32 GetGlobalSomethingVal() const;
};

// implement GetGlobalSomethingVal() to access the "global_something_val" global variable 
SInt32 helloworld::GetGlobalSomethingVal(Void) const
{
    return global_something_val;
}

// get the value of the "global_something_val" global variable via GetGlobalSomethingVal()
static_cast<helloworldPtr>(SFYApplication::GetInstance())->GetGlobalSomethingVal();

3.1.7. Error Handling

static_exception::static_throw and static_exception::static_try in the constructor are functions to set an error value and validate it respectively.

The error value can be obtained with the static_exception::static_catch function. In general, the static_exception::static_catch function is called in the class which uses the class throwing out the error value.

[Note] Handling the error in the contructor

Though the constructor returns no error value, the error which may occur in the constructor can be notified outside the constructor with this mechanism.

Example 3.8. Handle the error in the constructor

 // handle the error which occurs in MyResponder constructor outside the MyResponder constructor
myResponder = MyResponder::NewInstance()
switch( myResponder->static_catch() ){

        // handle the error depending on the value

       ...

};

static_exception is the template class which has the variable(template argument) to contain the error value. The SFCError type is used as the variable(template argument).

The merit of static_exception lies in the fact that the error value inside the constructor or operator can be thrown out to the outside by this mechanism when the exception handling in the C++ compiler such as RVCT for BREW 1.2 is not available.

Reference: Application Class (Basic)

3.1.8. Terminating an Applet

To terminate an applet, call the SFCApplication::Terminate function.

When the SFCApplication::Terminate function is called, the BREW API ISHELL_CloseApplet function will be internally called. At this time, the applet will receive the SFEVT_APP_STOP event, the instance of the application class will be released after the destructor of the application class is executed, and then the applet will terminate.

In the destructor of the application class, the text input control editor, the responder tree, the renderer, and the distributer will terminate in this order. Then all resources that the applet has used will be released.

In the SFCApplication::~SFCApplication destructor, the applet is set to the state that it will not handle the BREW event hereafter.

If the user presses the power key(AVK_POWER) or the clear key(AVK_CLR) with sending false to AEE, the applet will terminate same as the SFCApplication::Terminate function is called.

[Note] Note

The SFEVT_KEY event of the clear key(AVK_CLR) can be handled by the applet, however, that of the AVK_POWER key cannot be handled.

[Note] Note

The SFCApplication::Terminate function is different from the SFYResponder::Terminate function to terminate a responder.