PrevNextUpHome SophiaFramework UNIVERSE 5.3

3.6. Container

3.6.1. General Purpose Container and Scroll Bar Control

Let's make the general purpose container(SFZContainer) to place controls or containers as the figure below.

Figure 3.30. General purpose container

General purpose container

The abstract of this sample code is as follows:

  1. Create the window of the user-defined "ItsWindow" class, which is derived from SFZWindow.
  2. Place the general purpose container of the SFZContainer class in the window.
  3. Place the text button control of the SFZTextButtonControl class in the container.
  4. Place the scroll bar control of the SFZContainerScrollBarControl class right next to the container to display the scroll status.
[Note] Container

Container is the responder to place controls and/or containers(container, window, dialog).

Window or dialog is a kind of the container.

When responders such as a control or a container are placed in the container, the focus can be moved among responders with the scroll keys set with the SFYContainer::SetScrollDownKey / SFYContainer::SetScrollUpKey / SFYContainer::SetPageDownKey / SFYContainer::SetPageUpKey / SFYContainer::SetSnapDownKey / SFYContainer::SetSnapUpKey function.

If the virtual region is larger than the real region, the scroll function linked with the move-focus function will be also available.

The following is the code to define and implement the ItsWindow class newly.

Example 3.50. Define the ItsWindow class

// define the ItsWindow class
SFMTYPEDEFRESPONDER(ItsWindow)  //  macro to generate the useful types
class ItsWindow : public SFZWindow
{
    SFMSEALRESPONDER(ItsWindow)  //  macro to prohibit the developer from copying this instance

    // macro to specify the inheritance relation from SFYResponder to this class
    SFMRESPONDERINSTANTIATEFOUR(ItsWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
public:

    // since 4-character type of small alphabet and symbol is reserved 
    // define ('I', 'W', 'N', 'D') of capital alphabets for ItsWindow type
    enum CodeEnum {
        CODE_TYPE = four_char_code('I', 'W', 'N', 'D')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static ItsWindowSmp NewInstance(SFCErrorPtr exception = null);

    // make the container and control on ItsWindow
    SFCError Make(Void);

protected:
    explicit ItsWindow(Void) static_throws;
    virtual ~ItsWindow(Void);

private:

    // declare the key handler
    XANDLER_DECLARE_BOOLEVENT(OnKey)
};

// define the color scheme
#define COLOR_ITS_WINDOW_BACK (SFXRGBColor(0xCC, 0xFF, 0xCC, 0x00))

// constructor
ItsWindow::ItsWindow(Void) static_throws
{
    if (static_try()) {
        SetType(CODE_TYPE);

        // register the key handler into ItsWindow
        static_throw(RegisterHandler(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            XANDLER_INTERNAL(OnKey)
        ));

        // set ItsWindows's background color to light green
        SetBackgroundColor(COLOR_ITS_WINDOW_BACK);
    }
}

// destructor
ItsWindow::~ItsWindow(Void)
{
}

// create the ItsWindow instance
ItsWindowSmp ItsWindow::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<ItsWindow>(Factory(:: new ItsWindow, exception));
}

// make the container and controls on ItsWindow
SFCError ItsWindow::Make(Void)
{
    SFYContainerSmp container;
    SFZContainerScrollBarControlSmp bar;
    SFCError error(SFERR_NO_ERROR);

    // create the general purpose container
    if ((container = SFZContainer::NewInstance(&error)) != null) {

        // set the container's parent responder to window
        if ((error = container->SetParent(GetThis())) == SFERR_NO_ERROR) {

            // set the container's real region to the region obtained by deflating the window's local region by (5, 5, 10, 5)
            container->SetRealBound(GetLocalBound().Deflate(5, 5, 10, 5));

            // set the container's virtual region to the region obtained by expanding the container's real region down by 150
            container->SetVirtualBound(SFXRectangle(container->GetRealBound()).AddHeight(150));

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

            SFZTextButtonControlSmp button;

            // create the button control
            if ((button = SFZTextButtonControl::NewInstance(&error)) != null) {

                // set the button control's parent responder to the container
                if ((error = button->SetParent(container)) == SFERR_NO_ERROR) {

                    // set the button control's text to "CenterMiddle"
                    if ((error = button->SetText("CenterMiddle")) == SFERR_NO_ERROR) {

                        // set the button control's real region at the center of the container's local region
                        button->SetRealBound(button->GetSuitableBound(container->GetLocalBound()).SnapCenterMiddle(container->GetLocalBound().GetCenterMiddle()));

                        // set the button control's state to "visible" + "active" + "enable" + "focus" together 
                        button->SetState(true, true, true, true);
                    }
                }
            }
        }
    }
    if (error == SFERR_NO_ERROR) {

        // create the scroll bar control for the container
        if ((bar = SFZContainerScrollBarControl::NewInstance(&error)) != null) {

            // set the scroll bar control's parent responder to ItsWindow
            if ((error = bar->SetParent(GetThis())) == SFERR_NO_ERROR) {

                // place the scroll bar control right next to the container
                // * scroll bar's width is 5
                SFXRectangle rx;
                rx.Set(container->GetRealBound());
                rx.AddX(rx.GetWidth());
                rx.SetWidth(5);
                bar->SetRealBound(rx);

                // set the scroll bar control's state to "visible" + "active" + "disable" + "unfocus" together 
                // * scroll bar control must be never focused
                bar->SetState(true, true, false, false);

                /// bind the container with the scroll bar control
                error = bar->Bind(container);
            }
        }
    }
    return error;
}

// key handler
XANDLER_IMPLEMENT_BOOLEVENT(ItsWindow, OnKey, invoker, event)
{
    Bool result(false);

    unused(invoker);
    switch (event.GetP16()) {

        // when the CLEAR key is pressed
        case AVK_CLR:

            // terminate ItsWindow
            Terminate();

            result = true;
            break;
    }
    return result;
}

ItsWindow will be displayed when the "3" key is pressed in the initial screen.

Example 3.51. Make ItsWindow

// 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;
    SFZTextMenuSmp _textMenu;

