Logo Search packages:      
Sourcecode: scigraphica version File versions  Download package

sg_menu.c

/*  SciGraphica - Scientific graphics and data manipulation
 *  Copyright (C) 2001 Adrian E. Feiguin <feiguin@ifir.edu.ar>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include "gtkpixmapmenuitem.h"
#include "sg_menu.h"



static void create_menu_item        (GtkMenuShell       *menu_shell,
                                     GnomeUIInfo        *uiinfo,
                                     GnomeUIBuilderData *uibdata,
                                     GtkAccelGroup      *accel_group,
                                     gboolean            uline_accels,
                                     gint                pos);

static void create_toolbar_item     (GtkToolbar *toolbar, 
                                     GnomeUIInfo *uiinfo, 
                                     GnomeUIBuilderData *uibdata,
                                     GtkAccelGroup *accel_group);

static void setup_uline_accel             (GtkMenuShell  *menu_shell,
                                     GtkAccelGroup *accel_group,
                                     GtkWidget     *menu_item,
                                     guint          keyval);

static void do_ui_signal_connect    (GnomeUIInfo *uiinfo, 
                               gchar *signal_name,
                                     GnomeUIBuilderData *uibdata);

static GtkWidget * create_pixmap    (GtkWidget *window, 
                               GnomeUIPixmapType pixmap_type,
                                     gconstpointer pixmap_info);

static GtkWidget * create_label     (const gchar *label_text, guint *keyval);

static void setup_accelerator             (GtkAccelGroup *accel_group, 
                               GnomeUIInfo *uiinfo,
                                     char *signal_name, int accel_flags);

void
sg_ui_create_menus (GtkWidget *app, GnomeUIInfo *uiinfo)
{
        GnomeUIBuilderData uibdata;

        g_return_if_fail (app != NULL);
        g_return_if_fail (GTK_IS_CONTAINER (app));
        g_return_if_fail (uiinfo != NULL);

        uibdata.connect_func = do_ui_signal_connect;
        uibdata.data = NULL;
        uibdata.is_interp = FALSE;
        uibdata.relay_func = NULL;
        uibdata.destroy_func = NULL;

        sg_ui_create_menus_custom (app, uiinfo, &uibdata);
}

void
sg_ui_create_menus_custom (GtkWidget *app, 
                     GnomeUIInfo *uiinfo,
                           GnomeUIBuilderData *uibdata)
{
        GtkWidget *menubar;
        GtkWidget *hb;

        g_return_if_fail (app != NULL);
        g_return_if_fail (GTK_IS_CONTAINER (app));
        g_return_if_fail (uiinfo != NULL);
        g_return_if_fail (uibdata != NULL);

        menubar = gtk_menu_bar_new ();
        sg_ui_fill_menu_custom (GTK_MENU_SHELL (menubar), uiinfo, uibdata,
                                NULL, TRUE, 0);
        hb = gtk_handle_box_new();
        gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
        gtk_widget_show(hb);
        gtk_container_set_border_width(GTK_CONTAINER(hb), 3);
        gtk_container_add(GTK_CONTAINER(hb), menubar);
        gtk_box_pack_start (GTK_BOX(app), hb, FALSE, FALSE, 0);
        gtk_widget_show_all (GTK_WIDGET(app));
}

void
sg_ui_fill_menu_custom (GtkMenuShell       *menu_shell,
                        GnomeUIInfo        *uiinfo,
                        GnomeUIBuilderData *uibdata,
                        GtkAccelGroup      *accel_group,
                        gboolean            uline_accels,
                        gint                pos)
{
        GnomeUIBuilderData *orig_uibdata;

        g_return_if_fail (menu_shell != NULL);
        g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
        g_return_if_fail (uiinfo != NULL);
        g_return_if_fail (uibdata != NULL);
        g_return_if_fail (pos >= 0);

        /* Store a pointer to the original uibdata so that we can use it for
         * the subtrees */

        orig_uibdata = uibdata;

        for (; uiinfo->type != GNOME_APP_UI_ENDOFINFO; uiinfo++)
                switch (uiinfo->type) {
                case GNOME_APP_UI_BUILDER_DATA:
                        /* Set the builder data for subsequent entries in the
                         * current uiinfo array */
                        uibdata = (GnomeUIBuilderData *)uiinfo->moreinfo;
                        break;

                case GNOME_APP_UI_HELP:
                        break;

                case GNOME_APP_UI_RADIOITEMS:
                        break;

                case GNOME_APP_UI_SEPARATOR:
                case GNOME_APP_UI_ITEM:
                case GNOME_APP_UI_ITEM_CONFIGURABLE:
                case GNOME_APP_UI_TOGGLEITEM:
                case GNOME_APP_UI_SUBTREE:
                        if (uiinfo->type == GNOME_APP_UI_SUBTREE_STOCK)
                                create_menu_item (menu_shell, uiinfo, 
                                      uibdata,
                                                  accel_group, uline_accels,
                                                  pos);
                        else
                                create_menu_item (menu_shell, uiinfo, 
                                      uibdata,
                                                  accel_group, uline_accels,
                                                  pos);

                        if (uiinfo->type == GNOME_APP_UI_SUBTREE ||
                            uiinfo->type == GNOME_APP_UI_SUBTREE_STOCK) {
                                /* Create the subtree for this item */

                                GtkWidget *menu;
                                GtkWidget *tearoff;

                                menu = gtk_menu_new ();
                                gtk_menu_item_set_submenu
                                        (GTK_MENU_ITEM(uiinfo->widget), menu);

                                if(accel_group)
                                        gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);

                                sg_ui_fill_menu_custom
                                        (GTK_MENU_SHELL (menu),
                                         (GnomeUIInfo *)uiinfo->moreinfo,
                               orig_uibdata,
                                         accel_group, uline_accels, 0);
                        }
                        pos++;
                        break;

                default:
                        g_warning ("Invalid GnomeUIInfo element type %d\n",
                                   (int) uiinfo->type);
                }

        /* Make the end item contain a pointer to the parent menu shell */

        uiinfo->widget = GTK_WIDGET (menu_shell);

        if (GTK_IS_MENU_BAR (menu_shell))
                gtk_menu_bar_set_shadow_type (GTK_MENU_BAR (menu_shell), 
                                    GTK_SHADOW_NONE);
}

