Menus and Toolbars using Gtk::UIManager

Instead of creating menus and toolbars by hand you can also do this using the action-based API, with an XML description. This is the preferred way because it makes it much easier to customize the UI of an application and allows you to handle user actions regardless of whether they are initiated from a menu item or toolbar button. The use of Gtk::UIManager with maemomm does not differ much from gtkmm.

Normally, you would use the <menubar> element to create a menu with gtkmm. However, Hildon::Windows instead add the menu using set_menu(). To create this Gtk::Menu from a Gtk::UIManager you must use a <popup> XML item. This is demonstrated in the example.

Reference

Example

This example shows how to use the Gtk::UIManager with a Hildon::Window. See the Gtk::UIManager section of the gtkmm tutorial for a fuller explanation.

Figure 5.3. Menus and toolbars with UIManager

Menus and toolbars with UIManager

Source Code

File: examplewindow.h

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

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

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

protected:
  //Signal handlers:
  virtual void on_action_file_new();
  virtual void on_action_file_quit();
  virtual void on_action_others();

  //Child widgets:
  Gtk::VBox m_Box;

  Glib::RefPtr<Gtk::UIManager> m_refUIManager;
  Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
};

#endif //GTKMM_EXAMPLEWINDOW_H

File: examplewindow.cc

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

ExampleWindow::ExampleWindow()
{
  //Create actions for menus and toolbars:
  m_refActionGroup = Gtk::ActionGroup::create();

  //File|New sub menu:
  m_refActionGroup->add( Gtk::Action::create("FileNewStandard", Gtk::Stock::NEW, "_New", "Create a new file"),
    sigc::mem_fun(*this, &ExampleWindow::on_action_file_new) );

  m_refActionGroup->add( Gtk::Action::create("FileNewFoo", Gtk::Stock::NEW, "New Foo", "Create a new foo"),
    sigc::mem_fun(*this, &ExampleWindow::on_action_file_new) );

  m_refActionGroup->add( Gtk::Action::create("FileNewGoo", Gtk::Stock::NEW, "_New Goo", "Create a new goo"),
    sigc::mem_fun(*this, &ExampleWindow::on_action_file_new) );

  //File menu:
  m_refActionGroup->add( Gtk::Action::create("FileMenu", "File") );
  m_refActionGroup->add( Gtk::Action::create("FileNew", Gtk::Stock::NEW) ); //Sub-menu.
  m_refActionGroup->add( Gtk::Action::create("FileQuit", Gtk::Stock::QUIT),
    sigc::mem_fun(*this, &ExampleWindow::on_action_file_quit) );

  m_refUIManager = Gtk::UIManager::create();
  m_refUIManager->insert_action_group(m_refActionGroup);
 
  add_accel_group(m_refUIManager->get_accel_group());

  //Layout the actions in a menu and toolbar. In Hildon you have to use "popup" for the menu because you can only have one menu
  // and cannot add a whole menubar.
  
  Glib::ustring ui_info = 
        "<ui>"
        "    <popup action='FileMenu'>"
        "      <menu action='FileNew'>"
        "        <menuitem action='FileNewStandard'/>"
        "        <menuitem action='FileNewFoo'/>"
        "        <menuitem action='FileNewGoo'/>"
        "      </menu>"
        "      <separator/>"
        "      <menuitem action='FileQuit'/>"
        "    </popup>"
        "  <toolbar  name='ToolBar'>"
        "    <toolitem action='FileNewStandard'/>"
        "    <toolitem action='FileQuit'/>"
        "  </toolbar>"
        "</ui>";

  std::auto_ptr<Glib::Error> ex;
  m_refUIManager->add_ui_from_string(ui_info, ex);
  if(ex.get())
  { 
    std::cerr << "building menus failed: " <<  ex->what();
  }
 
  //Get the menu and toolbar widgets, and add them to a container widget:
  Gtk::Menu* pMenu = dynamic_cast<Gtk::Menu*>(m_refUIManager->get_widget("/FileMenu"));
  if(pMenu)
    set_main_menu(*pMenu);

  Gtk::Toolbar* pToolbar = dynamic_cast<Gtk::Toolbar*>(m_refUIManager->get_widget("/ToolBar"));
  if(pToolbar)
    add_toolbar(*pToolbar);
  
  // TODO:  bug #875 
  show_all();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_action_file_quit()
{
  hide(); //Closes the main window to stop the Gtk::Main::run().
}

void ExampleWindow::on_action_file_new()
{
   std::cout << "A File|New menu item was selected." << std::endl;
}

void ExampleWindow::on_action_others()
{
  std::cout << "A menu item was selected." << std::endl;
}

File: main.cc

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

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

  osso_context_t* osso_context = osso_initialize("example", "0.0.1", TRUE /* deprecated parameter */, 0 /* Use default Glib main loop context */);
  if(!osso_context)
    std::cerr << "osso_initialize() failed." << std::endl;
  
  Glib::set_application_name("UIManager example");

  // Create Window and set it to Program
  ExampleWindow window;
  Hildon::Program::get_instance()->add_window(window);

  // Begin the main application
  kit.run(window);
	
  osso_deinitialize(osso_context);

  return 0;

}