PrevNextUpHome SophiaFramework UNIVERSE 5.3

3.8. Frame

Frame provides the function to attach a frame with a border and/or a title to the responder such as a window, a dialog, or a menu.

3.8.1. Frame with a Title(Plain Frame and Bevel Frame)

Let's attach the plain frame with a title [SFZTitlePlainFrame] and the bevel frame with a title [SFZTitleBevelFrame] to the window and the dialog respectively as the figure below.

[Tip] How to attach a frame to a responder

Call the SFYResponder::SetFrame function of a responder to attach a frame to.

Figure 3.45. Plain frame with a title which is attached to the window [SFZTitlePlainFrame]

Plain frame with a title which is attached to the window [SFZTitlePlainFrame]

Figure 3.46. Bevel frame with a title which is attached to the dialog [SFZTitleBevelFrame]

Bevel frame with a title which is attached to the dialog [SFZTitleBevelFrame]

First, let's make two kinds of frames in the helloworld application class, which will be attached to the window and the dialog respectively.

Example 3.69. Create and place the frames attached to the window and the dialog

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

private:

    MyWindowSmp _myWindow;
    ItsWindowSmp _itsWindow;
    SFZTextMenuSmp _textMenu;
    TabWindowSmp _tabWindow;
    SFZSoftKeyControlSmp _softkey;

    // *** added and updated code segments are in bold

    // smart pointer to SFZTitlePlainFrame (frame for the window)
    SFZTitlePlainFrameSmp _windowFrame;

    // smart pointer to SFZTitleBevelFrame (frame for the dialog)
    SFZTitleBevelFrameSmp _dialogFrame;

public:

    static SFCInvokerPtr Factory(Void);

private:

    explicit helloworld(Void) static_throws;
    virtual ~helloworld(Void);
    SFCError MakeMy(Void);
    SFCError MakeMenu(Void);
    SFCError MakeIts(Void);
    SFCError MakeTab(Void);
    SFCError MakeSoftMenu(UInt32 key);

    // extend arguments so as to set title text

    // make the dialog
    SFCError MakeColorDialog(SFXWideStringConstRef title, UserColorConstRef color);

    // make the window frame
    SFCError MakeWindowFrame(SFXWideStringConstRef title);

    // make the dialog frame
    SFCError MakeDialogFrame(SFXWideStringConstRef title);

    SFCError RegisterSoftText(Void);
    Void SetMenuColors(UserColorConstRef color);
    SFXRectangle GetContentBound(Void) const;

    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest) // declare the drawing handler
    XANDLER_DECLARE_BOOLEVENT(OnKey)            // declare the key handler 
    XANDLER_DECLARE_VOIDRESULT(OnMenuResult)    // declare the result handler
    XANDLER_DECLARE_VOIDEVENT(OnSoftKey)        // declare the SoftKey handler
    XANDLER_DECLARE_VOIDEVENT(OnMenuSoftKey)    // declare the SoftKey handler
    XANDLER_DECLARE_VOIDEVENT(OnWindowSoftKey)  // declare the SoftKey handler

    // key handler of the window
    XANDLER_DECLARE_BOOLEVENT(OnWindowKey)

    // result handler of the dialog
    XANDLER_DECLARE_VOIDRESULT(OnDialogResult)
};

// make the window frame
SFCError helloworld::MakeWindowFrame(SFXWideStringConstRef title)
{
    SFCError error(SFERR_NO_ERROR);

    // create the plain frame with the title
    if ((_windowFrame = SFZTitlePlainFrame::NewInstance(&error)) != null) {

        // set the frame's title text
        error = _windowFrame->SetText(title);

        if (error == SFERR_NO_ERROR) {

            // set the enable flag of frame shadow to "false"(disabled)
            _windowFrame->SetShadowEnable(false);

            // in general, frame's state is set to "visible" + "active" + "enable" + "focus"
            _windowFrame->SetState(true, true, true, true);
        }
    }
    return error;
}

