/* 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);
}
syntax highlighted by Code2HTML, v. 0.9.1