Menus

There are two ways to create menus with maemomm. The Maemo Human Interface Guidelines recommend the use of Hildon::AppMenu, which provides a menu containing a number of entries as Gtk::Buttons, organised in columns if necessary. This menu can be attached to a Hildon::Program instance, and made common to the whole application, or attached to a Hildon::Window so that different menus can be used.

Gtk::Menus can be used in maemomm, but this is not recommended as of Maemo 5.

AppMenu

The Maemo Human Interface Guidelines recommend Hildon::AppMenu for implementing menus with maemomm. Hildon::AppMenu is derived from Gtk::Window, and can contain Gtk::Buttons as well as groups of filter buttons (Gtk::ToggleButtons and Gtk::RadioButtons).

A Gtk::Button is added to a Hildon::AppMenu with the append(), insert() or prepend() methods. A filter button is added with the add_filter() method. A list of either the "items", i.e. normal Gtk::Buttons, or the "filters", i.e. Gtk::ToggleButtons and Gtk::RadioButtons, can be retrieved with the get_items() and get_filters methods, respectively.

Example

This example shows how to attach a Hildon::AppMenu, containing Gtk::Buttons, Gtk::RadioButtons and Gtk::ToggleButtons, to a Hildon::Program. Clicking any of the buttons sends output to the terminal.

Figure 4.15. AppMenu

AppMenu

Source Code

File: examplewindow.h

#ifndef _MAEMOMM_EXAMPLEWINDOW_H
#define _MAEMOMM_EXAMPLEWINDOW_H

#include <hildonmm/window.h>
#include <hildonmm/app-menu.h>
#include <gtkmm/button.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/togglebutton.h>
#include <gtkmm/label.h>

class ExampleWindow : public Hildon::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

private:
  // Signal handlers:
  void on_button1_clicked();
  void on_button2_clicked();
  void on_radio_toggled();
  void on_toggle1_toggled();
  void on_toggle2_toggled();

  // Child widgets:
  Hildon::AppMenu menu_;
  Gtk::Button button1_;
  Gtk::Button button2_;
  Gtk::RadioButton radio1_;
  Gtk::RadioButton radio2_;
  Gtk::ToggleButton toggle1_;
  Gtk::ToggleButton toggle2_;
  Gtk::Label label_;
};

#endif /* _MAEMOMM_EXAMPLEWINDOW_H */

File: main.cc

#include <hildonmm.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);
  Hildon::init();

  ExampleWindow window;
  Hildon::Program::get_instance()->add_window(window);

  kit.run(window); //Shows the window and returns when it is closed.

  return 0;
}

File: examplewindow.cc

#include "examplewindow.h"
#include <hildonmm/program.h>
#include <iostream>

ExampleWindow::ExampleWindow() :
  button1_("Button 1"),
  button2_("Button 2"),
  radio1_("Radio 1"),
  radio2_("Radio 2"),
  toggle1_("Toggle 1"),
  toggle2_("Toggle 2"),
  label_("Hildon::AppMenu example. Click window title to display menu.")
{
  set_title("Hildon::AppMenu Example");
  Hildon::Program::get_instance()->set_common_app_menu(menu_);

  // Setup radio buttons to be in one group.
  radio1_.set_active();
  Gtk::RadioButton::Group radio_group = radio1_.get_group();
  radio2_.set_group(radio_group);

  // Add buttons and filters to AppMenu.
  menu_.append(button1_);
  menu_.append(button2_);
  menu_.add_filter(radio1_);
  menu_.add_filter(radio2_);
  menu_.add_filter(toggle1_);
  menu_.add_filter(toggle2_);

  add(label_);

  // Connect signal handlers.
  button1_.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_button1_clicked));
  button2_.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_button2_clicked));
  radio1_.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_radio_toggled));
  toggle1_.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_toggle1_toggled));
  toggle2_.signal_clicked().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_toggle1_toggled));

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_button1_clicked()
{
  std::cout << "Button 1 clicked" << std::endl;
}

void ExampleWindow::on_button2_clicked()
{
  std::cout << "Button 2 clicked" << std::endl;
}

void ExampleWindow::on_radio_toggled()
{
  std::cout << "Radio button toggled, current state: Radio 1=" <<
    radio1_.get_active() << ", Radio 2=" << radio2_.get_active() << std::endl;
}

void ExampleWindow::on_toggle1_toggled()
{
  std::cout << "Toggle 1 toggled, current state=" << toggle1_.get_active() <<
    std::endl;
}

