Hello World example

Index

The Basics

// This header should be included from the main file of your application, typically main.cpp
// What ever file would normally contain the main() function for your program should include
// this file instead. It will also include omgui/app.h.
#include <omgui/main.h>

// This header is for the omgui::Window class.
#include <omgui/window.h>

// This is the application object for the program. Program execution is controlled
// by this object. All OMGUI applications must create an object derived from
// omgui::App and implement the omgui::App::init method. This method is called
// to initialize the application, creating its Windows and performing any other
// initialization tasks.
class HelloWorldApp : public omgui::App
{
public:
    bool init();
};

// This is the omgui::App::init method for the HelloWorldApp class.
// All it does is...
bool HelloWorldApp::init()
{
    // ...create a Window object...
    omgui::Window::create(omgui::Window::Initializer()
        // ...with "Hello World" as its title...
        .title(OMGUI_STR("Hello World"))
        // ...which is initially visible (Windows are hidden by default)...
        .show()
        );

    // ...and returns true to indicate that initialization was successful.
    // Returning false would indicate failed initialization, terminating the application.
    return true;
}

// The entry point for all OMGUI applications, this function is used instead of int main().
// Its job is to return an omgui::App instance which will run the application.
// Here, this function simply returns a new HelloWorldApp object, but it could also
// process the command line arguments and possibly return a different object.
omgui::App *omgui::main(const omgui::App::cmd_line &cmd)
{
    return new HelloWorldApp;
}
Back to top

Adding a Button

#include <omgui/main.h>
#include <omgui/window.h>

// These headers are for the omgui::TableLayout class and omgui::Button classes respectively
#include <omgui/tablelayout.h>
#include <omgui/button.h>

class HelloWorldApp : public omgui::App
{
public:
    bool init();
};

// Now, the init function is doing much more than it did before: it is creating
// a content panel for the Window and adding a Button to it. The content panel is the only
// child of a Window, occupying all of the client area of the Window. All of the other Widgets
// used by the application should be placed into this content panel. In this case, just a button.
bool HelloWorldApp::init()
{
    // This will be the content panel for the Window. A TableLayout is a Widget that can have children
    // and will arrange them in a tabular fashion based on information you provide. We will see this soon.
    omgui::Pointer<omgui::TableLayout> contentpanel = omgui::TableLayout::create(omgui::TableLayout::Initializer());

    // Here, we are creating the button...
    omgui::Pointer<omgui::Button> goodbyebutton = omgui::Button::create(omgui::Button::Initializer()
        // ...whose parent is the TableLayout we created before...
        .parent(contentpanel)
        // ...with a label "Goodbye World".
        .label(OMGUI_STR("Goodbye World"))
        // Note that you don't need to add a show() command here, as all Widgets (except Windows)
        // are shown by default.
        );
        
    // This is where we specify where the button should appear in the TableLayout.
    // The TableLayoutInfo class is used to pass information to the TableLayout, telling
    // it where to arrange the button. The TableLayout is very powerful, but for now we
    // will just align the button in the center with the omgui::ALIGN_CENTER flag.
    // Because this button is the only child of the TableLayout, we don't need to specify anything else.
    contentpanel->set_widget_layout_info(goodbyebutton, omgui::TableLayoutInfo().flags(omgui::ALIGN_CENTER));

    // Here we create the Window as usual, but with one additional argument.
    omgui::Window::create(omgui::Window::Initializer()
        .title(OMGUI_STR("Hello World"))
        // This sets the content panel of the Window to the TableLayout we created.
        .content_panel(contentpanel)
        .show()
        );

    return true;
}

omgui::App *omgui::main(const omgui::App::cmd_line &cmd)
{
    return new HelloWorldApp;
}
Back to top

Using Events

#include <omgui/main.h>
#include <omgui/window.h>
#include <omgui/tablelayout.h>
#include <omgui/button.h>

class HelloWorldApp : public omgui::App
{
public:
    bool init();

    // This will be the slot that is signaled when the button we create is activated
    bool on_button_activate(const omgui::Event &event);
};

// The only change here is to connect an event
bool HelloWorldApp::init()
{
    omgui::Pointer<omgui::TableLayout> contentpanel = omgui::TableLayout::create(omgui::TableLayout::Initializer());

    omgui::Pointer<omgui::Button> goodbyebutton = omgui::Button::create(omgui::Button::Initializer()
        .parent(contentpanel)
        .label(OMGUI_STR("Goodbye World"))
        );
    contentpanel->set_widget_layout_info(goodbyebutton, omgui::TableLayoutInfo().flags(omgui::ALIGN_CENTER));
    
    // Here we are connecting an event. The event we are connecting to is the ACTIVATE event,
    // which is signalled when the button is clicked or otherwise activated by the user.
    goodbyebutton->connect(omgui::Button::event_traits::ACTIVATE,
        // Here is where we create a slot to connect to the event. omgui::make_slot
        // is a handy template to simplify this process. The template argument is the kind of event
        // object the slot expects to recieve as its only argument. The arguments to the function
        // depend on what kind of slot is being connected. Here, we are using a member function,
        // so two arguments are necessary: the first to specify the member function, and the second
        // to specify what instance to invoke the member function with.
        omgui::make_slot<omgui::Event>(&HelloWorldApp::on_button_activate, *this));

    omgui::Window::create(omgui::Window::Initializer()
        .title(OMGUI_STR("Hello World"))
        .content_panel(contentpanel)
        .show()
        );

    return true;
}