void
sg_ui_create_toolbar (GtkWidget *app, GnomeUIInfo *uiinfo)
{
        GnomeUIBuilderData uibdata;

        g_return_if_fail (app != NULL);
        g_return_if_fail (GTK_IS_CONTAINER (app));
        g_return_if_fail (uiinfo != NULL);

        uibdata.connect_func = do_ui_signal_connect;
        uibdata.data = NULL;
        uibdata.is_interp = FALSE;
        uibdata.relay_func = NULL;
        uibdata.destroy_func = NULL;

        sg_ui_create_toolbar_custom (app, uiinfo, &uibdata);
}

void
sg_ui_create_toolbar_custom (GtkWidget *app, 
                       GnomeUIInfo *uiinfo, 
                       GnomeUIBuilderData *uibdata)
{
        GtkWidget *toolbar;
        GtkWidget *hb;

        g_return_if_fail (app != NULL);
        g_return_if_fail (GTK_IS_CONTAINER (app));
        g_return_if_fail (uiinfo != NULL);
        g_return_if_fail (uibdata != NULL);

        toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
        sg_ui_fill_toolbar_custom(GTK_TOOLBAR (toolbar), uiinfo, uibdata, NULL);
        hb = gtk_handle_box_new();
        gtk_handle_box_set_handle_position(GTK_HANDLE_BOX(hb), GTK_POS_LEFT);
        gtk_widget_show(hb);
        gtk_container_set_border_width(GTK_CONTAINER(hb), 3);
        gtk_container_add(GTK_CONTAINER(hb), toolbar);
        gtk_box_pack_start (GTK_BOX(app), hb, FALSE, FALSE, 0);
        gtk_widget_show_all (GTK_WIDGET(app));
}

