diff options
Diffstat (limited to 'examples/menu')
-rw-r--r-- | examples/menu/Makefile | 19 | ||||
-rw-r--r-- | examples/menu/menu.c | 134 | ||||
-rw-r--r-- | examples/menu/menufactory.c | 151 | ||||
-rw-r--r-- | examples/menu/menufactory.h | 19 | ||||
-rw-r--r-- | examples/menu/mfmain.c | 52 | ||||
-rw-r--r-- | examples/menu/mfmain.h | 19 |
6 files changed, 394 insertions, 0 deletions
diff --git a/examples/menu/Makefile b/examples/menu/Makefile new file mode 100644 index 0000000000..630d3f297e --- /dev/null +++ b/examples/menu/Makefile @@ -0,0 +1,19 @@ + +CC = gcc + +all: menu menufactory + +menu: menu.c + $(CC) `gtk-config --cflags` `gtk-config --libs` menu.c -o menu + +menufactory: menufactory.o mfmain.o + $(CC) `gtk-config --libs` menufactory.o mfmain.o -o menufactory + +menufactory.o: + $(CC) `gtk-config --cflags` -c menufactory.c -o menufactory.o + +mfmain.o: + $(CC) `gtk-config --cflags` -c mfmain.c -o mfmain.o + +clean: + rm -f *.o menu menufactory diff --git a/examples/menu/menu.c b/examples/menu/menu.c new file mode 100644 index 0000000000..4053fab7b6 --- /dev/null +++ b/examples/menu/menu.c @@ -0,0 +1,134 @@ +/* This file extracted from the GTK tutorial. */ + +/* menu.c */ + +#include <gtk/gtk.h> + +static gint button_press (GtkWidget *, GdkEvent *); +static void menuitem_response (gchar *); + +int main (int argc, char *argv[]) +{ + + GtkWidget *window; + GtkWidget *menu; + GtkWidget *menu_bar; + GtkWidget *root_menu; + GtkWidget *menu_items; + GtkWidget *vbox; + GtkWidget *button; + char buf[128]; + int i; + + gtk_init (&argc, &argv); + + /* create a new window */ + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_usize( GTK_WIDGET (window), 200, 100); + gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test"); + gtk_signal_connect(GTK_OBJECT (window), "delete_event", + (GtkSignalFunc) gtk_exit, NULL); + + /* Init the menu-widget, and remember -- never + * gtk_show_widget() the menu widget!! + * This is the menu that holds the menu items, the one that + * will pop up when you click on the "Root Menu" in the app */ + menu = gtk_menu_new(); + + /* Next we make a little loop that makes three menu-entries for "test-menu". + * Notice the call to gtk_menu_append. Here we are adding a list of + * menu items to our menu. Normally, we'd also catch the "clicked" + * signal on each of the menu items and setup a callback for it, + * but it's omitted here to save space. */ + + for(i = 0; i < 3; i++) + { + /* Copy the names to the buf. */ + sprintf(buf, "Test-undermenu - %d", i); + + /* Create a new menu-item with a name... */ + menu_items = gtk_menu_item_new_with_label(buf); + + /* ...and add it to the menu. */ + gtk_menu_append(GTK_MENU (menu), menu_items); + + /* Do something interesting when the menuitem is selected */ + gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate", + GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf)); + + /* Show the widget */ + gtk_widget_show(menu_items); + } + + /* This is the root menu, and will be the label + * displayed on the menu bar. There won't be a signal handler attached, + * as it only pops up the rest of the menu when pressed. */ + root_menu = gtk_menu_item_new_with_label("Root Menu"); + + gtk_widget_show(root_menu); + + /* Now we specify that we want our newly created "menu" to be the menu + * for the "root menu" */ + gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu); + + /* A vbox to put a menu and a button in: */ + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(window), vbox); + gtk_widget_show(vbox); + + /* Create a menu-bar to hold the menus and add it to our main window */ + menu_bar = gtk_menu_bar_new(); + gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2); + gtk_widget_show(menu_bar); + + /* Create a button to which to attach menu as a popup */ + button = gtk_button_new_with_label("press me"); + gtk_signal_connect_object(GTK_OBJECT(button), "event", + GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu)); + gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2); + gtk_widget_show(button); + + /* And finally we append the menu-item to the menu-bar -- this is the + * "root" menu-item I have been raving about =) */ + gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu); + + /* always display the window as the last step so it all splashes on + * the screen at once. */ + gtk_widget_show(window); + + gtk_main (); + + return 0; +} + + + +/* Respond to a button-press by posting a menu passed in as widget. + * + * Note that the "widget" argument is the menu being posted, NOT + * the button that was pressed. + */ + +static gint button_press (GtkWidget *widget, GdkEvent *event) +{ + + if (event->type == GDK_BUTTON_PRESS) { + GdkEventButton *bevent = (GdkEventButton *) event; + gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL, + bevent->button, bevent->time); + /* Tell calling code that we have handled this event; the buck + * stops here. */ + return TRUE; + } + + /* Tell calling code that we have not handled this event; pass it on. */ + return FALSE; +} + + +/* Print a string when a menu item is selected */ + +static void menuitem_response (gchar *string) +{ + printf("%s\n", string); +} diff --git a/examples/menu/menufactory.c b/examples/menu/menufactory.c new file mode 100644 index 0000000000..9f72e1e925 --- /dev/null +++ b/examples/menu/menufactory.c @@ -0,0 +1,151 @@ +/* This file extracted from the GTK tutorial. */ + +/* menufactory.c */ + +#include <gtk/gtk.h> +#include <strings.h> + +#include "mfmain.h" + + +static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path); +static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path); +void menus_init(void); +void menus_create(GtkMenuEntry * entries, int nmenu_entries); + + +/* this is the GtkMenuEntry structure used to create new menus. The + * first member is the menu definition string. The second, the + * default accelerator key used to access this menu function with + * the keyboard. The third is the callback function to call when + * this menu item is selected (by the accelerator key, or with the + * mouse.) The last member is the data to pass to your callback function. + */ + +static GtkMenuEntry menu_items[] = +{ + {"<Main>/File/New", "<control>N", NULL, NULL}, + {"<Main>/File/Open", "<control>O", NULL, NULL}, + {"<Main>/File/Save", "<control>S", NULL, NULL}, + {"<Main>/File/Save as", NULL, NULL, NULL}, + {"<Main>/File/<separator>", NULL, NULL, NULL}, + {"<Main>/File/Quit", "<control>Q", file_quit_cmd_callback, "OK, I'll quit"}, + {"<Main>/Options/Test", NULL, NULL, NULL} +}; + +/* calculate the number of menu_item's */ +static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); + +static int initialize = TRUE; +static GtkMenuFactory *factory = NULL; +static GtkMenuFactory *subfactory[1]; +static GHashTable *entry_ht = NULL; + +void get_main_menu(GtkWidget ** menubar, GtkAcceleratorTable ** table) +{ + if (initialize) + menus_init(); + + if (menubar) + *menubar = subfactory[0]->widget; + if (table) + *table = subfactory[0]->table; +} + +void menus_init(void) +{ + if (initialize) { + initialize = FALSE; + + factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR); + subfactory[0] = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR); + + gtk_menu_factory_add_subfactory(factory, subfactory[0], "<Main>"); + menus_create(menu_items, nmenu_items); + } +} + +void menus_create(GtkMenuEntry * entries, int nmenu_entries) +{ + char *accelerator; + int i; + + if (initialize) + menus_init(); + + if (entry_ht) + for (i = 0; i < nmenu_entries; i++) { + accelerator = g_hash_table_lookup(entry_ht, entries[i].path); + if (accelerator) { + if (accelerator[0] == '\0') + entries[i].accelerator = NULL; + else + entries[i].accelerator = accelerator; + } + } + gtk_menu_factory_add_entries(factory, entries, nmenu_entries); + + for (i = 0; i < nmenu_entries; i++) + if (entries[i].widget) { + gtk_signal_connect(GTK_OBJECT(entries[i].widget), "install_accelerator", + (GtkSignalFunc) menus_install_accel, + entries[i].path); + gtk_signal_connect(GTK_OBJECT(entries[i].widget), "remove_accelerator", + (GtkSignalFunc) menus_remove_accel, + entries[i].path); + } +} + +static gint menus_install_accel(GtkWidget * widget, gchar * signal_name, gchar key, gchar modifiers, gchar * path) +{ + char accel[64]; + char *t1, t2[2]; + + accel[0] = '\0'; + if (modifiers & GDK_CONTROL_MASK) + strcat(accel, "<control>"); + if (modifiers & GDK_SHIFT_MASK) + strcat(accel, "<shift>"); + if (modifiers & GDK_MOD1_MASK) + strcat(accel, "<alt>"); + + t2[0] = key; + t2[1] = '\0'; + strcat(accel, t2); + + if (entry_ht) { + t1 = g_hash_table_lookup(entry_ht, path); + g_free(t1); + } else + entry_ht = g_hash_table_new(g_str_hash, g_str_equal); + + g_hash_table_insert(entry_ht, path, g_strdup(accel)); + + return TRUE; +} + +static void menus_remove_accel(GtkWidget * widget, gchar * signal_name, gchar * path) +{ + char *t; + + if (entry_ht) { + t = g_hash_table_lookup(entry_ht, path); + g_free(t); + + g_hash_table_insert(entry_ht, path, g_strdup("")); + } +} + +void menus_set_sensitive(char *path, int sensitive) +{ + GtkMenuPath *menu_path; + + if (initialize) + menus_init(); + + menu_path = gtk_menu_factory_find(factory, path); + if (menu_path) + gtk_widget_set_sensitive(menu_path->widget, sensitive); + else + g_warning("Unable to set sensitivity for menu which doesn't exist: %s", path); +} diff --git a/examples/menu/menufactory.h b/examples/menu/menufactory.h new file mode 100644 index 0000000000..e1569dae4c --- /dev/null +++ b/examples/menu/menufactory.h @@ -0,0 +1,19 @@ +/* This file extracted from the GTK tutorial. */ + +/* menufactory.h */ + +#ifndef __MENUFACTORY_H__ +#define __MENUFACTORY_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void get_main_menu (GtkWidget **menubar, GtkAcceleratorTable **table); +void menus_create(GtkMenuEntry *entries, int nmenu_entries); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MENUFACTORY_H__ */ diff --git a/examples/menu/mfmain.c b/examples/menu/mfmain.c new file mode 100644 index 0000000000..cbe0c58408 --- /dev/null +++ b/examples/menu/mfmain.c @@ -0,0 +1,52 @@ +/* This file extracted from the GTK tutorial. */ + +/* mfmain.c */ + +#include <gtk/gtk.h> + +#include "mfmain.h" +#include "menufactory.h" + + +int main(int argc, char *argv[]) +{ + GtkWidget *window; + GtkWidget *main_vbox; + GtkWidget *menubar; + + GtkAcceleratorTable *accel; + + gtk_init(&argc, &argv); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(window), "destroy", + GTK_SIGNAL_FUNC(file_quit_cmd_callback), + "WM destroy"); + gtk_window_set_title(GTK_WINDOW(window), "Menu Factory"); + gtk_widget_set_usize(GTK_WIDGET(window), 300, 200); + + main_vbox = gtk_vbox_new(FALSE, 1); + gtk_container_border_width(GTK_CONTAINER(main_vbox), 1); + gtk_container_add(GTK_CONTAINER(window), main_vbox); + gtk_widget_show(main_vbox); + + get_main_menu(&menubar, &accel); + gtk_window_add_accelerator_table(GTK_WINDOW(window), accel); + gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0); + gtk_widget_show(menubar); + + gtk_widget_show(window); + gtk_main(); + + return(0); +} + +/* This is just to demonstrate how callbacks work when using the + * menufactory. Often, people put all the callbacks from the menus + * in a separate file, and then have them call the appropriate functions + * from there. Keeps it more organized. */ +void file_quit_cmd_callback (GtkWidget *widget, gpointer data) +{ + g_print ("%s\n", (char *) data); + gtk_exit(0); +} diff --git a/examples/menu/mfmain.h b/examples/menu/mfmain.h new file mode 100644 index 0000000000..fe481b0c1f --- /dev/null +++ b/examples/menu/mfmain.h @@ -0,0 +1,19 @@ +/* This file extracted from the GTK tutorial. */ + +/* mfmain.h */ + +#ifndef __MFMAIN_H__ +#define __MFMAIN_H__ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void file_quit_cmd_callback(GtkWidget *widget, gpointer data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MFMAIN_H__ */ |