Back to Index

Table of contents

  1. Adding more widgets to the "Hello World" application
  2. Building the application

Maemo for mobile developers

Adding more widgets to the "Hello World" application

This section demonstrates how the developer can add some GTK widgets to take our Hello World application to a richer and more customized UI interaction space. Furthermore, it will show how the developer can make use of these widgets in their function definitions. It can also serve as an introduction to the implementation of simple the maemomm API functions for the widgets listed bellow.

Note: The newly added lines to our existing code will be in red.

Container Widgets

The two types of container widgets explained bellow, namely VBox and HBox, will be used in our API implementation for the other widgets organization within our hello world application.

Vbox

Vbox is a vertical container box widget, which we can use to organize child widgets into a single column.

HBox

HBox is a horizontal container box widget, which we can use to organize child widgets into a single row.

Adding the following lines to mywindow.h header file, the new Layout Container widgets listed above will be declared:

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
        /* Widgets */
        Gtk::VBox m_frame_box;
        Gtk::HBox m_hbox_textbox;
        Gtk::HBox m_hbox_button;
        ...
};

Now that we have declared these container widgets in our header file, we can go to the source file mywindow.cpp and modify our class constructor so that we attach the main frame box to the window application, allocate enough space for it, and add the widgets to the boxes:

...
MyWindow::MyWindow() :
        ...
{       ...
	/* Attach the frame_box to window application */
        add(m_frame_box);
        ...
	/* All widgets should use the same amount of space */
	m_hbox_button.set_homogeneous(true);
	m_frame_box.set_homogeneous(true);
        ...
	/* Adding the widgets to boxes */
	m_hbox_button.pack_start(m_button, Gtk::PACK_SHRINK);
	m_hbox_textbox.pack_start(m_label);
	m_hbox_textbox.pack_start(m_entry);
	m_hbox_textbox.pack_start(m_image);
	m_frame_box.pack_start(m_hbox_textbox);
        m_frame_box.pack_start(m_hbox_button, Gtk::PACK_SHRINK);
        ...

Label Widget

A widget that is designed to display a small to medium amount of text. It is a simple setable widget for holding a string. Add the following line to declare the Label widget in our mywindow.cpp header file:

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
        /* Widgets */
        Gtk::Label m_label;
        ...
};

Now, we can go to our mywindow.cpp source file and add the following line to set the Label Widget's properties:

...
MyWindow::MyWindow() :
        ...
	m_label("Type some text"),
        ...
{       ...
	/* Adding the widgets to boxes */
        m_hbox_textbox.pack_start(m_label);
	...

Note:The main label's value is already passed to the textbox widget in previous steps.

Text Box Widget

This widget will allow you to enter a single line to a text entry field. A fairly large set of key bindings are suported by default. If the entered text is longer than the allocation of the widget, the widget will scroll so that the cursor position is visible. Add the following lines to our mywindow.h header file to declare the text box widget:

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
	/* Signal handlers */
        virtual void on_menu_helloworld_entry();
...
        /* Widgets */
        Gtk::Entry m_entry;
        Gtk::Entry m_tb_entry;
        ...
};

In your mywindow.cpp source file class constructor, you will set the text property to your text box by calling the member function set_text(). Additionaly, you will call the add() function passing the entry value to the toolbar entry widget:

...
MyWindow::MyWindow() :
        ...
{
	m_tool_entry.add(m_tb_entry);
        ...
	/* Sets the "text" property to the value of entry. */
	m_entry.set_text("My \"Hello World!\"");
	...
	/* Adding the widgets to boxes */
        m_hbox_textbox.pack_start(m_entry);
	...

Note:The main entry's value is already passed to the textbox widget in the previous step.

Callback function, which will be called when the "Say Hello from text box" menu is activated

...
void MyWindow::on_menu_helloworld_entry()
{
        Hildon::Note helloworld_note(Hildon::NOTE_TYPE_INFORMATION_THEME, m_entry.get_text());
        helloworld_note.run();
}
...

The image shown here, illustrates the application run of the Label and TextBox Widgets' implementations:

Button Widget

The Button widget is generally used to attach a function that is called when the button is pressed. Additionally, it can hold any valid child widget (e.g. Gtk::Label).

For the Button widget declaration, add the following line to your mywindow.h header file:

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
        /* Widgets */
        Gtk::Button m_button;
        ...
};