void
sg_ui_fill_toolbar_custom (GtkToolbar *toolbar, 
                               GnomeUIInfo *uiinfo,
                               GnomeUIBuilderData *uibdata, 
                               GtkAccelGroup *accel_group)
{
        g_return_if_fail (toolbar != NULL);
        g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
        g_return_if_fail (uiinfo != NULL);
        g_return_if_fail (uibdata != NULL);

        for (; uiinfo->type != GNOME_APP_UI_ENDOFINFO; uiinfo++)
                switch (uiinfo->type) {
                case GNOME_APP_UI_BUILDER_DATA:
                        /* Set the builder data for subsequent entries in the
                         * current uiinfo array */
                        uibdata = (GnomeUIBuilderData *)uiinfo->moreinfo;
                        break;

                case GNOME_APP_UI_SEPARATOR:
                case GNOME_APP_UI_ITEM:
                        create_toolbar_item (toolbar, uiinfo, 
                                             uibdata, accel_group);
                        break;

                default:
                        g_warning ("Invalid GnomeUIInfo element type %d\n",
                                        (int) uiinfo->type);
                }

        /* Make the end item contain a pointer to the parent toolbar */

        uiinfo->widget = GTK_WIDGET (toolbar);

        gtk_toolbar_set_space_size (toolbar, GNOME_PAD);

        gtk_toolbar_set_button_relief (toolbar, GTK_RELIEF_NONE);
        gtk_toolbar_set_style (toolbar, GTK_TOOLBAR_ICONS);
}



