File: examplewindow.h (For use with gtkmm 3, not gtkmm 2)
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
class ExampleWindow : public Gtk::ApplicationWindow
{
public:
ExampleWindow();
virtual ~ExampleWindow();
protected:
//Signal handlers:
void on_menu_file_new_generic();
void on_menu_file_quit();
void on_menu_others();
void on_menu_choices(const Glib::ustring& parameter);
void on_menu_choices_other(int parameter);
void on_menu_toggle();
//Child widgets:
Gtk::Box m_Box;
Glib::RefPtr<Gtk::Builder> m_refBuilder;
//Two sets of choices:
Glib::RefPtr<Gio::SimpleAction> m_refChoice, m_refChoiceOther;
Glib::RefPtr<Gio::SimpleAction> m_refToggle;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc (For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h"
#include <gtkmm/stock.h>
#include <iostream>
ExampleWindow::ExampleWindow()
: m_Box(Gtk::ORIENTATION_VERTICAL)
{
set_title("main menu example");
set_default_size(200, 200);
add(m_Box); // put a MenuBar at the top of the box and other stuff below it.
//Create actions for menus and toolbars:
Glib::RefPtr<Gio::SimpleActionGroup> refActionGroup =
Gio::SimpleActionGroup::create();
//File|New sub menu:
refActionGroup->add_action("newstandard",
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_new_generic));
refActionGroup->add_action("newfoo",
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_new_generic));
refActionGroup->add_action("newgoo",
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_new_generic));
//File menu:
refActionGroup->add_action("quit",
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_quit));
//Edit menu:
refActionGroup->add_action("copy",
sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
refActionGroup->add_action("paste",
sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
refActionGroup->add_action("something",
sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
//Choices menus, to demonstrate Radio items,
//using our convenience methods for string and int radio values:
m_refChoice = refActionGroup->add_action_radio_string("choice",
sigc::mem_fun(*this, &ExampleWindow::on_menu_choices),
"a");
m_refChoiceOther = refActionGroup->add_action_radio_integer("choiceother",
sigc::mem_fun(*this, &ExampleWindow::on_menu_choices_other),
1);
m_refToggle = refActionGroup->add_action_bool("sometoggle",
sigc::mem_fun(*this, &ExampleWindow::on_menu_toggle),
false);
//Help menu:
refActionGroup->add_action("about",
sigc::mem_fun(*this, &ExampleWindow::on_menu_others) );
insert_action_group("example", refActionGroup);
m_refBuilder = Gtk::Builder::create();
//TODO: add_accel_group(m_refBuilder->get_accel_group());
//Layout the actions in a menubar and toolbar:
Glib::ustring ui_info =
"<interface>"
" <menu id='menu-example'>"
" <submenu>"
" <attribute name='label' translatable='yes'>_File</attribute>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>New _Standard</attribute>"
" <attribute name='action'>example.newstandard</attribute>"
" <attribute name='accel'><Primary>n</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>New _Foo</attribute>"
" <attribute name='action'>example.newfoo</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>New _Goo</attribute>"
" <attribute name='action'>example.newgoo</attribute>"
" </item>"
" </section>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>_Quit</attribute>"
" <attribute name='action'>example.quit</attribute>"
" <attribute name='accel'><Primary>q</attribute>"
" </item>"
" </section>"
" </submenu>"
" <submenu>"
" <attribute name='label' translatable='yes'>_Edit</attribute>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>_Copy</attribute>"
" <attribute name='action'>example.copy</attribute>"
" <attribute name='accel'><Primary>c</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>_Paste</attribute>"
" <attribute name='action'>example.paste</attribute>"
" <attribute name='accel'><Primary>v</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>_Something</attribute>"
" <attribute name='action'>example.something</attribute>"
" </item>"
" </section>"
" </submenu>"
" <submenu>"
" <attribute name='label' translatable='yes'>_Choices</attribute>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>Choice _A</attribute>"
" <attribute name='action'>example.choice</attribute>"
" <attribute name='target'>a</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>Choice _B</attribute>"
" <attribute name='action'>example.choice</attribute>"
" <attribute name='target'>b</attribute>"
" </item>"
" </section>"
" </submenu>"
" <submenu>"
" <attribute name='label' translatable='yes'>_Other Choices</attribute>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>Choice 1</attribute>"
" <attribute name='action'>example.choiceother</attribute>"
" <attribute name='target' type='i'>1</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>Choice 2</attribute>"
" <attribute name='action'>example.choiceother</attribute>"
" <attribute name='target' type='i'>2</attribute>"
" </item>"
" </section>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>Some Toggle</attribute>"
" <attribute name='action'>example.sometoggle</attribute>"
" </item>"
" </section>"
" </submenu>"
" <submenu>"
" <attribute name='label' translatable='yes'>_Help</attribute>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>_About</attribute>"
" <attribute name='action'>example.about</attribute>"
" </item>"
" </section>"
" </submenu>"
" </menu>"
"</interface>";
try
{
m_refBuilder->add_from_string(ui_info);
}
catch(const Glib::Error& ex)
{
std::cerr << "building menus failed: " << ex.what();
}
//Get the menubar and add it to a container widget:
Glib::RefPtr<Glib::Object> object =
m_refBuilder->get_object("menu-example");
Glib::RefPtr<Gio::Menu> gmenu =
Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
if(!gmenu)
std::cerr << "GMenu not found." << std::endl;
//Menubar:
//If we just create a Gtk::MenuBar from Gio::Menu, and pack
//that into the window, for instance by packing
//it into a Gtk::Box, the accelerators will not work.
//This only seems to work if we use a Gtk::ApplicationWindow
//and Gtk::Application::set_menubar(). (or set_app_menu).
// Gtk::MenuBar* pMenubar = Gtk::manage(new Gtk::MenuBar(gmenu));
Glib::RefPtr<Gtk::Application> app = get_application();
if(!app)
std::cerr << "app not found." << std::endl;
else
app->set_menubar(gmenu);
//Create the toolbar and add it to a container widget:
Gtk::Toolbar* toolbar = Gtk::manage(new Gtk::Toolbar());
Gtk::ToolButton* button = Gtk::manage(new Gtk::ToolButton());
button->set_icon_name("document-new");
//We can't do this until we can break the ToolButton ABI: button->set_detailed_action_name("example.new");
gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button->gobj()), "example.newstandard");
toolbar->add(*button);
button = Gtk::manage(new Gtk::ToolButton());
button->set_icon_name("application-exit");
//We can't do this until we can break the ToolButton ABI: button->set_detailed_action_name("example.quit");
gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button->gobj()), "example.quit");
toolbar->add(*button);
m_Box.pack_start(*toolbar, Gtk::PACK_SHRINK);
show_all_children();
}
ExampleWindow::~ExampleWindow()
{
}
void ExampleWindow::on_menu_file_quit()
{
hide(); //Closes the main window to stop the app->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;
}
void ExampleWindow::on_menu_choices(const Glib::ustring& parameter)
{
//The radio action's state does not change automatically:
m_refChoice->change_state(parameter);
Glib::ustring message;
if(parameter == "a")
message = "Choice a was selected.";
else
message = "Choice b was selected";
std::cout << message << std::endl;
}
void ExampleWindow::on_menu_choices_other(int parameter)
{
//The radio action's state does not change automatically:
m_refChoice->change_state(parameter);
Glib::ustring message;
if(parameter == 1)
message = "Choice 1 was selected.";
else
message = "Choice 2 was selected";
std::cout << message << std::endl;
}
void ExampleWindow::on_menu_toggle()
{
bool active = false;
m_refToggle->get_state(active);
//The toggle action's state does not change automatically:
m_refToggle->change_state(!active);
active = !active;
Glib::ustring message;
if(active)
message = "Toggle is active.";
else
message = "Toggle is not active";
std::cout << message << std::endl;
}
File: main.cc (For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
ExampleWindow window;
//Shows the window and returns when it is closed.
return app->run(window);
}
File: examplewindow.h (For use with gtkmm 3, not gtkmm 2)
#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);
void on_menu_file_popup_generic();
//Child widgets:
Gtk::Box m_Box;
Gtk::EventBox m_EventBox;
Gtk::Label m_Label;
Glib::RefPtr<Gtk::Builder> m_refBuilder;
Gtk::Menu* m_pMenuPopup;
};
#endif //GTKMM_EXAMPLEWINDOW_H
File: examplewindow.cc (For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h"
#include <gtkmm/stock.h>
#include <iostream>
ExampleWindow::ExampleWindow()
: m_Box(Gtk::ORIENTATION_VERTICAL),
m_Label("Right-click to see the popup menu."),
m_pMenuPopup(0)
/* 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::mem_fun(*this,
&ExampleWindow::on_button_press_event) );
m_EventBox.add(m_Label);
//Create actions:
//Fill menu:
Glib::RefPtr<Gio::SimpleActionGroup> refActionGroup =
Gio::SimpleActionGroup::create();
//File|New sub menu:
//These menu actions would normally already exist for a main menu, because a
//context menu should not normally contain menu items that are only available
//via a context menu.
refActionGroup->add_action("edit",
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic));
refActionGroup->add_action("process", //TODO: How to specify "<control>P" as an accelerator.
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic));
refActionGroup->add_action("remove",
sigc::mem_fun(*this, &ExampleWindow::on_menu_file_popup_generic));
insert_action_group("examplepopup", refActionGroup);
m_refBuilder = Gtk::Builder::create();
//Layout the actions in a menubar and toolbar:
Glib::ustring ui_info =
"<interface>"
" <menu id='menu-examplepopup'>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>Edit</attribute>"
" <attribute name='action'>examplepopup.edit</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>Process</attribute>"
" <attribute name='action'>examplepopup.process</attribute>"
" </item>"
" <item>"
" <attribute name='label' translatable='yes'>Remove</attribute>"
" <attribute name='action'>examplepopup.remove</attribute>"
" </item>"
" </section>"
" </menu>"
"</interface>";
try
{
m_refBuilder->add_from_string(ui_info);
}
catch(const Glib::Error& ex)
{
std::cerr << "building menus failed: " << ex.what();
}
//Get the menu:
Glib::RefPtr<Glib::Object> object =
m_refBuilder->get_object("menu-examplepopup");
Glib::RefPtr<Gio::Menu> gmenu =
Glib::RefPtr<Gio::Menu>::cast_dynamic(object);
if(!gmenu)
g_warning("GMenu not found");
m_pMenuPopup = new Gtk::Menu(gmenu);
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) )
{
if(!m_pMenuPopup->get_attach_widget())
{
m_pMenuPopup->attach_to_widget(*this);
}
if(m_pMenuPopup)
m_pMenuPopup->popup(event->button, event->time);
return true; //It has been handled.
}
else
return false;
}
File: main.cc (For use with gtkmm 3, not gtkmm 2)
#include "examplewindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
ExampleWindow window;
//Shows the window and returns when it is closed.
return app->run(window);
}