Now on your mywindow.cpp source file, we will modify our class constructor so that the quit button will have a label property, the signal emmited by the button when it's pressed attached to an appropriate callback function:

...
MyWindow::MyWindow() :
        ...
	m_button("Quit"),
	...
{       ...
	/* Attach the callback function to signal handler signal */
	m_button.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_menu_quit));
        ...
	/* Adding the widgets to boxes */
        m_hbox_button.pack_start(m_button, Gtk::PACK_SHRINK);
	...

Note:The button widget is already added to the main window by the container button widget in the previous step.

The image shown here, illustrates the application run of the Button Widget's implementations:

Toolbars and Icons Widgets

In order to build our toolbar containing the necessary buttons and their respective icons as well as other items, we will be implementing the following widgets:

Toolbar

A widget designed to implement bars with capacity to hold buttons and other widgets.

ToolButton

A Gtk::ToolItem widget containing a button that can be associated with an icon (e.g. open, save).

SeparatorToolItem

A toolbar item that separates groups of other toolbar items.

ToolItem

As its name suggests, it is a widget that can hold other widgets within our toolbar.

Add the following lines to our header file to declare the above widgets:

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
        /* Signal handlers */
        virtual void on_open_click();
        virtual void on_save_click();
        virtual void on_open_click();
        virtual void on_save_click();
        ...

        /* Toolbar */
        Gtk::Toolbar m_toolbar;
        Gtk::ToolButton m_tool_open;
        Gtk::ToolButton m_tool_save;
        Gtk::SeparatorToolItem m_tool_separator;
        Gtk::ToolItem m_tool_entry;
        ...
};

Now that we have declared our toolbar and icons in our header file, we will turn to the mywindow.cpp source file and modify our constructor class accordingly.

We will add the toolbar items to the toolbar by calling the append() function with the item widgets values passed. Then we will add the toolbar and show the items in the main window. We will also connect the signal emitted by the clicked open and save buttons to the signal handler callbacks:

...
MyWindow::MyWindow() :
        ...
	m_tool_open(Gtk::Stock::OPEN),
	m_tool_save(Gtk::Stock::SAVE),
        ...
{       ...
	m_tool_entry.add(m_tb_entry);
	m_tool_entry.set_expand();
        ...
	/* Add Tollbar items to Toolbar */
	m_toolbar.append(m_tool_open);
        m_toolbar.append(m_tool_save);
        m_toolbar.append(m_tool_separator);
        m_toolbar.append(m_tool_entry);
	/* Add ToolBar */
        add_toolbar(m_toolbar);
        m_toolbar.show_all();
	...
	/* Attach the callback function to signal handler signal */
	m_tool_open.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_open_click));
	m_tool_save.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::on_save_click));
	...

Note:Previously we have called the add() member function to pass the value of the text entry to our toolitem widget. Now we add the line with the set_expand() member function call to set whether the toolitem is allocated extra space when there is more room on the toolbar than needed for the items.

Note also, that the signal_clicked() function is used in conjunction with connect() so that an "on_menu_quit" signal is emmited when the button is clicked.

Callback function which is called when the "open" toolbar icon is clicked:

...
void MyWindow::on_open_click()
{
        Hildon::FileChooserDialog dialog(*this, Gtk::FILE_CHOOSER_ACTION_OPEN);

        /* Show the dialog and wait for a user response: */
        int response = dialog.run();

        if (response == Gtk::RESPONSE_OK) {
                std::string filename = dialog.get_filename();
                m_tb_entry.set_text(filename.c_str());
        }
}
...

Callback function which is called when the "save" icon on the toolbar is clicked:

