GEOS-SC : Flex UI : Sections : How To Write An Application

Introduction | Terminology | How To Write An Application | How To Detect User Interaction | How To Bring Everything Together


The Flex UI provides the visual interface between the user and the system. This example will create a simple application that displays the text, "Hello World!" by using the following Flex UI components:

To write an application that displays the text, "Hello World!":

  1. Declare the class HelloApp in the header file.
  2. Register the application with the system.
  3. Add the constructor to initialize the variables in the application.
  4. Add SetAppContext() to check if the user interface has been built.
  5. Add a frame to the application.
  6. Create a layout to manage the user interface.
  7. Add a label to the frame and make the user interface visible.
  8. Add the method Exit() to clean up the user interface.
  9. Compile and run the application.


Declare the class HelloApp in the header file. (resource | header | source)


class HelloApp : public AppBase {
 public:
    // Constructor - initializes member data
    HelloApp();

    // Override SetAppContext to create the user interface for
    // the application.
    virtual void SetAppContext(const TCHAR *context);

    // Override Exit to destroy the user interface for
    // the application.
    virtual void Exit(void);

 private:
    // Helper function to create the user interface for the application.
    Result BuildHelloAppUI(void);

    // Class variables
    FlexFrame   *_helloAppMainFrame;      // The main frame of the application.
    Boolean     _helloAppUIBuilt;       // If the application is currently running.
};

Declaring HelloApp as a descendant of the AppBase class lets the system know that HelloApp is an application.

The AppBase method SetAppContext() builds the user interface each time that the application is loaded. The AppBase method Exit() destroys the user interface each time that the application is exit.


Register the application with the system and create a new instance of it by subclassing the ResidentApplication class. (resource | header | source)

// Strings that are not user-visible and should not be localized.
const TCHAR *HELLOAPP_NAME = _TEXT("helloUI");

// Register the application.
class HelloAppResidentApplication : public ResidentApplication 
{
 public:
    HelloAppResidentApplication() : ResidentApplication(HELLOAPP_NAME) 
    {};
    virtual AppBase *CreateAppBase(void) 
    {
        return new HelloApp;
    }
};
static HelloAppResidentApplication helloApp;

// Specify the name of the application.
static AppNameAttribute helloAppName(&helloApp, HELLOAPP_APP_TEXT);


Subclass the ResidentApplication class to create a new application class and declare an instance of this new class. The system will look for this instance to start the application.

Use AppNameAttribute to hold the name of the application. The text string HELLOAPP_NAME specifies the name of the application to the system.


Add the constructor to explicitly initialize the variables in the application. (resource | header | source)


HelloApp::HelloApp() : _helloAppMainFrame(NULL), _helloAppUIBuilt(FALSE)
{
}

The constructor is called whenever an instance of the application is created.


Add the method SetAppContext() to build the user interface if it does not exist. resource | header | source)


void
HelloApp::SetAppContext(const TCHAR *context)
{
    if (!_helloAppUIBuilt) {
        if (BuildHelloAppUI() != SUCCESS) {
            EC_WARN("Unable to build user interface.");
            Exit();
        } else {
            _helloAppUIBuilt = TRUE;
        }
    }
    // Pass context to the USE_IT macro to suppress compiler warnings.
    USE_IT(context);
}

Use the Boolean _helloAppUIBuilt to determine if the user interface has already been built. If it has not been built, call the helper function BuildHelloAppUI() to build it. If BuildHelloAppUI() fails, we exit the application, otherwise _helloAppUIBuilt is set to TRUE.

Since the context of this application is not used, pass the context parameter to the macro USE_IT to suppress compiler warnings about unused paramters.


Add a frame to the application to hold the elements of the user interface. (resource | header | source)

void
HelloApp::SetAppContext(const TCHAR *context)
{
    // Create a frame to hold the user interface of our application
    _helloAppMainFrame = 
        theUIFactory->CreateFlexFrame(HINT_FRAME_WITH_NO_CLOSE_BUTTON,
				      HELLOAPP_APP_TEXT);
    if (NULL == _helloAppMainFrame) {
        EC_WARN("Unable to create the main frame.");
        return FAILURE;
    }

    // Attempt to add the main window to the application.
    if (Add(_helloAppMainFrame) != SUCCESS) {
        EC_WARN("Unable to add the main frame.");
        delete _helloAppMainFrame;
        return FAILURE;
    }

We pass only two arguments, look and title, to the CreateFlexFrame() method, because these are the only attributes we want to set explicitly. The other arguments (width, height, xPos, yPos) are set to their default values.

The method Add() attaches the _helloAppMainFrame to the application. To prevent a memory leak, you must delete any component if it is not successfully added to the application base or to another component that is attached to the application base. Objects that are successfully added to the application base, either directly or through another object, will be deleted by the system when the application exits.


Create a layout to manage the user interface in BuildHelloAppUI(). (resource | header | source)


    // Create a flow layout that centers the components horizontally.
    HorizontalFlowLayout *frameLayout = new HorizontalFlowLayout(0);
    if (NULL == frameLayout) {
        EC_WARN("Unable to create layout.");
        return FAILURE;
    }
    _helloAppMainFrame->SetLayout(frameLayout);

Use the new operator to create a layout for the frame. A layout manages the display of Flex UI items for a specified FlexContainer. In this example, the HorizontalFlowLayout will position a FlexLabel for the frame. Since the HorizontalFlowLayout will manage only one component, we don't care about the gap between components.

Variations: There are three types of layouts: HorizontalFlowLayouts, VerticalFlowLayouts, and DialogLayouts.


Add a label to the frame and make the user interface visible to the user. (resource | header | source)


    // Create a label to display the text.
    FlexLabel *helloLabel = theUIFactory->CreateFlexLabel();
    if (NULL == helloLabel) {
        EC_WARN("Unable to create the label.");
        return FAILURE;
    }
    // Attempt to add the label to the frame.
    if (_helloAppMainFrame->Add(helloLabel) != SUCCESS) {
        EC_WARN("Unable to add label to the frame.");
        delete helloLabel;
        return FAILURE;
    }
    // Set the label text.
    helloLabel->SetText(HELLOAPP_TEXT);

    // Make the main window visible.
    _helloAppMainFrame->SetVisible(TRUE);

    // Return SUCCESS once we have built all of the user interface.
    return SUCCESS;

}

The method Add() makes helloLabel a child of the _helloAppMainFrame component.

The method SetText() sets the string HELLOAPP_TEXT as the label for the component helloLabel.

Once is attached, use the method SetVisible() to make the application's user interface visible to the user.


Override the method Exit() to clean up the user interface when the application is hidden. (resource | header | source)

void
HelloApp::Exit(void)
{
    // Delete the layout for the main frame.
    if (_helloAppMainFrame) {
        delete _helloAppMainFrame->RemoveLayout();
    }    

    // Set the boolean for the application.
    _helloAppUIBuilt = FALSE;

    AppBase::Exit();
}

You must delete any object that were not created by theUIFactory. The system deletes objects that were created by theUIFactory and successfully added to the application base in the AppBase method Exit().


Compile and run the application.


Introduction | Terminology | How To Write An Application | How To Detect User Interaction | How To Bring Everything Together