    // *** added code segments are in bold

    // ItsWindow's smart pointer
    ItsWindowSmp _itsWindow;

public:

    static SFCInvokerPtr Factory(Void);

private:

    explicit helloworld(Void) static_throws;
    virtual ~helloworld(Void);
    SFCError MakeMy(Void);
    SFCError MakeMenu(Void);
    SFCError MakeColorDialog(UserColorConstRef color);

    // ItsWindow make
    SFCError MakeIts(Void);

    Void SetMenuColors(UserColorConstRef color);

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

// make ItsWindow
SFCError helloworld::MakeIts(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // create ItsWindow instance
    if ((_itsWindow = ItsWindow::NewInstance(&error)) != null) {

        // set ItsWindow's parent responder to the root
        error = _itsWindow->SetParent(GetThis());

        if (error == SFERR_NO_ERROR) {

            // set ItsWindow's real region to the region obtained by deflating the device screen region by (10, 10)
            _itsWindow->SetRealBound(GetLocalBound().Deflate(10, 10));

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

            // move ItsWindow foremost 
            _itsWindow->ToFront();

            // make ItsWindow's control
            _itsWindow->Make();
        }
    }
    return error;
}

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

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

    // draw text
    graphics->DrawSingleText("Key 1 - Controls", SFXGrid(20, 20), GetLocalBound(), COLOR_BLACK);
    graphics->DrawSingleText("Key 2 - TextMenu", SFXGrid(20, 40), GetLocalBound(), COLOR_BLACK);

    graphics->DrawSingleText("Key 3 - Container", SFXGrid(20, 60), GetLocalBound(), COLOR_BLACK);

    return;
}

// key handler
XANDLER_IMPLEMENT_BOOLEVENT(helloworld, OnKey, invoker, event)
{
    Bool result(false);

    unused(invoker);
    if (this->GetChildFront(true, false, false, false) == null) {
        switch (event.GetP16()) {
            case AVK_SELECT:    // when the SELECT key is pressed
                Terminate();
                result = true;
                break;
            case AVK_1:         // when the "1" key is pressed
                TRACE("key 1");
                if (MakeMy() == SFERR_NO_ERROR) {
                    result = true;
                }
                break;
            case AVK_2:         // when the "2" key is pressed
                TRACE("key 2");
                if (MakeMenu() == SFERR_NO_ERROR) {
                    result = true;
                }
                break;
            case AVK_3:         // when the "3" key is pressed
            TRACE("key 3");

                // make ItsWindow
                if (MakeIts() == SFERR_NO_ERROR) {

                    result = true;
                }
                break;
        }
    }
    return result;
}