static void
create_menu_item (GtkMenuShell       *menu_shell,
                  GnomeUIInfo        *uiinfo,
                  GnomeUIBuilderData *uibdata,
                  GtkAccelGroup      *accel_group,
                  gboolean            uline_accels,
                  gint                pos)
{
        GtkWidget *label;
        GtkWidget *pixmap;
        guint keyval;
        int type;

        /* Translate configurable menu items to normal menu items. */

        /* Create the menu item */

        switch (uiinfo->type) {
        case GNOME_APP_UI_SEPARATOR:
                uiinfo->widget = gtk_menu_item_new ();
                break;
        case GNOME_APP_UI_ITEM:
        case GNOME_APP_UI_SUBTREE:
        case GNOME_APP_UI_SUBTREE_STOCK:
                if (uiinfo->pixmap_type != GNOME_APP_PIXMAP_NONE && uiinfo->pixmap_info != NULL) {
                        uiinfo->widget = GTK_WIDGET(gtk_pixmap_menu_item_new ());
                        pixmap = create_pixmap (uiinfo->widget, 
                                    uiinfo->pixmap_type,
                                                uiinfo->pixmap_info);

                        if (pixmap) {
                                gtk_widget_show(pixmap);
                                gtk_pixmap_menu_item_set_pixmap(GTK_PIXMAP_MENU_ITEM(uiinfo->widget),
                                                                pixmap);                                }
                } else
                        uiinfo->widget = gtk_menu_item_new ();
                break;

        default:
                g_warning ("Invalid GnomeUIInfo type %d passed to "
                           "create_menu_item()", (int) uiinfo->type);
                return;
        }

        if (!accel_group)
                gtk_widget_lock_accelerators (uiinfo->widget);

        gtk_widget_show (uiinfo->widget);
        gtk_menu_shell_insert (menu_shell, uiinfo->widget, pos);

        /* If it is a separator, set it as insensitive so that it cannot be
         * selected, and return -- there is nothing left to do.
         */

        if (uiinfo->type == GNOME_APP_UI_SEPARATOR) {
                gtk_widget_set_sensitive (uiinfo->widget, FALSE);
                return;
        }

        /* Create the contents of the menu item */

        /* Don't use gettext on the empty string since gettext will map
         * the empty string to the header at the beginning of the .pot file. */

#ifdef WITH_WARNINGS
#warning TODO label = create_label(gint) uiinfo->label[0] == '\0' ?
#endif
/*
        label = create_label ( (gint) uiinfo->label[0] == '\0' ?
                               "":(uiinfo->type == GNOME_APP_UI_SUBTREE_STOCK ?
                                   D_(uiinfo->label):L_(uiinfo->label)),
                               &keyval);
*/
        label = create_label (uiinfo->label[0] == '\0'? "" : uiinfo->label, &keyval);
        gtk_container_add (GTK_CONTAINER (uiinfo->widget), label);

        gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label),
                                          uiinfo->widget);

        /* setup underline accelerators
         */
        if (uline_accels)
                setup_uline_accel (menu_shell,
                                   accel_group,
                                   uiinfo->widget,
                                   keyval);

        /* install global accelerator
         */
        {
                static guint save_accels_id = 0;
                GString *gstring;
                GtkWidget *widget;

                /* build up the menu item path */
                gstring = g_string_new ("");
                widget = uiinfo->widget;
                while (widget) {
                        if (GTK_IS_MENU_ITEM (widget)) {
                                GtkWidget *child = GTK_BIN (widget)->child;

                                if (GTK_IS_LABEL (child)) {
                                        g_string_prepend (gstring, GTK_LABEL (child)->label);
                                        g_string_prepend_c (gstring, '/');
                                }
                                widget = widget->parent;
                        } else if (GTK_IS_MENU (widget)) {
                                widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
                                if (widget == NULL) {
                                        g_string_prepend (gstring, "/-Orphan");
                                        widget = NULL;
                                }
                        } else
                                widget = widget->parent;
                }
                g_string_prepend_c (gstring, '>');
                g_string_prepend (gstring, "");
                g_string_prepend_c (gstring, '<');

                /* g_print ("######## menu item path: %s\n", gstring->str); */

                /* the item factory cares about installing the correct accelerator */

                if(accel_group)
                gtk_item_factory_add_foreign (uiinfo->widget,
                                              gstring->str,
                                              accel_group,
                                              uiinfo->accelerator_key,
                                              uiinfo->ac_mods);
                g_string_free (gstring, TRUE);

        }

        /* Connect to the signal and set user data */

        type = uiinfo->type;
        if (type == GNOME_APP_UI_SUBTREE_STOCK)
                type = GNOME_APP_UI_SUBTREE;

        if (type != GNOME_APP_UI_SUBTREE) {
                gtk_object_set_data (GTK_OBJECT (uiinfo->widget),
                                     GNOMEUIINFO_KEY_UIDATA,
                                     uiinfo->user_data);

                gtk_object_set_data (GTK_OBJECT (uiinfo->widget),
                                     GNOMEUIINFO_KEY_UIBDATA,
                                     uibdata->data);


                (* uibdata->connect_func) (uiinfo, "activate", uibdata);
        }
}


static void
create_toolbar_item (GtkToolbar *toolbar, 
                     GnomeUIInfo *uiinfo, 
                     GnomeUIBuilderData *uibdata,
                     GtkAccelGroup *accel_group)
{
        GtkWidget *pixmap;
        GtkToolbarChildType type;

        switch (uiinfo->type) {
        case GNOME_APP_UI_SEPARATOR:
                gtk_toolbar_append_space (toolbar);
                uiinfo->widget = NULL; /* no meaningful widget for a space */
                break;

        case GNOME_APP_UI_ITEM:
        case GNOME_APP_UI_TOGGLEITEM:
                /* Create the icon */

                pixmap = create_pixmap (GTK_WIDGET (toolbar),
                                uiinfo->pixmap_type, uiinfo->pixmap_info);

                /* Create the toolbar item */

                if (uiinfo->type == GNOME_APP_UI_ITEM)
                        type = GTK_TOOLBAR_CHILD_BUTTON;
                else
                        type = GTK_TOOLBAR_CHILD_TOGGLEBUTTON;

                uiinfo->widget =
                        gtk_toolbar_append_element (toolbar,
                                                    type,
                                                    NULL,
#ifdef WITH_WARNINGS
#warning TODO gtk_toolbar_append_element (toolbar,
#warning               L_(uiinfo->label),
#warning               L_(uiinfo->hint),
#endif
                                        uiinfo->label,
                                                    uiinfo->hint,
                                                    NULL,
                                                    pixmap,
                                                    NULL,
                                                    NULL);
            break;
        default:
                g_warning ("Invalid GnomeUIInfo type %d passed to "
                           "create_toolbar_item()", (int) uiinfo->type);
                return;
        }

        if (uiinfo->type == GNOME_APP_UI_SEPARATOR)
                return; /* nothing more to do */

        /* Set the accelerator and connect to the signal */

        setup_accelerator (accel_group, uiinfo, "clicked", 0);
        (* uibdata->connect_func) (uiinfo, "clicked", uibdata);
}

