Setting Up the Menu: Panel Applet Reference Manual

## Setting Up the Menu

The only part of dealing with a context menu that is specific to applets is how to setup the context menu. Once it is setup, this is really just a matter of using GtkAction.

To setup the context menu of the applet, the `panel_applet_setup_menu_from_file()` function should be used, with a path to a menu XML file and a GtkActionGroup object containing all actions that are used in the menu XML file. The example below shows how to achieve this:

Example 3. Hello World applet, with a context menu

    #include <glib/gi18n.h>
    #include <gtk/gtk.h>
    #include <panel-applet.h>

    /* This would usually be defined in config.h */
    #define GETTEXT_PACKAGE "hello-world"
    /* This would usually be defined in Makefile.am */
    #define HELLO_WORLD_UI_DIR "/usr/share/hello-world"

    static void hello_world_applet_prefs (GtkAction   *action,
                                          PanelApplet *applet);
    static void hello_world_applet_say   (GtkAction   *action,
                                          PanelApplet *applet);

    static const GtkActionEntry hello_world_menu_actions [] = {
            { "HelloWorldPrefs", GTK_STOCK_HELP, N_("_Preferences"),
              NULL, NULL,
              G_CALLBACK (hello_world_applet_prefs) },
            { "HelloWorldSay", GTK_STOCK_ABOUT, N_("_Say Hello"),
              NULL, NULL,
              G_CALLBACK (hello_world_applet_say) }
    };

    static void
    hello_world_applet_prefs (GtkAction   *action,
                              PanelApplet *applet)
    {
        GtkWidget *dialog;
        dialog = gtk_message_dialog_new (NULL, 0,
                                        GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
                                        "Preferences");
        g_signal_connect (dialog, "response",
                          G_CALLBACK (gtk_widget_destroy), NULL);
        gtk_widget_show (dialog);
    }

    static void
    hello_world_applet_say (GtkAction   *action,
                            PanelApplet *applet)
    {
        GtkWidget *dialog;
        dialog = gtk_message_dialog_new (NULL, 0,
                                        GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
                                        "Hello World!");
        g_signal_connect (dialog, "response",
                          G_CALLBACK (gtk_widget_destroy), NULL);
        gtk_widget_show (dialog);
    }

    static gboolean
    hello_world_applet_start (PanelApplet *applet)
    {
        GtkWidget *label;
        GtkActionGroup *action_group;
        gchar *ui_path;

        label = gtk_label_new ("Hello World");
        gtk_container_add (GTK_CONTAINER (applet), label);

        action_group = gtk_action_group_new ("Hello World Applet Actions");
        gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
        gtk_action_group_add_actions (action_group,
                                      hello_world_menu_actions,
                                      G_N_ELEMENTS (hello_world_menu_actions),
                                      applet);

        ui_path = g_build_filename (HELLO_WORLD_UI_DIR, "hello-world-menu.xml", NULL);
        panel_applet_setup_menu_from_file (applet, ui_path, action_group);

        g_free (ui_path);
        g_object_unref (action_group);

        gtk_widget_show_all (GTK_WIDGET (applet));

        return TRUE;
    }

    static gboolean
    hello_world_factory_callback (PanelApplet  *applet,
                                  const gchar  *iid,
                                  gpointer      data)
    {
        gboolean retval = FALSE;

        if (g_strcmp0 (iid, "HelloWorldApplet") == 0)
            retval = hello_world_applet_start (applet);

        return retval;
    }

    PANEL_APPLET_OUT_PROCESS_FACTORY ("HelloWorldFactory",
                                      PANEL_TYPE_APPLET,
                                      hello_world_factory_callback,
                                      NULL)

Here are the changes compared to the simple example with no context menu:

- We define a list of GtkActionEntry entries: `hello_world_menu_actions`. This will be used later on to build GtkAction objects, with their label and callback. We obviously implement the callbacks.

- We change `hello_world_applet_start()` to define a GtkActionGroup object, to which we add, with `gtk_action_group_add_actions()`, GtkAction objects based on the GtkActionEntry entries. Note that the the last argument to `gtk_action_group_add_actions()` will be passed as user data to the callbacks.

- We also change `hello_world_applet_start()` to add this GtkActionGroup object to the context menu of the applet, by calling `panel_applet_setup_menu_from_file()`. This function takes as argument a path to the menu XML file that will define how to display the GtkAction objects in the context menu.