Chapter 10. Menus and Toolbars

Table of Contents

Menus
The MenuBar
Menus and Menu Items
Popup Menus
Examples
Toolbars
Example

Menus

The MenuBar


Google

Gtk::MenuBar is a container that holds child Gtk::Menus.

Actually, it contains child Gtk::MenuItem, which contain Gtk::Menus in turn, but that uninteresting detail is hidden when using the STL-style interface. You may choose to use the non-STL-interface, using methods such as Gtk::MenuShell::append()), but that would be much more tedious.

Figure 10.1. MenuBar

The child items of both MenuBars and Menus can be accessed via the items() method, defined in their common base class, Gtk::MenuShell. Use the Gtk::Menu_Helpers::MenuElem helper class to add menus to the menu bar. For instance,

Gtk::MenuBar m_MenuBar;
Gtk::Menu m_Menu_File, m_Menu_Edit;
...
m_MenuBar.items().push_back( Gtk::Menu_Helpers::MenuElem("_File", m_Menu_File) );
m_MenuBar.items().push_back( Gtk::Menu_Helpers::MenuElem("_Edit", m_Menu_Edit) );

You can add stock menus by using the StockElem helper, like so:

m_MenuBar.items().push_back( Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::HELP, m_Menu_Help) )

Reference

Menus and Menu Items

Gtk::Menu contain child Gtk::MenuItems. MenuItems can, in turn, contain child Menus, to create sub menus.

Figure 10.2. Menu

As when adding menus to the menu bar, use the STL-style interface and the Gtk::Menu_Helpers to add the menu items. You may specify the signal handler to be called when the user chooses the menu item. For instance:

 Gtk::Menu::MenuList& menulist = m_Menu_Edit.items();

 menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Copy",
  SigC::slot(*this, &ExampleWindow::on_menu_others) ) );

 menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Paste",
  SigC::slot(*this, &ExampleWindow::on_menu_others) ) );

You may also specify stock items (StockMenuElem), radio button items (RadioMenuElem), check button items (CheckMenuElem) or separators (SeparatorMenuElem). Stock menu items will use standard text, with translations in many languages, standard icons, and standard keyboard accelerators and shortcuts.

Menu reference

Menu_Helpers reference

Popup Menus

Menus are normally just added to a window, but they can also be displayed temporarily as the result of a mouse button click. For instance, a context menu might be diplayed when the user clicks their right mouse button. You can use Gtk::Menu's popup() method, but you need to provide a button identifier and the time of activation. This information is provided by the button_press_event signal, which you will need to handle anyway. For instance:

bool ExampleWindow::on_button_press_event(GdkEventButton* event)
{
  if( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) )
  {
    m_Menu_Popup.popup(event->button, event->time);
    return true; //It has been handled.
  }
  else
    return false;
}

Examples

Main Menu example

Figure 10.3. Main Menu

Source Code

File: examplewindow.h

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm/window.h>
#include <gtkmm/box.h>
#include <gtkmm/menubar.h>
#include <gtkmm/menu.h>

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

protected:
  //Signal handlers:
  virtual void on_menu_file_new_generic();
  virtual void on_menu_file_quit();
  virtual void on_menu_others();

  //Child widgets:
  Gtk::VBox m_Box;
  Gtk::MenuBar m_MenuBar;
  Gtk::Menu m_Menu_File, m_Menu_Edit;
  Gtk::Menu m_Menu_File_New; //submenu.
  Gtk::Menu m_Menu_Help;
};

#endif //GTKMM_EXAMPLEWINDOW_H

File: examplewindow.cc

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