Reference: Container(Basic)

3.6.2. Custom Container

Let's make the user-defined custom container with the frame ("CustomContainer") inheriting from the abstract container of SFYContainer as the figure below.

The dotted line will be drawn in the black color on the border of the real region(visible region) of custom container as a frame.

Figure 3.31. Custom container

Custom container

The following is the code to define and implement the user-defined custom container called "CustomContainer".

Example 3.52. Define CustomContainer class

// define the CustomContainer class
SFMTYPEDEFRESPONDER(CustomContainer)  //  macro to generate the useful types
class CustomContainer : public SFYContainer
{
    SFMSEALRESPONDER(CustomContainer)  //  macro to prohibit the developer from copying this instance

    // macro to specify the inheritance relation from SFYResponder to this class
    SFMRESPONDERINSTANTIATETHREE(CustomContainer, SFYContainer, SFYWidget, SFYResponder)

public:

    // since 4-character type of small alphabet and symbol is reserved 
    // define ('C', 'C', 'T', 'N') of capital alphabets for CustomContainer type
    enum CodeEnum {
        CODE_TYPE = four_char_code('C', 'C', 'T', 'N')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:

    static CustomContainerSmp NewInstance(SFCErrorPtr exception = null);

protected:

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

    // drawing handler
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

// constructor
CustomContainer::CustomContainer(Void) static_throws
{
    if (static_try()) {
        SetType(CODE_TYPE);
    }
}

// destructor
CustomContainer::~CustomContainer(Void)
{
}

// create CustomContainer instance 
CustomContainerSmp CustomContainer::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<CustomContainer>(Factory(:: new CustomContainer, exception));
}

// drawing handler of CustomContainer
Void CustomContainer::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    AEEStrokeStyle style;   // line type

    // save the line type before drawing
    style = graphics->GetStrokeStyle();

    // set the line type to dotted line
    graphics->SetStrokeStyle(STROKE_DOTTED);

    // calculate the visible region CustomContainer
    // visible region is real region of CustomContainer
    SFXRectangle rx;
    rx.Set(GetVirtualBound());
    rx.Set(SFXGrid(-rx.GetX(), -rx.GetY()), GetRealBound().GetSize());

    // draw the black dotted line on the border of the visible region
    graphics->DrawRectangle(rx, COLOR_BLACK);

    // restore the line type
    graphics->SetStrokeStyle(style);

    return;
}

The below is the updated code of the previous section in which the general purpose container of SFZContainer is replaced with the user-defined custom container of "CustomContainer".

[Note] Note
In this code, there is another specification change that the button control in the previous section is not placed in this user-defined custom container.

Example 3.53. 

// make the container and scroll bar control on ItsWindo
SFCError ItsWindow::Make(Void)
{
    SFYContainerSmp container;
    SFZContainerScrollBarControlSmp bar;
    SFCError error(SFERR_NO_ERROR);

    // *** updated code segments are in bold

    // create the custom container
    if ((container = CustomContainer::NewInstance(&error)) != null) {

        // set the container's parent responder to ItsWindow
        if ((error = container->SetParent(GetThis())) == SFERR_NO_ERROR) {

            // set the container's real region to the region obtained by deflating ItsWindow's local region by (5, 5, 10, 5)
            container->SetRealBound(GetLocalBound().Deflate(5, 5, 10, 5));

            // set the container's virtual region to the region obtained by expanding the container's real region down by 150
            container->SetVirtualBound(container->GetLocalBound().AddHeight(150));

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

            // the button control in the previous section is not placed //
        }
    }
    if (error == SFERR_NO_ERROR) {

        // create scroll bar control for container
        // ... (omitted) ...

    }
    return error;
}

Reference: Abstract Class that Represents a Container[SFYContainer]