// make the dialog frame
SFCError helloworld::MakeDialogFrame(SFXWideStringConstRef title)
{
    SFCError error(SFERR_NO_ERROR);

    // create the bevel frame with title
    if ((_dialogFrame = SFZTitleBevelFrame::NewInstance(&error)) != null) {

        //  set the frame's title text
        error = _dialogFrame->SetText(title);

        if (error == SFERR_NO_ERROR) {

            // in general, frame's state is set to "visible" + "active" + "enable" + "focus"
            _dialogFrame->SetState(true, true, true, true);
        }
    }
    return error;
}

Next, let's attach the frames to the window and the dialog created by the above codes.

In the code below, we will register the key handler("OnWindowKey") and the result handler("OnDialogResult") into the window and the dialog, which will terminate the corresponding window or dialog, when the CLEAR key is pressed.

Example 3.70. Attach frames to the window and the dialog

// make MyWindow
SFCError helloworld::MakeMy(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // *** added and updated code segments are in bold

    // make the frame
    if ((error = MakeWindowFrame("MyWindow")) == SFERR_NO_ERROR) {

        // create the MyWindow instance
        if ((_myWindow = MyWindow::NewInstance(&error)) != null) {

            // set the MyWindow's parent responder to the application class(root)
            error = _myWindow->SetParent(GetThis());

            if (error == SFERR_NO_ERROR) {

                // attach the frame to MyWindow
                error = _myWindow->SetFrame(_windowFrame);

                if (error == SFERR_NO_ERROR) {

                    error = _myWindow->RegisterHandler(
                        SFXEventRange(SFEVT_RESPONDER_SOFTKEY, SFEVT_RESPONDER_SOFTKEY, SFP16_BEGIN, SFP16_END),
                        XANDLER_INTERNAL(OnWindowSoftKey)
                    );

                    if (error == SFERR_NO_ERROR) {

                        // register the key handler
                        error = _myWindow->RegisterHandler(
                            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
                            XANDLER_INTERNAL(OnWindowKey)
                        );

                        if (error == SFERR_NO_ERROR) {

                            // set the frame's real region to the content region
                            // * automatically, window's real region will be set to the region obtained by deflating the frame's real region by frame margin
                            _windowFrame->SetRealBound(GetContentBound());

                            // set the MyWindow's state to "visible" + "active" + "enable" + "focus" together
                            _myWindow->SetState(true, true, true, true);

                            // make the SoftKey menu
                            if ((error = MakeSoftMenu(KEY_MENU_WINDOW)) == SFERR_NO_ERROR) {

                                // bind the SoftKey menu with MyWindow
                                error = _softkey->Bind(_myWindow, KEY_MENU_WINDOW);

                                // move MyWindow foremost
                                // * the frame will be moved foremost automatically
                                _myWindow->ToFront();

                                // make MyWindow's controls
                                _myWindow->Make();
                            }
                        }
                    }
                }
            }
        }
    }
    return error;
}

