GTK+ 2.0 Tutorial
<<< Previous | Menu Widget | Next >>>

# Item Factory Example

Here is an example using the GTK item factory.

    /* example-start menu itemfactory.c */

    #include &lt;gtk/gtk.h&gt;
    #include &lt;strings.h&gt;

    /* Obligatory basic callback */
    static void print_hello( GtkWidget *w,
                             gpointer   data )
    {
      g_message ("Hello, World!\n");
    }

    /* For the check button */
    static void print_toggle(gpointer   callback_data,
                             guint      callback_action,
                             GtkWidget *menu_item)
    {
       g_message ("Check button state - %d\n",
                  GTK_CHECK_MENU_ITEM(menu_item)-&gt;active);
    }

    /* For the radio buttons */
    static void print_selected(gpointer   callback_data,
                               guint      callback_action,
                               GtkWidget *menu_item)
    {
       if(GTK_CHECK_MENU_ITEM(menu_item)-&gt;active)
         g_message("Radio button %d selected\n", callback_action);
    }

    /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
    static GtkItemFactoryEntry menu_items[] = {
      { "/_File",         NULL,         NULL,           0, "&lt;Branch&gt;" },
      { "/File/_New",     "&lt;control&gt;N", print_hello,    0, "<Item>" },
      { "/File/_Open",    "&lt;control&gt;O", print_hello,    0, "<Item>" },
      { "/File/_Save",    "&lt;control&gt;S", print_hello,    0, "<Item>" },
      { "/File/Save _As", NULL,         NULL,           0, "<Item>" },
      { "/File/sep1",     NULL,         NULL,           0, "&lt;Separator&gt;" },
      { "/File/Quit",     "&lt;control&gt;Q", gtk_main_quit,  0, "<Item>" },
      { "/_Options",      NULL,         NULL,           0, "&lt;Branch&gt;" },
      { "/Options/tear",  NULL,         NULL,           0, "&lt;Tearoff&gt;" },
      { "/Options/Check", NULL,         print_toggle,   1, "&lt;CheckItem&gt;" },
      { "/Options/sep",   NULL,         NULL,           0, "&lt;Separator&gt;" },
      { "/Options/Rad1",  NULL,         print_selected, 1, "&lt;RadioItem&gt;" },
      { "/Options/Rad2",  NULL,         print_selected, 2, "/Options/Rad1" },
      { "/Options/Rad3",  NULL,         print_selected, 3, "/Options/Rad1" },
      { "/_Help",         NULL,         NULL,           0, "&lt;LastBranch&gt;" },
      { "/_Help/About",   NULL,         NULL,           0, "<Item>" },
    };

    static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);

    /* Returns a menubar widget made from the above menu */
    GtkWidget *get_menubar_menu( GtkWidget  *window)
    {
      GtkItemFactory *item_factory;
      GtkAccelGroup *accel_group;

      /* Make an accelerator group (shortcut keys) */
      accel_group = gtk_accel_group_new ();

      /* Make an ItemFactory (that makes a menubar) */
      item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "&lt;main&gt;",
                                           accel_group);

      /* This function generates the menu items. Pass the item factory,
         the number of items in the array, the array itself, and any
         callback data for the the menu items. */
      gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);

      /* Attach the new accelerator group to the window. */
      gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);

      /* Finally, return the actual menu bar created by the item factory. */
      return gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
    }

    /* Popup the menu when the popup button is pressed */
    static gint popup_cb(GtkWidget *widget, GdkEvent *event, GtkWidget *menu)
    {
       GdkEventButton *bevent = (GdkEventButton *)event;

       /* Only take button presses */
       if(event-&gt;type != GDK_BUTTON_PRESS)
         return FALSE;

       /* Show the menu */
       gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
                      NULL, NULL, bevent-&gt;button, bevent-&gt;time);

       return TRUE;
    }

    /* Same as with get_menubar_menu() but just return a button with a signal to
       call a popup menu */
    GtkWidget *get_popup_menu(void)
    {
       GtkItemFactory *item_factory;
       GtkWidget *button, *menu;

       /* Same as before but don't bother with the accelerators */
       item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "&lt;main&gt;",
                                            NULL);
       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
       menu = gtk_item_factory_get_widget(item_factory, "&lt;main&gt;");

       /* Make a button to activate the popup menu */
       button = gtk_button_new_with_label("Popup");
       /* Make the menu popup when clicked */
       g_signal_connect(G_OBJECT(button),
                        "event",
                        G_CALLBACK(popup_cb),
                        (gpointer) menu);

       return button;
    }

    /* Same again but return an option menu */
    GtkWidget *get_option_menu(void)
    {
       GtkItemFactory *item_factory;
       GtkWidget *option_menu;

       /* Same again, not bothering with the accelerators */
       item_factory = gtk_item_factory_new (GTK_TYPE_OPTION_MENU, "&lt;main&gt;",
                                            NULL);
       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
       option_menu = gtk_item_factory_get_widget(item_factory, "&lt;main&gt;");

       return option_menu;
    }

    /* You have to start somewhere */
    int main( int argc,
              char *argv[] )
    {
      GtkWidget *window;
      GtkWidget *main_vbox;
      GtkWidget *menubar, *option_menu, *popup_button;

      /* Initialize GTK */
      gtk_init (&argc, &argv);

      /* Make a window */
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      g_signal_connect (G_OBJECT (window), "destroy",
                        G_CALLBACK (gtk_main_quit),
                        NULL);
      gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
      gtk_widget_set_size_request (GTK_WIDGET(window), 300, 200);

      /* Make a vbox to put the three menus in */
      main_vbox = gtk_vbox_new (FALSE, 1);
      gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
      gtk_container_add (GTK_CONTAINER (window), main_vbox);

      /* Get the three types of menu */
      /* Note: all three menus are separately created, so they are not the
         same menu */
      menubar = get_menubar_menu (window);
      popup_button = get_popup_menu();
      option_menu = get_option_menu();

      /* Pack it all together */
      gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
      gtk_box_pack_end (GTK_BOX (main_vbox), popup_button, FALSE, TRUE, 0);
      gtk_box_pack_end (GTK_BOX (main_vbox), option_menu, FALSE, TRUE, 0);

      /* Show the widgets */
      gtk_widget_show_all (window);

      /* Finished! */
      gtk_main ();

      return(0);
    }
    /* example-end */

<<< Previous | Home | Next >>>
Using ItemFactory | Up | Undocumented Widgets