Chapter 10. Menus and Toolbars
Prev |  | Next

## Chapter 10. Menus and Toolbars

## Menus

### The MenuBar

`Gtk::MenuBar` is a container that holds child `Gtk::Menu`s.

Actually, it contains child `Gtk::MenuItem`, which contain `Gtk::Menu`s 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 `MenuBar`s and `Menu`s 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::MenuItem`s. 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;
    }

Prev | Up | Next
Examples | Home | Toolbars