...
void MyWindow::on_save_click()
{
        std::ofstream file;

        file.open(m_tb_entry.get_text().c_str());
        if (!file) {
                Gtk::MessageDialog dialog(*this, "File cannot be saved!", false, Gtk::MESSAGE_ERROR);
                dialog.set_title("Error");
                dialog.run();
        } else {
                file.close();
                std::remove(m_tb_entry.get_text().c_str());
                file.open(m_tb_entry.get_text().c_str(), std::ios::trunc);
                file << m_entry.get_text().c_str();
                Gtk::MessageDialog dialog(*this, "File saved!");
                dialog.set_title("Info");
                dialog.run();
        }

        file.close();
}

Image Widgets

As it is defined, this widget is used to display images. We will be able to display various kinds of image objects (e.g. pixel buffer) from a file, and then display them. Add the following line to our header file:

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
        /* Widgets */
       Gtk::Image m_image;
        ...
};

Again, we will turn to our mywindow.cpp source file to make the necessary modifications in our Class Constructor. Our Image property settings will be a stock help image with with the dialog sized icon:

...
MyWindow::MyWindow() :
        ...
	m_image(Gtk::Stock::HELP, Gtk::ICON_SIZE_DIALOG),
        ...
{       ...
	/* Adding the widgets to boxes */
	m_hbox_textbox.pack_start(m_image);

Note:The main image value is passed by the pack_start() method to the Container widget as previously shown.

In addition to the old widgets already gone through, the image shown bellow illustrates the application running with the implementation of the Toolbars, Icons, and Image Widgets:

File Chooser Widgets

A Child widget that serves as an item for the menus. It handles highlighting, events and submenus.

...
class MyWindow : public Hildon::Window
{
public:
        ...
protected:
	/* Signal handlers */
       virtual void on_menu_helloworld_file();
	...
        /* The menu items */
       Gtk::MenuItem m_item_helloworld_entry;
       Gtk::MenuItem m_item_helloworld_file;
        ...
};

Turning to our mywindow.cpp source file, we will set the following properties inside our class constructor. We will just hardcode a text message both to our entry and file objects, add the items to the menu then handle the signal emitted with the callback functions:

...
MyWindow::MyWindow() :
        ...
	m_item_helloworld_entry("Say \"Hello\" From Text Box"),
        m_item_helloworld_file("Say \"Hello\" From File"),
        ...
{       ...
	/* Add items to the menu */
	m_main.append(m_item_helloworld_entry);
	m_main.append(m_item_helloworld_file);
	...
	/* Attach the callback function to signal handler signal */
	m_item_helloworld_entry.signal_activate().connect(sigc::mem_fun(*this, &MyWindow::on_menu_helloworld_entry));
	m_item_helloworld_file.signal_activate().connect(sigc::mem_fun(*this, &MyWindow::on_menu_helloworld_file));
	...

Note:The signal_activate(), which is a member functions of the Gtk::Action will be used to trigger the "activate" signal. The connect() is then called as well to provide a timeout handler for the menu items.

Callback function, which will be called when the "Say Hello from file" menu is activated:

...
void MyWindow::on_menu_helloworld_file()
{
        std::string line="";
        std::fstream file;

        file.open(m_tb_entry.get_text().c_str());

        if (!file) {
                std::cerr << "File cannot be opened!" << std::endl;
                Gtk::MessageDialog dialog(*this, "File cannot be open!", false, Gtk::MESSAGE_ERROR);
                dialog.set_title("Error");
                dialog.run();
        } else {
                std::getline (file,line);
                Hildon::Note helloworld_note(Hildon::NOTE_TYPE_INFORMATION_THEME, line);
                helloworld_note.run();
        }

        file.close();
}
...

Dialog Box Widgets

The object used to create a confirmation dialog box:

...
class MyWindow : public Hildon::Window
{
public:
        ...

protected:
	/* Signal handlers */
        bool on_delete_event(GdkEventAny *);
	virtual void on_note_response(int);
        ...
	/* Quit confimation dialog box */
	Hildon::Note m_note;
	
};

On our mywindow.cpp source file we will modify our class constructor to set a note to the Dialog widget, then add a response to the button according to the yes/no choice:

...
MyWindow::MyWindow() :
        ...
	m_note(Hildon::NOTE_TYPE_CONFIRMATION_BUTTON, "Quit application?")
{       ...
	/* Add dialog box buttons */
	m_note.add_button(Gtk::Stock::YES, Gtk::RESPONSE_YES);
        m_note.add_button(Gtk::Stock::NO, Gtk::RESPONSE_NO);
	...
	/* Attach the callback function to signal handler signal */
	m_note.signal_response().connect(sigc::mem_fun(*this, &MyWindow::on_note_response));
	...

Note:This signal_response() is connected in the Dialog Box response (emitted when the user clicks Yes or No). It is an unusual way to handle dialog boxes, but it's the GTK implementation.

The callback functions which will be called to close the application, displaying the quit confirmation dialog box:

...
MyWindow::MyWindow() :
        ...
{       ...
	/* Handle click on X button in the title bar */
	this->signal_delete_event().connect(sigc::mem_fun(*this, &MyWindow::on_delete_event));
	...
}
...
bool MyWindow::on_delete_event(GdkEventAny *event)
{
        m_note.run();
        return true;
}
...

This callback is the "Quit" confirmation dialog box response handler. This code will verify the user response, closing the application on Yes or closing the dialog box on No.

...
/* Note response handler */
void MyWindow::on_note_response(int response_id)
{
        if (response_id == Gtk::RESPONSE_YES) {
                /* Close the window */
                this->hide();
        } else {
                /* Close the dialog box */
                m_note.hide();
        }
}
...

Note:The signal_delete_event(), which is a Gtk::Widget member function and will emmit a "delete_event" signal at user request when the top level windown is closed needs to be defined in our class constructor.

Building the application

Includes

Before we go on to the next step which is to build our application and run it, we need to add the following #include lines to our mywindow.cpp source code to access the necessary header files:

#include <fstream>
#include <hildon-fmmm.h>
#include <iostream>
...

Building the application with gcc

After you write the source code above, you can build your program with gcc using this command:

Note: This is not the same command used to build the first "Hello World!". Here, a new library "hildon-fmmm" is used.

[sbox-SDK_X86: ~] > g++ main.cpp mywindow.cpp -o maemo_hello `pkg-config hildonmm hildon-fmmm --cflags --libs`

And run with:

[sbox-SDK_X86: ~] > run-standalone ./maemo_hello

Below is a screenshot of the view you should see now. The application has a main menu, a label, a text box, an image, a button, and a tollbar with "open" and "save" icons and a text box for address files.

Press the Hello World drop-down menu which contains the "Say Hello", "Say Hello from text box", "Say Hello from file", and "Exit" options to choose from, as the following image shows:

Click the "Say Hello" option, and as the following image shows, a Hello World message with an "OK" button is displayed. Click "OK".

Click the "Say Hello From Text Box" option, and as the following image shows, the text with an "OK" button is displayed. Click "OK":

Note: If you change the text in the text box, the message popup will change, too.

Click the "Open" icon in the toolbar, and the as the following image shows, a File Chooser Dialog appears. Select the file "foo.txt", and click "Select":

As the following image shows, the file path of "foo.txt" was put in the text box in the toolbar:

Now, click the save icon in the toolbar, and the file "foo.txt" will be saved with the text in the text box, "My Hello World!" by default. A message dialog to confirm the save is displayed:

Select the "Say Hello From File" option from the drop-down menu, and the contents of the "foo.txt" file with an "OK" button is displayed. Click "OK":

If you try to save or open files that do not exist, the error handling will be called and the "Error" popups are shown.

If you click Menu and then Exit, a Dialog Box asking for confirmation to close the application appears.

The maemo "Hello World" source code is available here.

Using Eclipse with ESbox