1 /* Menus
2  *
3  * There are several widgets involved in displaying menus. The
4  * GtkMenuBar widget is a horizontal menu bar, which normally appears
5  * at the top of an application. The GtkMenu widget is the actual menu
6  * that pops up. Both GtkMenuBar and GtkMenu are subclasses of
7  * GtkMenuShell; a GtkMenuShell contains menu items
8  * (GtkMenuItem). Each menu item contains text and/or images and can
9  * be selected by the user.
10  *
11  * There are several kinds of menu item, including plain GtkMenuItem,
12  * GtkCheckMenuItem which can be checked/unchecked, GtkRadioMenuItem
13  * which is a check menu item that's in a mutually exclusive group,
14  * GtkSeparatorMenuItem which is a separator bar, GtkTearoffMenuItem
15  * which allows a GtkMenu to be torn off, and GtkImageMenuItem which
16  * can place a GtkImage or other widget next to the menu text.
17  *
18  * A GtkMenuItem can have a submenu, which is simply a GtkMenu to pop
19  * up when the menu item is selected. Typically, all menu items in a menu bar
20  * have submenus.
21  *
22  * GtkUIManager provides a higher-level interface for creating menu bars
23  * and menus; while you can construct menus manually, most people don't
24  * do that. There's a separate demo for GtkUIManager.
25  *
26  */
27 
28 #include "gtkmm.h"
29 #include <stdio.h>
30 
31 class Example_Menus : public Gtk::Window
32 {
33 public:
34   Example_Menus();
35   virtual ~Example_Menus();
36 
37 protected:
38   //signal handlers:
39   virtual void on_button_clicked();
40 
41   virtual Gtk::Menu* create_menu(gint depth, bool tearoff);
42 
43   //Member widgets:
44   Gtk::Frame m_Frame_Horizontal, m_Frame_Vertical;
45   Gtk::VBox m_VBox1, m_VBox_Sub1, m_VBox_Sub2;
46   Gtk::MenuBar m_MenuBar;
47   Gtk::HSeparator m_Separator;
48   Gtk::Button m_Button;
49 };
50 
51 //Called by DemoWindow;
do_menus()52 Gtk::Window* do_menus()
53 {
54   return new Example_Menus();
55 }
56 
Example_Menus()57 Example_Menus::Example_Menus()
58 : m_VBox_Sub1(false, 10),
59   m_VBox_Sub2(false, 10),
60   m_Button("close")
61 {
62   set_title("menus");
63   set_border_width(0);
64 
65   add(m_VBox1);
66 
67   m_VBox1.pack_start(m_MenuBar, Gtk::PACK_SHRINK);
68 
69   {
70     //Note:: It's generally easier to use the Gtk::UIManager API.
71     Gtk::MenuItem* pMenuItem = Gtk::manage(new Gtk::MenuItem("test\nline2"));
72     pMenuItem->set_submenu( *(create_menu(2, true)) );
73     m_MenuBar.append(*pMenuItem);
74     pMenuItem->show();
75 
76     pMenuItem = Gtk::manage(new Gtk::MenuItem("foo"));
77     pMenuItem->set_submenu( *(create_menu(3, true)) );
78     m_MenuBar.append(*pMenuItem);
79     pMenuItem->show();
80 
81     pMenuItem = Gtk::manage(new Gtk::MenuItem("bar"));
82     pMenuItem->set_submenu( *(create_menu(4, true)) );
83     pMenuItem->set_right_justified();
84     m_MenuBar.append(*pMenuItem);
85     pMenuItem->show();
86   }
87 
88 
89   m_VBox_Sub1.set_border_width(10);
90   m_VBox1.pack_start(m_VBox_Sub1);
91 
92   {
93     Gtk::Menu* pMenu = create_menu(1, false);
94     pMenu->set_accel_group(get_accel_group());
95 
96     Gtk::MenuItem* pMenuItem = Gtk::manage(new Gtk::SeparatorMenuItem());
97     pMenu->append(*pMenuItem);
98     pMenuItem->show();
99 
100     pMenuItem = Gtk::manage(new Gtk::CheckMenuItem("Accelerate Me"));
101     pMenuItem->add_accelerator("activate", get_accel_group(), GDK_KEY_F1, Gdk::ModifierType(0), Gtk::ACCEL_VISIBLE );
102     pMenu->append(*pMenuItem);
103     pMenuItem->show();
104 
105     pMenuItem = Gtk::manage(new Gtk::CheckMenuItem("Accelerator Locked"));
106     pMenu->append(*pMenuItem);
107     pMenuItem->add_accelerator("activate", get_accel_group(), GDK_KEY_F2, Gdk::ModifierType(0), Gtk::ACCEL_VISIBLE | Gtk::ACCEL_LOCKED);
108     pMenuItem->show();
109 
110     pMenuItem = Gtk::manage(new Gtk::CheckMenuItem("Accelerator Frozen"));
111     pMenu->append(*pMenuItem);
112     pMenuItem->add_accelerator("activate", get_accel_group(), GDK_KEY_F2, Gdk::ModifierType(0), Gtk::ACCEL_VISIBLE);
113     pMenuItem->show();
114   }
115 
116   m_VBox1.pack_start(m_Separator, Gtk::PACK_SHRINK);
117 
118 
119   m_VBox_Sub2.set_border_width(10);
120   m_VBox1.pack_start(m_VBox_Sub2, Gtk::PACK_SHRINK);
121 
122   m_Button.signal_clicked().connect(sigc::mem_fun(*this, &Example_Menus::on_button_clicked));
123 
124   m_VBox_Sub2.pack_start(m_Button);
125   m_Button.property_can_default() = true;
126   m_Button.grab_default();
127 
128   show_all();
129 }
130 
~Example_Menus()131 Example_Menus::~Example_Menus()
132 {
133 }
134 
create_menu(gint depth,bool tearoff)135 Gtk::Menu* Example_Menus::create_menu(gint depth, bool tearoff)
136 {
137   if (depth < 1)
138     return 0;
139 
140   Gtk::Menu* pMenu = Gtk::manage(new Gtk::Menu());
141 
142   {
143     if(tearoff)
144     {
145       Gtk::MenuItem* menu_item = Gtk::manage(new Gtk::TearoffMenuItem());
146       pMenu->append(*menu_item);
147       menu_item->show();
148     }
149 
150     Gtk::RadioMenuItem::Group radiogroup;
151 
152     for(int i = 0, j = 1; i < 5; i++, j++)
153     {
154       char buf[32];
155       sprintf(buf, "item %2d - %d", depth, j);
156 
157       Gtk::MenuItem* pMenuItem = Gtk::manage(new Gtk::RadioMenuItem(radiogroup, buf));
158       pMenu->append(*pMenuItem);
159       pMenuItem->show();
160 
161       if(i == 3)
162         pMenuItem->set_sensitive(false);
163 
164       Gtk::Menu* pSubMenu = create_menu(depth - 1, true);
165       if(pSubMenu)
166         pMenuItem->set_submenu(*pSubMenu);
167     }
168   }
169 
170   return pMenu;
171 }
172 
on_button_clicked()173 void Example_Menus::on_button_clicked()
174 {
175   hide();
176 }
177