ExampleWindow::ExampleWindow()
{
  set_title("main_menu example");
  set_default_size(200, 200);

  add(m_Box); //We can put a MenuBar at the top of the box and other stuff below it.

  //Fill menus:

  //File|New sub menu:
  {
  	Gtk::Menu::MenuList& menulist = m_Menu_File_New.items();

  	menulist.push_back( Gtk::Menu_Helpers::MenuElem("_New Foo",  Gtk::Menu::AccelKey("<control>n"),
      SigC::slot(*this, &ExampleWindow::on_menu_file_new_generic) ) );
  	menulist.push_back( Gtk::Menu_Helpers::MenuElem("New _Goo",
      SigC::slot(*this, &ExampleWindow::on_menu_file_new_generic) ) );
  }

  //File menu:
  {
  	Gtk::Menu::MenuList& menulist = m_Menu_File.items();

  	menulist.push_back( Gtk::Menu_Helpers::MenuElem("_New", m_Menu_File_New) ); //Add sub menu.
  	menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Quit",  Gtk::Menu::AccelKey("<control>q"),
      SigC::slot(*this, &ExampleWindow::on_menu_file_quit) ) );
  }

  //Edit menu:
  {
    Gtk::Menu::MenuList& menulist = m_Menu_Edit.items();

    menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Copy",
      SigC::slot(*this, &ExampleWindow::on_menu_others) ) );

    menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Paste",
      SigC::slot(*this, &ExampleWindow::on_menu_others) ) );

    menulist.push_back( Gtk::Menu_Helpers::CheckMenuElem("Something",
      SigC::slot(*this, &ExampleWindow::on_menu_others) ) );
  }
  
  //Help menu: (exercise stock items)
  {
    Gtk::Menu::MenuList& menulist = m_Menu_Help.items();
    
    menulist.push_back( Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::CDROM,
      SigC::slot(*this, &ExampleWindow::on_menu_others) ) );
  }

  //Add the menus to the MenuBar:
  m_MenuBar.items().push_back( Gtk::Menu_Helpers::MenuElem("_File", m_Menu_File) );
  m_MenuBar.items().push_back( Gtk::Menu_Helpers::MenuElem("_Edit", m_Menu_Edit) );
  m_MenuBar.items().push_back( Gtk::Menu_Helpers::StockMenuElem(Gtk::Stock::HELP, m_Menu_Help) );

  //Add the MenuBar to the window:
  m_Box.pack_start(m_MenuBar, Gtk::PACK_SHRINK);

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

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

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

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


File: main.cc

#include <gtkmm/main.h>
#include "examplewindow.h"

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

  ExampleWindow window;
  Gtk::Main::run(window); //Shows the window and returns when it is closed.

  return 0;
}

Popup Menu example

Figure 10.4. Popup Menu

Source Code

File: examplewindow.h

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>

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

protected:
  //Signal handlers:
  virtual bool on_button_press_event(GdkEventButton* event);
  virtual void on_menu_file_popup_generic();

  //Child widgets:
  Gtk::VBox m_Box;
  Gtk::EventBox m_EventBox;
  Gtk::Label m_Label;
  Gtk::Menu m_Menu_Popup;
  Gtk::Image m_Image;
};

#endif //GTKMM_EXAMPLEWINDOW_H

File: examplewindow.cc

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

ExampleWindow::ExampleWindow()
: m_Label("Right-click to see the popup menu."),
  m_Image(Gtk::Stock::DIALOG_QUESTION, Gtk::ICON_SIZE_MENU)
{
  set_title("popup example");
  set_default_size(200, 200);

  add(m_Box);

  //Add an event box that can catch button_press events:
  m_Box.pack_start(m_EventBox);
  m_EventBox.signal_button_press_event().connect( SigC::slot(*this, &ExampleWindow::on_button_press_event) );

  m_EventBox.add(m_Label);


  //Fill menu:
  {
  	Gtk::Menu::MenuList& menulist = m_Menu_Popup.items();

  	menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Edit",
      SigC::slot(*this, &ExampleWindow::on_menu_file_popup_generic) ) );
	menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Process", Gtk::Menu::AccelKey("<control>p"),
      SigC::slot(*this, &ExampleWindow::on_menu_file_popup_generic) ) );
  	menulist.push_back( Gtk::Menu_Helpers::MenuElem("_Remove",
      SigC::slot(*this, &ExampleWindow::on_menu_file_popup_generic) ) );

    //Add a ImageMenuElem:
    menulist.push_back( Gtk::Menu_Helpers::ImageMenuElem("_Something", m_Image,
      SigC::slot(*this, &ExampleWindow::on_menu_file_popup_generic) ) ) ;


  }
  m_Menu_Popup.accelerate(*this);

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

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

bool ExampleWindow::on_button_press_event(GdkEventButton* event)
{
  if( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) )
  {
    m_Menu_Popup.popup(event->button, event->time);
    return true; //It has been handled.
  }
  else
    return false;
}

File: main.cc

#include <gtkmm/main.h>
#include "examplewindow.h"

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

  ExampleWindow window;
  Gtk::Main::run(window); //Shows the window and returns when it is closed.

  return 0;
}