// make ItsWindow
SFCError helloworld::MakeIts(Void)
{
    // ...(omitted)...

    if ((error = MakeWindowFrame("ItsWindow")) == SFERR_NO_ERROR) {

    // ...(omitted)...
}

// make TabWindow
SFCError helloworld::MakeTab(Void)
{
    // ...(omitted)...

    if ((error = MakeWindowFrame("TabWindow")) == SFERR_NO_ERROR) {

    // ...(omitted)...
}

// make the dialog
SFCError helloworld::MakeColorDialog(SFXWideStringConstRef title, UserColorConstRef color)
{
    SFZMessageDialogSmp dlg;
    SFCError error(SFERR_NO_ERROR);

    // make the frame
    if ((error = MakeDialogFrame(title)) == SFERR_NO_ERROR) {

        // create the dialog
        if ((dlg = SFZMessageDialog::NewInstance(&error)) != null) {

            // set the dialog's parent responder to the application class(root)
            error = dlg->SetParent(GetThis());

            if (error == SFERR_NO_ERROR) {

                // attach the frame to the dialog
                error = dlg->SetFrame(_dialogFrame);

                if (error == SFERR_NO_ERROR) {

                    // register the result handler of the dialog
                    error = dlg->RegisterHandler(
                        SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                        XANDLER_INTERNAL(OnDialogResult)
                    );

                    // ...(omitted)...

                    // Calculate the suitable dialog region within the hint region as the screen device region, 
                    // which will be aligned at the center and the middle of the hint region.
                    // Set the dialog's real region to it.
                    // * Automatically, the frame's real region will be set to the region obtained by inflating it by the frame margin.
                    dlg->SetRealBound(dlg->GetSuitableBound(GetContentBound(), SFYResponder::HORIZONTAL_CENTER, SFYResponder::VERTICAL_MIDDLE));

                    dlg->SetState(true, true, true, true);

                    // ...(omitted)...

                    // move the dialog foremost
                    // * automatically, the frame will be moved foremost together
                    dlg->ToFront();
                }
            }
        }
    }
    return error;
}

// result handler of the text menu
XANDLER_IMPLEMENT_VOIDRESULT(helloworld, OnMenuResult, invoker, reason, result)
{
    // ...(omitted)...

    switch (reason) {
        case SFP16_RESULT_OK:
            TRACE("'%S' is selected", _textMenu->GetItemText(static_cast<SInt16>(result)).GetCString());
            switch (result) {
                case 0:
                case 1:
                case 2:
                case 3: {
                    SetMenuColors((color[result]));

                    // make the dialog
                    // * give color scheme's name(frame title) as an argument
                    MakeColorDialog(_textMenu->GetItemText(result), (color[result]));

                    break;
                }

                // ...(omitted)...
            }
            break;

        // ...(omitted)...

    }
    return;
}

At the last, let's implement codes to terminate the window in the key handler and the SoftKey handler of MyWindow, and terminate the dialog in the result handler of the dialog.

Example 3.71. Terminate the frame

// key handler of MyWindow
XANDLER_IMPLEMENT_BOOLEVENT(helloworld, OnWindowKey, invoker, event)
{
    // invoker: MyWindow

    Bool result(false);

    switch (event.GetP16()) {
        case AVK_CLR:

            // terminate the window only
            // * automatically, the frame will be detached from the window and become invisible
            // * there is no need to close the frame
            invoker->Terminate();

            result = true;
            break;
    }
    return result;
}

// result handler of the dialog
XANDLER_IMPLEMENT_VOIDRESULT(helloworld, OnDialogResult, invoker, reason, result)
{
    unused(reason);
    unused(result);

    // terminate the dialog
    // * the frame will be automatically detached from the the dialog and become invisible
    // * there is no need to close the frame
    invoker->Terminate();

    return;
}

[Note] Note

There are two kinds of key handlers registered into MyWindow as follows:

  1. OnKey key handler registered in the constructor of MyWindow
  2. OnWindowKey key handler registered in the helloworld application class after instantiation of MyWindow

In this case, the OnWindowKey key handler will be booted up first when MyWindow receives the key event, since the OnWindowKey key handler is registered later than the OnKey key handler.

[Tip] The order to boot up more than one registered key handler

If multiple key handlers are registered into the same responder, they will be booted up in the reverse order of registration when the key event is received.

Reference: Key Event[from SFEVT_KEY to SFEVT_KEY_HOOK_RELEASE]

The following is execution result on BREW simulator.

Figure 3.47. Plain frame with a title which is attached to the window [SFZTitlePlainFrame]

Plain frame with a title which is attached to the window [SFZTitlePlainFrame]

Figure 3.48. Bevel frame with a title which is attached to the dialog [SFZTitleBevelFrame]

Bevel frame with a title which is attached to the dialog [SFZTitleBevelFrame]

Reference: Frame