static void
setup_uline_accel (GtkMenuShell  *menu_shell,
                   GtkAccelGroup *accel_group,
                   GtkWidget     *menu_item,
                   guint          keyval)
{
        if (keyval != GDK_VoidSymbol) {
                if (accel_group && GTK_IS_MENU (menu_shell))
                        gtk_widget_add_accelerator (menu_item,
                                                    "activate_item",
                                                    gtk_menu_ensure_uline_accel_group (GTK_MENU (menu_shell)),
                                                    keyval, 0,
                                                    (GtkAccelFlags)0);
                if (GTK_IS_MENU_BAR (menu_shell) && accel_group)
                        gtk_widget_add_accelerator (menu_item,
                                                    "activate_item",
                                                    accel_group,
                                                    keyval, GDK_MOD1_MASK,
                                                    (GtkAccelFlags)0);
        }
}

static void
do_ui_signal_connect (GnomeUIInfo *uiinfo, gchar *signal_name,
                      GnomeUIBuilderData *uibdata)
{
        if (signal_name && uiinfo->moreinfo)
            gtk_signal_connect (GTK_OBJECT (uiinfo->widget), signal_name,
                              GTK_SIGNAL_FUNC(uiinfo->moreinfo),
                        uibdata->data ? uibdata->data : uiinfo->user_data);
}

static GtkWidget *
create_pixmap (GtkWidget *window, GnomeUIPixmapType pixmap_type,
               gconstpointer pixmap_info)
{
        GtkWidget *pixmap;
        GdkPixmap *tool;
        GdkBitmap *mask;
        GdkColormap *colormap;
        gchar *name;

        colormap = gdk_colormap_get_system();

        pixmap = NULL;

        switch (pixmap_type) {
        case GNOME_APP_PIXMAP_STOCK:
                break;

        case GNOME_APP_PIXMAP_DATA:
                if (pixmap_info){
                        tool = gdk_pixmap_colormap_create_from_xpm_d(NULL, colormap, &mask, NULL, (gchar **)pixmap_info);
                        pixmap = gtk_pixmap_new(tool, mask);
                }

                break;

        case GNOME_APP_PIXMAP_NONE:
                break;

        case GNOME_APP_PIXMAP_FILENAME:
                break;

        default:
                g_assert_not_reached ();
                g_warning("Invalid pixmap_type %d", (int) pixmap_type);
        }

        return pixmap;
}

static GtkWidget *
create_label (const gchar *label_text, guint *keyval)
{
        guint kv;
        GtkWidget *label;

        label = gtk_accel_label_new (label_text);

        kv = gtk_label_parse_uline (GTK_LABEL (label), label_text);
        if (keyval)
                *keyval = kv;

        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
        gtk_widget_show (label);

        return label;
}

static void
setup_accelerator (GtkAccelGroup *accel_group, GnomeUIInfo *uiinfo,
                   char *signal_name, int accel_flags)
{
        if (accel_group && uiinfo->accelerator_key != 0)
                gtk_widget_add_accelerator (uiinfo->widget, signal_name,
                                            accel_group, 
                                            uiinfo->accelerator_key,
                                            uiinfo->ac_mods,
                                  (GtkAccelFlags)accel_flags);
}



Generated by  Doxygen 1.6.0   Back to index