/* SciGraphica - Scientific graphics and data manipulation * Copyright (C) 2001 Adrian E. Feiguin * * 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 #include #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); }