// This is the slot that is signaled when the button is activated.
// For now, we are just telling the application to quit with a call to omgui::App::quit.
// The application won't quit immediately, so code after the quit call will still execute.
// By returning true, the slot is indicating that it processed the event. It could have returned
// false to indicate that it did not process the event. Whether an event is processed matters for
// certain kinds of events, but not this one.
bool HelloWorldApp::on_button_activate(const omgui::Event &event)
{
    quit();
    return true;
}

omgui::App *omgui::main(const omgui::App::cmd_line &cmd)
{
    return new HelloWorldApp;
}
Back to top

Using a custom Window class

#include <omgui/main.h>
#include <omgui/window.h>
#include <omgui/tablelayout.h>
#include <omgui/button.h>

// This is our custom omgui::Window widget. Up to now, we had been creating all our widgets
// in the init method of the application object. However, that isn't very modular, and modularity
// is an important part of GUI design. By creating our own Window object, we can create it's child Widgets
// here, instead of from the init function. This is done by connecting a slot to the CREATE event, which is
// signaled when the Widget is created, indicating that it is safe to add children to it.
//
// Its important to pay attention to some of the specifics of this class, as they are the conventions
// this library uses, which you should follow as well. The conventions are designed to help promote
// safe code.
class HelloWorldWindow : public omgui::Window
{
public:
    // This is called a "named constructor". Instead of having a normal constructor be public,
    // which would allow this object to be created on the stack (which will cause a segfault!),
    // this static method is used to create new objects on the heap using the new operator.
    // It's implementation is simple, and should be the same for all custom widgets you create.
    static omgui::Pointer<HelloWorldWindow> create(const HelloWorldWindow::Initializer &initializer, omgui::object_id id = omgui::OBJECT_ID_ANY);

protected:
    // Here is the actual constructor for our custom Window. It only takes an omgui::object_id
    // as its argument. You will see later that this constructor doesn't do very much on its own.
    HelloWorldWindow(omgui::object_id id);

    // This is the slot that will be signaled when our custom Window object is created.
    // It is where the children will be created.
    bool on_create(const omgui::Event &event);
    
    // Here is the event handler for activating the button. It has been moved here from the
    // application object to promote modularity.
    bool on_button_activate(const omgui::Event &event);
};

// Here is the constructor. All it does is connect slots to events we are interested in, which in
// this case is just the CREATE event. Note that while this constructor is executing, the actual
// widget does not really exist yet! If you tried to create new Widgets that were children of this one
// right now, you'd probably segfault! Instead, create child widgets in a CREATE slot.
HelloWorldWindow::HelloWorldWindow(omgui::object_id id):
omgui::Window(id)
{
    connect(event_traits::CREATE, omgui::make_slot<omgui::Event>(&HelloWorldWindow::on_create, *this));
}

// Here is the named constructor implementation. Its just three lines. Every single Widget in OMGUI
// has the same three lines for their named constructors (with type differences, of course).
// The call to initialize here is what actually creates the Widget. After that call is made, you can
// start adding children to the Widget. You shouldn't create them here though, use a CREATE slot as
// discussed previously.
omgui::Pointer<HelloWorldWindow> HelloWorldWindow::create(const HelloWorldWindow::Initializer &initializer, omgui::object_id id)
{
    omgui::Pointer<HelloWorldWindow> ptr = new HelloWorldWindow(id);
    ptr->initialize(initializer);
    return ptr;
}

// Here is the CREATE slot that adds child Widgets. Here, we again create the TableLayout content panel,
// add a button as a child, and connect to the buttons ACTIVATE signal.
bool HelloWorldWindow::on_create(const omgui::Event &event)
{
    omgui::Pointer<omgui::TableLayout> contentpanel = omgui::TableLayout::create(omgui::TableLayout::Initializer());

    omgui::Pointer<omgui::Button> goodbyebutton = omgui::Button::create(omgui::Button::Initializer()
        .parent(contentpanel)
        .label(OMGUI_STR("Goodbye World"))
        );
    contentpanel->set_widget_layout_info(goodbyebutton, omgui::TableLayoutInfo().flags(omgui::ALIGN_CENTER));
    goodbyebutton->connect(omgui::Button::event_traits::ACTIVATE,
        omgui::make_slot<omgui::Event>(&HelloWorldWindow::on_button_activate, *this));

    set_content_panel(contentpanel);
    return true;
}

// A slight difference in the slot for the ACTIVATE signal this time around. Because
// this slot is no longer inside the application object, it needs to obtain a reference
// to the application object so that the omgui::App::quit function can be invoked. That is
// done with a call to omgui::get_app(), which returns an omgui::App reference.
bool HelloWorldWindow::on_button_activate(const omgui::Event &event)
{
    omgui::get_app().quit();
    return true;
}

class HelloWorldApp : public omgui::App
{
public:
    bool init();
};

// Here, we create an instance of our HelloWorldWindow instead of a omgui::Window.
bool HelloWorldApp::init()
{
    HelloWorldWindow::create(HelloWorldWindow::Initializer()
        .title(OMGUI_STR("Hello World"))
        .show()
        );

    return true;
}

omgui::App *omgui::main(const omgui::App::cmd_line &cmd)
{
    return new HelloWorldApp;
}
Back to top

Adding Windows XP / Vista Visual Styles to your application

// Add this once anywhere in your program. The best place is in the file that includes <omgui/main.h>.
#ifdef _MSC_VER
// Enable visual styles
#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
Back to top

doxygen SourceForge.net Logo