void ExampleWindow::on_toggle2_toggled()
{
  std::cout << "Toggle 2 toggled, current state=" << toggle2_.get_active() <<
    std::endl;
}

Gtkmm menus

Menus in maemomm can also use gtkmm menu functions, although the menu is then attached to the Hildon::Program/Hildon:Window and appears in the title bar. A Gtk::Menu can be created and attached to the Hildon::Program to be used as a common menu for all Hildon::Windows that don't have their own menu. Another way is to use a Gtk::Menu in a Hildon::Window. In this way every application window can have a different menu.

gtkmm menus can be created either manually or using Gtk::UIManager. The Gtk::UIManager is an action-based API used to create menus and toolbars using an XML description. We will first show the manual way and introduce you to Gtk::UIManager in the section Menus and Toolbars using Gtk::UIManager

Hildon::Window Reference

Gtk::Menu Reference

// In constructor of window
set_main_menu(main);

This is the only line that differs from the equivalent gtkmm example program. It specifies what menu to use for the application.

Example

This example creates a menu with a submenu. This submenu contains radio menu items and check menu item, all of which can be toggled. The last item in the menu (Close) is attached to a signal handler so that the application can also be closed from the menu.

This example also shows how to derive your own window class from Hildon::Window:

Figure 4.16. Menu

Menu

Source Code

File: examplewindow.h

#ifndef _MAEMOMM_EXAMPLEWINDOW_H
#define _MAEMOMM_EXAMPLEWINDOW_H

#include <hildonmm/window.h>
#include <gtkmm.h>

class ExampleWindow : public Hildon::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

private:
  // Signal handlers:
  void on_menu_radio1();
  void on_menu_radio2();
  void on_menu_check();
  void on_menu_close();

  // Child widgets:
  Gtk::Menu main_;
  Gtk::Menu sub_others_;

  Gtk::MenuItem item_others_;
  Gtk::RadioMenuItem::Group group_;
  Gtk::RadioMenuItem item_radio1_;
  Gtk::RadioMenuItem item_radio2_;

  Gtk::CheckMenuItem item_check_;
  Gtk::CheckMenuItem item_close_;
  Gtk::SeparatorMenuItem item_separator_;
};

#endif /* _MAEMOMM_EXAMPLEWINDOW_H */

File: main.cc

#include <hildonmm.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  // Initialize gtkmm:
  Gtk::Main kit(&argc, &argv);
  Hildon::init();
  
  // Create Window and set it to Program.
  ExampleWindow window;
  Hildon::Program::get_instance()->add_window(window);
  
  // Add example label to window.
  Gtk::Label label("Menu example");
  window.add(label);
  label.show();
  
  // Begin the main application.
  kit.run(window);

  return 0;
}

File: examplewindow.cc

#include "examplewindow.h"
#include <gtkmm.h>
#include <iostream>

ExampleWindow::ExampleWindow() :
  item_others_("Others"),
  item_radio1_(group_, "Radio1"),
  item_radio2_(group_, "Radio2"),  
  item_check_("Check"),
  item_close_("Close")
{
  set_title("Menu Example");

  // Add menu items to right menus.
  main_.append(item_others_);
  sub_others_.append(item_radio1_);
  sub_others_.append(item_radio2_);
  sub_others_.append(item_separator_);
  sub_others_.append(item_check_);
  main_.append(item_close_);
 
  // Add others submenu to the "Others" item.
  item_others_.set_submenu(sub_others_);
  main_.show_all_children(); //Show the main menu and all its child widgets.
  set_main_menu(main_);
  
  // Attach the callback functions to the activate signal.
  item_radio1_.signal_toggled().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_menu_radio1));
  item_radio2_.signal_toggled().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_menu_radio2));
  item_check_.signal_toggled().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_menu_check));
  item_close_.signal_activate().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_menu_close));
  
  // Make all child widgets visible:
  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_menu_radio1()
{
  std::cout << "Menu radioitem1 toggled. Current state=" <<
    item_radio1_.get_active() << std::endl;
}

void ExampleWindow::on_menu_radio2()
{
  std::cout << "Menu radioitem2 toggled. Current state=" <<
    item_radio2_.get_active() << std::endl;
}

void ExampleWindow::on_menu_check()
{
  std::cout << "Menu chickitem toggled. Current state=" <<
    item_check_.get_active() << std::endl;
}

void ExampleWindow::on_menu_close()
{
  hide();
}

The documentation for the standard gtkmm menu API can be found in the gtkmm tutorial.