]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/menus.c
Don't use GTK_WIDGET_*SET_FLAGS (wid, GTK_CAN_DEFAULT)
[~andy/gtk] / demos / gtk-demo / menus.c
1 /* Menus
2  *
3  * There are several widgets involved in displaying menus. The
4  * GtkMenuBar widget is a menu bar, which normally appears horizontally
5  * at the top of an application, but can also be layed out vertically.
6  * The GtkMenu widget is the actual menu that pops up. Both GtkMenuBar
7  * and GtkMenu are subclasses of GtkMenuShell; a GtkMenuShell contains
8  * menu items (GtkMenuItem). Each menu item contains text and/or images
9  * and can 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 #include <gtk/gtk.h>
28 #include <gdk/gdkkeysyms.h>
29
30 #include <stdio.h>
31
32 static GtkWidget *
33 create_menu (gint     depth,
34              gboolean tearoff)
35 {
36   GtkWidget *menu;
37   GtkWidget *menuitem;
38   GSList *group;
39   char buf[32];
40   int i, j;
41
42   if (depth < 1)
43     return NULL;
44
45   menu = gtk_menu_new ();
46   group = NULL;
47
48   if (tearoff)
49     {
50       menuitem = gtk_tearoff_menu_item_new ();
51       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
52       gtk_widget_show (menuitem);
53     }
54
55   for (i = 0, j = 1; i < 5; i++, j++)
56     {
57       sprintf (buf, "item %2d - %d", depth, j);
58       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
59       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
60
61       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
62       gtk_widget_show (menuitem);
63       if (i == 3)
64         gtk_widget_set_sensitive (menuitem, FALSE);
65
66       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (depth - 1, TRUE));
67     }
68
69   return menu;
70 }
71
72 static void
73 change_orientation (GtkWidget *button,
74                     GtkWidget *menubar)
75 {
76   GtkWidget *parent;
77   GtkWidget *box = NULL;
78
79   parent = gtk_widget_get_parent (menubar);
80
81   if (GTK_IS_VBOX (parent))
82     {
83       box = gtk_widget_get_parent (parent);
84
85       g_object_ref (menubar);
86       gtk_container_remove (GTK_CONTAINER (parent), menubar);
87       gtk_container_add (GTK_CONTAINER (box), menubar);
88       gtk_box_reorder_child (GTK_BOX (box), menubar, 0);
89       g_object_unref (menubar);
90       g_object_set (menubar, 
91                     "pack-direction", GTK_PACK_DIRECTION_TTB,
92                     NULL);
93     }
94   else
95     {
96       GList *children, *l;
97
98       children = gtk_container_get_children (GTK_CONTAINER (parent));
99       for (l = children; l; l = l->next)
100         {
101           if (GTK_IS_VBOX (l->data))
102             {
103               box = l->data;
104               break;
105             }
106         }
107       g_list_free (children);
108
109       g_object_ref (menubar);
110       gtk_container_remove (GTK_CONTAINER (parent), menubar);
111       gtk_container_add (GTK_CONTAINER (box), menubar);
112       gtk_box_reorder_child (GTK_BOX (box), menubar, 0);
113       g_object_unref (menubar);
114       g_object_set (menubar, 
115                     "pack-direction", GTK_PACK_DIRECTION_LTR,
116                     NULL);
117     }
118 }
119
120 static GtkWidget *window = NULL;
121
122 GtkWidget *
123 do_menus (GtkWidget *do_widget)
124 {
125   GtkWidget *box;
126   GtkWidget *box1;
127   GtkWidget *box2;
128   GtkWidget *button;
129
130   if (!window)
131     {
132       GtkWidget *menubar;
133       GtkWidget *menu;
134       GtkWidget *menuitem;
135       GtkAccelGroup *accel_group;
136
137       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
138       gtk_window_set_screen (GTK_WINDOW (window),
139                              gtk_widget_get_screen (do_widget));
140       gtk_window_set_title (GTK_WINDOW (window), "Menus");
141       g_signal_connect (window, "destroy",
142                         G_CALLBACK(gtk_widget_destroyed), &window);
143
144       accel_group = gtk_accel_group_new ();
145       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
146
147       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
148
149       box = gtk_hbox_new (FALSE, 0);
150       gtk_container_add (GTK_CONTAINER (window), box);
151       gtk_widget_show (box);
152
153       box1 = gtk_vbox_new (FALSE, 0);
154       gtk_container_add (GTK_CONTAINER (box), box1);
155       gtk_widget_show (box1);
156
157       menubar = gtk_menu_bar_new ();
158       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
159       gtk_widget_show (menubar);
160
161       menu = create_menu (2, TRUE);
162
163       menuitem = gtk_menu_item_new_with_label ("test\nline2");
164       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
165       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
166       gtk_widget_show (menuitem);
167
168       menuitem = gtk_menu_item_new_with_label ("foo");
169       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (3, TRUE));
170       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
171       gtk_widget_show (menuitem);
172
173       menuitem = gtk_menu_item_new_with_label ("bar");
174       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (4, TRUE));
175       gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
176       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
177       gtk_widget_show (menuitem);
178
179       box2 = gtk_vbox_new (FALSE, 10);
180       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
181       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
182       gtk_widget_show (box2);
183
184       button = gtk_button_new_with_label ("Flip");
185       g_signal_connect (button, "clicked",
186                         G_CALLBACK (change_orientation), menubar);
187       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
188       gtk_widget_show (button);
189
190       button = gtk_button_new_with_label ("Close");
191       g_signal_connect_swapped (button, "clicked",
192                                 G_CALLBACK(gtk_widget_destroy), window);
193       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
194       gtk_widget_set_can_default (button, TRUE);
195       gtk_widget_grab_default (button);
196       gtk_widget_show (button);
197     }
198
199   if (!gtk_widget_get_visible (window))
200     {
201       gtk_widget_show (window);
202     }
203   else
204     {
205       gtk_widget_destroy (window);
206       window = NULL;
207     }
208
209   return window;
210 }