* Copyright (C) 1998 Tim Janik
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
- * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include "config.h"
+
#include "gtkitemfactory.h"
#include "gtk/gtksignal.h"
#include "gtk/gtkoptionmenu.h"
#include "gtk/gtkmenuitem.h"
#include "gtk/gtkradiomenuitem.h"
#include "gtk/gtkcheckmenuitem.h"
+#include "gtk/gtkimagemenuitem.h"
#include "gtk/gtktearoffmenuitem.h"
+#include "gtk/gtkaccelmap.h"
#include "gtk/gtkaccellabel.h"
#include "gdk/gdkkeysyms.h"
+#include "gtk/gtkimage.h"
+#include "gtk/gtkstock.h"
+#include "gtk/gtkiconfactory.h"
#include <string.h>
-#include <sys/stat.h>
#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <stdio.h>
-
-
/* --- defines --- */
#define ITEM_FACTORY_STRING ((gchar*) item_factory_string)
#define ITEM_BLOCK_SIZE (128)
/* --- structures --- */
typedef struct _GtkIFCBData GtkIFCBData;
-typedef struct _GtkIFActionLink GtkIFActionLink;
typedef struct _GtkIFDumpData GtkIFDumpData;
struct _GtkIFCBData
{
gpointer func_data;
guint callback_action;
};
-struct _GtkIFActionLink
-{
- GtkWidget *widget;
- guint callback_action;
-};
-struct _GtkIFDumpData
-{
- GtkPrintFunc print_func;
- gpointer func_data;
- guint modified_only : 1;
- GtkPatternSpec *pspec;
-};
/* --- prototypes --- */
static void gtk_item_factory_class_init (GtkItemFactoryClass *klass);
static void gtk_item_factory_init (GtkItemFactory *ifactory);
static void gtk_item_factory_destroy (GtkObject *object);
-static void gtk_item_factory_finalize (GtkObject *object);
+static void gtk_item_factory_finalize (GObject *object);
/* --- static variables --- */
static GtkItemFactoryClass *gtk_item_factory_class = NULL;
-static GtkObjectClass *parent_class = NULL;
+static gpointer parent_class = NULL;
static const gchar *item_factory_string = "Gtk-<ItemFactory>";
static GMemChunk *ifactory_item_chunks = NULL;
static GMemChunk *ifactory_cb_data_chunks = NULL;
-static const gchar *key_popup_data = "GtkItemFactory-popup-data";
static GQuark quark_popup_data = 0;
-static const gchar *key_if_menu_pos = "GtkItemFactory-menu-position";
static GQuark quark_if_menu_pos = 0;
-static const gchar *key_item_factory = "GtkItemFactory";
static GQuark quark_item_factory = 0;
-static const gchar *key_item_factory_path = "GtkItemFactory-path";
-static GQuark quark_item_factory_path = 0;
-static const gchar *key_type_item = "<Item>";
+static GQuark quark_item_path = 0;
+static GQuark quark_action = 0;
+static GQuark quark_accel_group = 0;
static GQuark quark_type_item = 0;
-static const gchar *key_type_title = "<Title>";
static GQuark quark_type_title = 0;
-static const gchar *key_type_radio_item = "<RadioItem>";
static GQuark quark_type_radio_item = 0;
-static const gchar *key_type_check_item = "<CheckItem>";
static GQuark quark_type_check_item = 0;
-static const gchar *key_type_toggle_item = "<ToggleItem>";
static GQuark quark_type_toggle_item = 0;
-static const gchar *key_type_tearoff_item = "<Tearoff>";
+static GQuark quark_type_image_item = 0;
+static GQuark quark_type_stock_item = 0;
static GQuark quark_type_tearoff_item = 0;
-static const gchar *key_type_separator_item = "<Separator>";
static GQuark quark_type_separator_item = 0;
-static const gchar *key_type_branch = "<Branch>";
static GQuark quark_type_branch = 0;
-static const gchar *key_type_last_branch = "<LastBranch>";
static GQuark quark_type_last_branch = 0;
-static GScannerConfig ifactory_scanner_config =
-{
- (
- " \t\n"
- ) /* cset_skip_characters */,
- (
- G_CSET_a_2_z
- "_"
- G_CSET_A_2_Z
- ) /* cset_identifier_first */,
- (
- G_CSET_a_2_z
- "-+_0123456789"
- G_CSET_A_2_Z
- G_CSET_LATINS
- G_CSET_LATINC
- ) /* cset_identifier_nth */,
- ( ";\n" ) /* cpair_comment_single */,
-
- FALSE /* case_sensitive */,
-
- TRUE /* skip_comment_multi */,
- TRUE /* skip_comment_single */,
- FALSE /* scan_comment_multi */,
- TRUE /* scan_identifier */,
- FALSE /* scan_identifier_1char */,
- FALSE /* scan_identifier_NULL */,
- TRUE /* scan_symbols */,
- TRUE /* scan_binary */,
- TRUE /* scan_octal */,
- TRUE /* scan_float */,
- TRUE /* scan_hex */,
- FALSE /* scan_hex_dollar */,
- TRUE /* scan_string_sq */,
- TRUE /* scan_string_dq */,
- TRUE /* numbers_2_int */,
- FALSE /* int_2_float */,
- FALSE /* identifier_2_string */,
- TRUE /* char_2_token */,
- FALSE /* symbol_2_token */,
-};
/* --- functions --- */
static void
gtk_item_factory_class_init (GtkItemFactoryClass *class)
{
- GtkObjectClass *object_class;
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
gtk_item_factory_class = class;
+ parent_class = g_type_class_peek_parent (class);
- parent_class = gtk_type_class (GTK_TYPE_OBJECT);
-
- object_class = (GtkObjectClass*) class;
+ gobject_class->finalize = gtk_item_factory_finalize;
object_class->destroy = gtk_item_factory_destroy;
- object_class->finalize = gtk_item_factory_finalize;
-
- class->cpair_comment_single = g_strdup (";\n");
class->item_ht = g_hash_table_new (g_str_hash, g_str_equal);
ifactory_item_chunks =
sizeof (GtkIFCBData) * ITEM_BLOCK_SIZE,
G_ALLOC_AND_FREE);
- quark_popup_data = g_quark_from_static_string (key_popup_data);
- quark_if_menu_pos = g_quark_from_static_string (key_if_menu_pos);
- quark_item_factory = g_quark_from_static_string (key_item_factory);
- quark_item_factory_path = g_quark_from_static_string (key_item_factory_path);
- quark_type_item = g_quark_from_static_string (key_type_item);
- quark_type_title = g_quark_from_static_string (key_type_title);
- quark_type_radio_item = g_quark_from_static_string (key_type_radio_item);
- quark_type_check_item = g_quark_from_static_string (key_type_check_item);
- quark_type_toggle_item = g_quark_from_static_string (key_type_toggle_item);
- quark_type_tearoff_item = g_quark_from_static_string (key_type_tearoff_item);
- quark_type_separator_item = g_quark_from_static_string (key_type_separator_item);
- quark_type_branch = g_quark_from_static_string (key_type_branch);
- quark_type_last_branch = g_quark_from_static_string (key_type_last_branch);
+ quark_popup_data = g_quark_from_static_string ("GtkItemFactory-popup-data");
+ quark_if_menu_pos = g_quark_from_static_string ("GtkItemFactory-menu-position");
+ quark_item_factory = g_quark_from_static_string ("GtkItemFactory");
+ quark_item_path = g_quark_from_static_string ("GtkItemFactory-path");
+ quark_action = g_quark_from_static_string ("GtkItemFactory-action");
+ quark_accel_group = g_quark_from_static_string ("GtkAccelGroup");
+ quark_type_item = g_quark_from_static_string ("<Item>");
+ quark_type_title = g_quark_from_static_string ("<Title>");
+ quark_type_radio_item = g_quark_from_static_string ("<RadioItem>");
+ quark_type_check_item = g_quark_from_static_string ("<CheckItem>");
+ quark_type_toggle_item = g_quark_from_static_string ("<ToggleItem>");
+ quark_type_image_item = g_quark_from_static_string ("<ImageItem>");
+ quark_type_stock_item = g_quark_from_static_string ("<StockItem>");
+ quark_type_separator_item = g_quark_from_static_string ("<Separator>");
+ quark_type_tearoff_item = g_quark_from_static_string ("<Tearoff>");
+ quark_type_branch = g_quark_from_static_string ("<Branch>");
+ quark_type_last_branch = g_quark_from_static_string ("<LastBranch>");
}
static void
ifactory->path = NULL;
ifactory->accel_group = NULL;
ifactory->widget = NULL;
- ifactory->widgets_by_action = NULL;
+ ifactory->items = NULL;
+ ifactory->translate_func = NULL;
+ ifactory->translate_data = NULL;
+ ifactory->translate_notify = NULL;
}
+/**
+ * gtk_item_factory_new:
+ * @container_type: the kind of menu to create; can be
+ * #GTK_TYPE_MENU_BAR, #GTK_TYPE_MENU or #GTK_TYPE_OPTION_MENU
+ * @path: the factory path of the new item factory, a string of the form
+ * <literal>"<name>"</literal>
+ * @accel_group: a #GtkAccelGroup to which the accelerators for the
+ * menu items will be added, or %NULL to create a new one
+ * @returns: a new #GtkItemFactory
+ *
+ * Creates a new #GtkItemFactory.
+ */
GtkItemFactory*
gtk_item_factory_new (GtkType container_type,
const gchar *path,
if (data->callback_type == 1)
{
- GtkItemFactoryCallback1 func1 = data->func;
+ GtkItemFactoryCallback1 func1 = (GtkItemFactoryCallback1) data->func;
func1 (data->func_data, data->callback_action, widget);
}
else if (data->callback_type == 2)
{
- GtkItemFactoryCallback2 func2 = data->func;
+ GtkItemFactoryCallback2 func2 = (GtkItemFactoryCallback2) data->func;
func2 (widget, data->func_data, data->callback_action);
}
}
static void
-gtk_item_factory_propagate_accelerator (GtkItemFactoryItem *item,
- GtkWidget *exclude)
+gtk_item_factory_item_remove_widget (GtkWidget *widget,
+ GtkItemFactoryItem *item)
{
- GSList *widget_list;
- GSList *slist;
-
- if (item->in_propagation)
- return;
-
- item->in_propagation = TRUE;
-
- widget_list = NULL;
- for (slist = item->widgets; slist; slist = slist->next)
- {
- GtkWidget *widget;
-
- widget = slist->data;
-
- if (widget != exclude)
- {
- gtk_widget_ref (widget);
- widget_list = g_slist_prepend (widget_list, widget);
- }
- }
-
- for (slist = widget_list; slist; slist = slist->next)
- {
- GtkWidget *widget;
- GtkItemFactory *ifactory;
-
- widget = slist->data;
-
- ifactory = gtk_item_factory_from_widget (widget);
-
- if (ifactory)
- {
- guint signal_id;
-
- signal_id = gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget));
- if (signal_id)
- {
- if (item->accelerator_key)
- gtk_widget_add_accelerator (widget,
- "activate",
- ifactory->accel_group,
- item->accelerator_key,
- item->accelerator_mods,
- GTK_ACCEL_VISIBLE);
- else
- {
- GSList *work;
-
- work = gtk_accel_group_entries_from_object (GTK_OBJECT (widget));
- while (work)
- {
- GtkAccelEntry *ac_entry;
-
- ac_entry = work->data;
- work = work->next;
- if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE &&
- ac_entry->accel_group == ifactory->accel_group &&
- ac_entry->signal_id == signal_id)
- gtk_widget_remove_accelerator (GTK_WIDGET (widget),
- ac_entry->accel_group,
- ac_entry->accelerator_key,
- ac_entry->accelerator_mods);
- }
- }
- }
- }
- gtk_widget_unref (widget);
- }
- g_slist_free (widget_list);
-
- item->in_propagation = FALSE;
+ item->widgets = g_slist_remove (item->widgets, widget);
+ gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_factory);
+ gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_path);
}
-static gint
-gtk_item_factory_item_add_accelerator (GtkWidget *widget,
- guint accel_signal_id,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods,
- GtkAccelFlags accel_flags,
- GtkItemFactoryItem *item)
+/**
+ * gtk_item_factory_add_foreign:
+ * @accel_widget: widget to install an accelerator on
+ * @full_path: the full path for the @accel_widget
+ * @accel_group: the accelerator group to install the accelerator in
+ * @keyval: key value of the accelerator
+ * @modifiers: modifier combination of the accelerator
+ *
+ * Installs an accelerator for @accel_widget in @accel_group, that causes
+ * the ::activate signal to be emitted if the accelerator is activated.
+ *
+ * This function can be used to make widgets participate in the accel
+ * saving/restoring functionality provided by gtk_accel_map_save() and
+ * gtk_accel_map_load(), even if they haven't been created by an item
+ * factory.
+ */
+void
+gtk_item_factory_add_foreign (GtkWidget *accel_widget,
+ const gchar *full_path,
+ GtkAccelGroup *accel_group,
+ guint keyval,
+ GdkModifierType modifiers)
{
- if (!item->in_propagation &&
- g_slist_find (item->widgets, widget) &&
- accel_signal_id == gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget)))
+ GtkItemFactoryClass *class;
+ GtkItemFactoryItem *item;
+
+ g_return_if_fail (GTK_IS_WIDGET (accel_widget));
+ g_return_if_fail (full_path != NULL);
+
+ class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
+
+ keyval = keyval != GDK_VoidSymbol ? keyval : 0;
+
+ item = g_hash_table_lookup (class->item_ht, full_path);
+ if (!item)
{
- item->accelerator_key = accel_key;
- item->accelerator_mods = accel_mods;
- item->modified = TRUE;
+ item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
+
+ item->path = g_strdup (full_path);
+ item->widgets = NULL;
- gtk_item_factory_propagate_accelerator (item, widget);
+ g_hash_table_insert (class->item_ht, item->path, item);
}
- return TRUE;
-}
+ item->widgets = g_slist_prepend (item->widgets, accel_widget);
+ gtk_signal_connect (GTK_OBJECT (accel_widget),
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_widget),
+ item);
-static void
-gtk_item_factory_item_remove_accelerator (GtkWidget *widget,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods,
- GtkItemFactoryItem *item)
-{
- if (!item->in_propagation &&
- g_slist_find (item->widgets, widget) &&
- item->accelerator_key == accel_key &&
- item->accelerator_mods == accel_mods)
+ /* set the item path for the widget
+ */
+ gtk_object_set_data_by_id (GTK_OBJECT (accel_widget),
+ quark_item_path, item->path);
+ gtk_widget_set_name (accel_widget, item->path);
+ if (accel_group)
{
- item->accelerator_key = 0;
- item->accelerator_mods = 0;
- item->modified = TRUE;
-
- gtk_item_factory_propagate_accelerator (item, widget);
+ gtk_accel_group_ref (accel_group);
+ gtk_object_set_data_by_id_full (GTK_OBJECT (accel_widget),
+ quark_accel_group,
+ accel_group,
+ (GtkDestroyNotify) gtk_accel_group_unref);
}
-}
+ else
+ gtk_object_set_data_by_id (GTK_OBJECT (accel_widget),
+ quark_accel_group, NULL);
-static void
-gtk_item_factory_item_remove_widget (GtkWidget *widget,
- GtkItemFactoryItem *item)
-{
- item->widgets = g_slist_remove (item->widgets, widget);
- gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_factory);
- gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_factory_path);
+ /* install defined accelerators
+ */
+ if (gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (accel_widget)))
+ {
+ if (accel_group)
+ {
+ gtk_accel_map_add_entry (full_path, keyval, modifiers);
+ gtk_widget_set_accel_path (accel_widget, full_path, accel_group);
+ }
+ }
}
static void
GtkItemFactoryClass *class;
GtkItemFactoryItem *item;
gchar *fpath;
+ guint keyval, mods;
g_return_if_fail (widget != NULL);
g_return_if_fail (item_type != NULL);
- class = GTK_ITEM_FACTORY_CLASS (GTK_OBJECT (ifactory)->klass);
-
- fpath = g_strconcat (ifactory->path, path, NULL);
- item = g_hash_table_lookup (class->item_ht, fpath);
-
- /* link the widget into its item-entry
- */
- if (!item)
- {
- guint keyval;
- guint mods;
-
- if (accelerator)
- gtk_accelerator_parse (accelerator, &keyval, &mods);
- else
- {
- keyval = 0;
- mods = 0;
- }
-
- item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
-
- item->path = fpath;
- fpath = NULL;
- item->accelerator_key = keyval;
- item->accelerator_mods = mods;
- item->modified = FALSE;
- item->in_propagation = FALSE;
- item->item_type = NULL;
- item->widgets = NULL;
-
- g_hash_table_insert (class->item_ht, item->path, item);
- }
- g_free (fpath);
-
- if (item->item_type == NULL)
- {
- g_assert (item->widgets == NULL);
-
- if (item_type != ITEM_FACTORY_STRING)
- item->item_type = g_strdup (item_type);
- else
- item->item_type = ITEM_FACTORY_STRING;
- }
-
- item->widgets = g_slist_prepend (item->widgets, widget);
- gtk_signal_connect (GTK_OBJECT (widget),
- "destroy",
- GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_widget),
- item);
-
- /* set back pointers for the widget
- */
- gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_factory, ifactory);
- gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_factory_path, item->path);
- gtk_widget_set_name (widget, item->path);
+ class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
/* set accelerator group on menu widgets
*/
if (GTK_IS_MENU (widget))
gtk_menu_set_accel_group ((GtkMenu*) widget, ifactory->accel_group);
- /* install defined accelerators
- */
- if (gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget)))
- {
- if (item->accelerator_key)
- gtk_widget_add_accelerator (widget,
- "activate",
- ifactory->accel_group,
- item->accelerator_key,
- item->accelerator_mods,
- GTK_ACCEL_VISIBLE);
- else
- gtk_widget_remove_accelerators (widget,
- "activate",
- TRUE);
- }
-
- /* keep track of accelerator changes
- */
- gtk_signal_connect_after (GTK_OBJECT (widget),
- "add-accelerator",
- GTK_SIGNAL_FUNC (gtk_item_factory_item_add_accelerator),
- item);
- gtk_signal_connect_after (GTK_OBJECT (widget),
- "remove-accelerator",
- GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_accelerator),
- item);
-
- /* keep a per-action list of the widgets on the factory
- */
- if (callback)
- {
- GtkIFActionLink *link;
-
- link = g_new (GtkIFActionLink, 1);
- link->widget = widget;
- link->callback_action = callback_action;
- ifactory->widgets_by_action = g_slist_prepend (ifactory->widgets_by_action, link);
- }
-
/* connect callback if neccessary
*/
if (callback)
GTK_SIGNAL_FUNC (gtk_item_factory_callback_marshal),
data);
}
+
+ /* link the widget into its item-entry
+ * and keep back pointer on both the item factory and the widget
+ */
+ gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_action, GUINT_TO_POINTER (callback_action));
+ gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_factory, ifactory);
+ if (accelerator)
+ gtk_accelerator_parse (accelerator, &keyval, &mods);
+ else
+ {
+ keyval = 0;
+ mods = 0;
+ }
+ fpath = g_strconcat (ifactory->path, path, NULL);
+ gtk_item_factory_add_foreign (widget, fpath, ifactory->accel_group, keyval, mods);
+ item = g_hash_table_lookup (class->item_ht, fpath);
+ g_free (fpath);
+
+ g_return_if_fail (item != NULL);
+
+ if (!g_slist_find (ifactory->items, item))
+ ifactory->items = g_slist_prepend (ifactory->items, item);
}
+/**
+ * gtk_item_factory_construct:
+ * @ifactory: a #GtkItemFactory
+ * @container_type: the kind of menu to create; can be
+ * #GTK_TYPE_MENU_BAR, #GTK_TYPE_MENU or #GTK_TYPE_OPTION_MENU
+ * @path: the factory path of @ifactory, a string of the form
+ * <literal>"<name>"</literal>
+ * @accel_group: a #GtkAccelGroup to which the accelerators for the
+ * menu items will be added, or %NULL to create a new one
+ *
+ * Initializes an item factory.
+ */
void
gtk_item_factory_construct (GtkItemFactory *ifactory,
GtkType container_type,
const gchar *path,
GtkAccelGroup *accel_group)
{
- GtkAccelGroup *menu_group;
guint len;
- g_return_if_fail (ifactory != NULL);
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
g_return_if_fail (ifactory->accel_group == NULL);
g_return_if_fail (path != NULL);
ifactory->accel_group = gtk_accel_group_new ();
ifactory->path = g_strdup (path);
- ifactory->widget =
- gtk_widget_new (container_type,
- "GtkObject::signal::destroy", gtk_widget_destroyed, &ifactory->widget,
- NULL);
+ ifactory->widget = g_object_connect (gtk_widget_new (container_type, NULL),
+ "signal::destroy", gtk_widget_destroyed, &ifactory->widget,
+ NULL);
gtk_object_ref (GTK_OBJECT (ifactory));
gtk_object_sink (GTK_OBJECT (ifactory));
- menu_group = gtk_accel_group_new ();
- gtk_accel_group_attach (menu_group, GTK_OBJECT (ifactory->widget));
-
- /*
- gtk_signal_connect_object_while_alive (GTK_OBJECT (ifactory->widget),
- "destroy",
- GTK_SIGNAL_FUNC (gtk_object_destroy),
- GTK_OBJECT (ifactory));
- */
gtk_item_factory_add_item (ifactory,
"", NULL,
NULL, 0, NULL, 0,
ifactory->widget);
}
+/**
+ * gtk_item_factory_from_path:
+ * @path: a string starting with a factory path of the form
+ * <literal>"<name>"</literal>
+ * @returns: the #GtkItemFactory created for the given factory path, or %NULL
+ *
+ * Finds an item factory which has been constructed using the
+ * <literal>"<name>"</literal> prefix of @path as the @path argument
+ * for gtk_item_factory_new().
+ */
GtkItemFactory*
gtk_item_factory_from_path (const gchar *path)
{
GtkItemFactory *ifactory;
GSList *slist;
- g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_ITEM_FACTORY (object));
ifactory = (GtkItemFactory*) object;
ifactory->widget = NULL;
}
- for (slist = ifactory->widgets_by_action; slist; slist = slist->next)
- g_free (slist->data);
- g_slist_free (ifactory->widgets_by_action);
- ifactory->widgets_by_action = NULL;
+ for (slist = ifactory->items; slist; slist = slist->next)
+ {
+ GtkItemFactoryItem *item = slist->data;
+ GSList *link;
+
+ for (link = item->widgets; link; link = link->next)
+ if (gtk_object_get_data_by_id (link->data, quark_item_factory) == ifactory)
+ gtk_object_remove_data_by_id (link->data, quark_item_factory);
+ }
+ g_slist_free (ifactory->items);
+ ifactory->items = NULL;
- parent_class->destroy (object);
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void
-gtk_item_factory_finalize (GtkObject *object)
+gtk_item_factory_finalize (GObject *object)
{
GtkItemFactory *ifactory;
- g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_ITEM_FACTORY (object));
ifactory = GTK_ITEM_FACTORY (object);
g_free (ifactory->path);
g_assert (ifactory->widget == NULL);
- if (ifactory->translate_data && ifactory->translate_notify)
+ if (ifactory->translate_notify)
ifactory->translate_notify (ifactory->translate_data);
- parent_class->finalize (object);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
+/**
+ * gtk_item_factory_from_widget:
+ * @widget: a widget
+ * @returns: the item factory from which @widget was created, or %NULL
+ *
+ * Obtains the item factory from which a widget was created.
+ */
GtkItemFactory*
gtk_item_factory_from_widget (GtkWidget *widget)
{
- g_return_val_if_fail (widget != NULL, NULL);
- g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
-
- return gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_factory);
-}
+ GtkItemFactory *ifactory;
-gchar*
-gtk_item_factory_path_from_widget (GtkWidget *widget)
-{
- g_return_val_if_fail (widget != NULL, NULL);
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- return gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_factory_path);
-}
-
-static void
-gtk_item_factory_foreach (gpointer hash_key,
- gpointer value,
- gpointer user_data)
-{
- GtkItemFactoryItem *item;
- GtkIFDumpData *data;
- gchar *string;
- gchar *name;
- gchar comment_prefix[2] = "\000\000";
-
- item = value;
- data = user_data;
-
- if (data->pspec && !gtk_pattern_match_string (data->pspec, item->path))
- return;
-
- comment_prefix[0] = gtk_item_factory_class->cpair_comment_single[0];
-
- name = gtk_accelerator_name (item->accelerator_key, item->accelerator_mods);
- string = g_strconcat (item->modified ? "" : comment_prefix,
- "(menu-path \"",
- hash_key,
- "\" \"",
- name,
- "\")",
- NULL);
- g_free (name);
-
- data->print_func (data->func_data, string);
-
- g_free (string);
-}
-
-void
-gtk_item_factory_dump_items (GtkPatternSpec *path_pspec,
- gboolean modified_only,
- GtkPrintFunc print_func,
- gpointer func_data)
-{
- GtkIFDumpData data;
-
- g_return_if_fail (print_func != NULL);
-
- if (!gtk_item_factory_class)
- gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
- data.print_func = print_func;
- data.func_data = func_data;
- data.modified_only = (modified_only != FALSE);
- data.pspec = path_pspec;
-
- g_hash_table_foreach (gtk_item_factory_class->item_ht, gtk_item_factory_foreach, &data);
-}
-
-void
-gtk_item_factory_print_func (gpointer FILE_pointer,
- gchar *string)
-{
- FILE *f_out = FILE_pointer;
+ ifactory = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_factory);
+ if (ifactory == NULL && GTK_IS_MENU_ITEM (widget) &&
+ GTK_MENU_ITEM (widget)->submenu != NULL)
+ {
+ GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
+ ifactory = gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_item_factory);
+ }
- g_return_if_fail (FILE_pointer != NULL);
- g_return_if_fail (string != NULL);
-
- fputs (string, f_out);
- fputc ('\n', f_out);
+ return ifactory;
}
-void
-gtk_item_factory_dump_rc (const gchar *file_name,
- GtkPatternSpec *path_pspec,
- gboolean modified_only)
+/**
+ * gtk_item_factory_path_from_widget:
+ * @widget: a widget
+ * @returns: the full path to @widget if it been created by an item factory,
+ * %NULL otherwise. This value is owned by GTK+ and must not be
+ * modified or freed.
+ *
+ * If @widget has been created by an item factory, returns the full path
+ * to it. (The full path of a widget is the concatenation of the factory
+ * path specified in gtk_item_factory_new() with the path specified in the
+ * #GtkItemFactoryEntry from which the widget was created.)
+ */
+G_CONST_RETURN gchar*
+gtk_item_factory_path_from_widget (GtkWidget *widget)
{
- FILE *f_out;
-
- g_return_if_fail (file_name != NULL);
+ gchar* path;
- f_out = fopen (file_name, "w");
- if (!f_out)
- return;
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- fputs ("; ", f_out);
- if (g_get_prgname ())
- fputs (g_get_prgname (), f_out);
- fputs (" GtkItemFactory rc-file -*- scheme -*-\n", f_out);
- fputs ("; this file is an automated menu-path dump\n", f_out);
- fputs (";\n", f_out);
+ path = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_path);
- gtk_item_factory_dump_items (path_pspec,
- modified_only,
- gtk_item_factory_print_func,
- f_out);
+ if (path == NULL && GTK_IS_MENU_ITEM (widget) &&
+ GTK_MENU_ITEM (widget)->submenu != NULL)
+ {
+ GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
+ path = gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_item_path);
+ }
- fclose (f_out);
+ return path;
}
+/**
+ * gtk_item_factory_create_items:
+ * @ifactory: a #GtkItemFactory
+ * @n_entries: the length of @entries
+ * @entries: an array of #GtkItemFactoryEntry<!>s whose @callback members
+ * must by of type #GtkItemFactoryCallback1
+ * @callback_data: data passed to the callback functions of all entries
+ *
+ * Creates the menu items from the @entries.
+ */
void
-gtk_item_factory_create_items (GtkItemFactory *ifactory,
- guint n_entries,
- GtkItemFactoryEntry *entries,
- gpointer callback_data)
+gtk_item_factory_create_items (GtkItemFactory *ifactory,
+ guint n_entries,
+ GtkItemFactoryEntry *entries,
+ gpointer callback_data)
{
gtk_item_factory_create_items_ac (ifactory, n_entries, entries, callback_data, 1);
}
+/**
+ * gtk_item_factory_create_items_ac:
+ * @ifactory: a #GtkItemFactory
+ * @n_entries: the length of @entries
+ * @entries: an array of #GtkItemFactoryEntry<!>s
+ * @callback_data: data passed to the callback functions of all entries
+ * @callback_type: 1 if the callback functions in @entries are of type
+ * #GtkItemFactoryCallback1, 2 if they are of type #GtkItemFactoryCallback2
+ *
+ * Creates the menu items from the @entries.
+ */
void
-gtk_item_factory_create_items_ac (GtkItemFactory *ifactory,
- guint n_entries,
- GtkItemFactoryEntry *entries,
- gpointer callback_data,
- guint callback_type)
+gtk_item_factory_create_items_ac (GtkItemFactory *ifactory,
+ guint n_entries,
+ GtkItemFactoryEntry *entries,
+ gpointer callback_data,
+ guint callback_type)
{
guint i;
- g_return_if_fail (ifactory != NULL);
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
g_return_if_fail (callback_type >= 1 && callback_type <= 2);
gtk_item_factory_create_item (ifactory, entries + i, callback_data, callback_type);
}
+/**
+ * gtk_item_factory_get_widget:
+ * @ifactory: a #GtkItemFactory
+ * @path: the path to the widget
+ * @returns: the widget for the given path, or %NULL if @path doesn't lead
+ * to a widget
+ *
+ * Obtains the widget which corresponds to @path.
+ *
+ * If the widget corresponding to @path is a menu item which opens a
+ * submenu, then the submenu is returned. If you are interested in the menu
+ * item, use gtk_item_factory_get_item() instead.
+ */
GtkWidget*
-gtk_item_factory_get_widget (GtkItemFactory *ifactory,
- const gchar *path)
+gtk_item_factory_get_widget (GtkItemFactory *ifactory,
+ const gchar *path)
{
GtkItemFactoryClass *class;
GtkItemFactoryItem *item;
- g_return_val_if_fail (ifactory != NULL, NULL);
g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
g_return_val_if_fail (path != NULL, NULL);
- class = GTK_ITEM_FACTORY_CLASS (GTK_OBJECT (ifactory)->klass);
+ class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
if (path[0] == '<')
item = g_hash_table_lookup (class->item_ht, (gpointer) path);
return NULL;
}
+/**
+ * gtk_item_factory_get_widget_by_action:
+ * @ifactory: a #GtkItemFactory
+ * @action: an action as specified in the @callback_action field
+ * of #GtkItemFactoryEntry
+ * @returns: the widget which corresponds to the given action, or %NULL
+ * if no widget was found
+ *
+ * Obtains the widget which was constructed from the #GtkItemFactoryEntry
+ * with the given @action.
+ *
+ * If there are multiple items with the same action, the result is
+ * undefined.
+ */
GtkWidget*
-gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory,
- guint action)
+gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory,
+ guint action)
{
GSList *slist;
- g_return_val_if_fail (ifactory != NULL, NULL);
g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
- for (slist = ifactory->widgets_by_action; slist; slist = slist->next)
+ for (slist = ifactory->items; slist; slist = slist->next)
{
- GtkIFActionLink *link;
-
- link = slist->data;
+ GtkItemFactoryItem *item = slist->data;
+ GSList *link;
- if (link->callback_action == action)
- return link->widget;
+ for (link = item->widgets; link; link = link->next)
+ if (gtk_object_get_data_by_id (link->data, quark_item_factory) == ifactory &&
+ gtk_object_get_data_by_id (link->data, quark_action) == GUINT_TO_POINTER (action))
+ return link->data;
}
return NULL;
}
+/**
+ * gtk_item_factory_get_item:
+ * @ifactory: a #GtkItemFactory
+ * @path: the path to the menu item
+ * @returns: the menu item for the given path, or %NULL if @path doesn't
+ * lead to a menu item
+ *
+ * Obtains the menu item which corresponds to @path.
+ *
+ * If the widget corresponding to @path is a menu item which opens a
+ * submenu, then the item is returned. If you are interested in the submenu,
+ * use gtk_item_factory_get_widget() instead.
+ */
+GtkWidget*
+gtk_item_factory_get_item (GtkItemFactory *ifactory,
+ const gchar *path)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
+ g_return_val_if_fail (path != NULL, NULL);
+
+ widget = gtk_item_factory_get_widget (ifactory, path);
+
+ if (GTK_IS_MENU (widget))
+ widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
+
+ return GTK_IS_ITEM (widget) ? widget : NULL;
+}
+
+
+/**
+ * gtk_item_factory_get_item_by_action:
+ * @ifactory: a #GtkItemFactory
+ * @action: an action as specified in the @callback_action field
+ * of #GtkItemFactoryEntry
+ * @returns: the menu item which corresponds to the given action, or %NULL
+ * if no menu item was found
+ *
+ * Obtains the menu item which was constructed from the first
+ * #GtkItemFactoryEntry with the given @action.
+ */
+GtkWidget*
+gtk_item_factory_get_item_by_action (GtkItemFactory *ifactory,
+ guint action)
+{
+ GtkWidget *widget;
+
+ g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
+
+ widget = gtk_item_factory_get_widget_by_action (ifactory, action);
+
+ if (GTK_IS_MENU (widget))
+ widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
+
+ return GTK_IS_ITEM (widget) ? widget : NULL;
+}
+
+static char *
+item_factory_find_separator_r (char *path)
+{
+ gchar *result = NULL;
+ gboolean escaped = FALSE;
+
+ while (*path)
+ {
+ if (escaped)
+ escaped = FALSE;
+ else
+ {
+ if (*path == '\\')
+ escaped = TRUE;
+ else if (*path == '/')
+ result = path;
+ }
+
+ path++;
+ }
+
+ return result;
+}
+
+static char *
+item_factory_unescape_label (const char *label)
+{
+ char *new = g_malloc (strlen (label) + 1);
+ char *p = new;
+ gboolean escaped = FALSE;
+
+ while (*label)
+ {
+ if (escaped)
+ {
+ *p++ = *label;
+ escaped = FALSE;
+ }
+ else
+ {
+ if (*label == '\\')
+ escaped = TRUE;
+ else
+ *p++ = *label;
+ }
+
+ label++;
+ }
+
+ *p = '\0';
+
+ return new;
+}
+
static gboolean
gtk_item_factory_parse_path (GtkItemFactory *ifactory,
gchar *str,
{
gchar *translation;
gchar *p, *q;
-
+
*path = g_strdup (str);
p = q = *path;
while (*p)
{
- if (*p != '_')
+ if (*p == '_')
+ {
+ if (p[1] == '_')
+ {
+ p++;
+ *q++ = '_';
+ }
+ }
+ else
{
*q++ = *p;
}
*q = 0;
*parent_path = g_strdup (*path);
- p = strrchr (*parent_path, '/');
+ p = item_factory_find_separator_r (*parent_path);
if (!p)
{
g_warning ("GtkItemFactory: invalid entry path `%s'", str);
else
translation = str;
- p = strrchr (translation, '/');
- p++;
+ p = item_factory_find_separator_r (translation);
+ if (p)
+ p++;
+ else
+ p = translation;
- *item = g_strdup (p);
+ *item = item_factory_unescape_label (p);
return TRUE;
}
+/**
+ * gtk_item_factory_create_item:
+ * @ifactory: a #GtkItemFactory
+ * @entry: the #GtkItemFactoryEntry to create an item for
+ * @callback_data: data passed to the callback function of @entry
+ * @callback_type: 1 if the callback function of @entry is of type
+ * #GtkItemFactoryCallback1, 2 if it is of type #GtkItemFactoryCallback2
+ *
+ * Creates an item for @entry.
+ */
void
gtk_item_factory_create_item (GtkItemFactory *ifactory,
GtkItemFactoryEntry *entry,
gpointer callback_data,
guint callback_type)
{
+ GtkOptionMenu *option_menu = NULL;
GtkWidget *parent;
GtkWidget *widget;
+ GtkWidget *image;
GSList *radio_group;
gchar *name;
gchar *parent_path;
gchar *path;
- guint accel_key;
+ gchar *accelerator;
guint type_id;
GtkType type;
gchar *item_type_path;
- GtkAccelGroup *parent_accel_group = NULL;
- GSList *tmp_list;
-
- g_return_if_fail (ifactory != NULL);
+ GtkStockItem stock_item;
+
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
g_return_if_fail (entry != NULL);
g_return_if_fail (entry->path != NULL);
if (!entry->item_type ||
entry->item_type[0] == 0)
{
- item_type_path = (gpointer) key_type_item;
+ item_type_path = "<Item>";
type_id = quark_type_item;
}
else
type = GTK_TYPE_RADIO_MENU_ITEM;
else if (type_id == quark_type_check_item)
type = GTK_TYPE_CHECK_MENU_ITEM;
+ else if (type_id == quark_type_image_item)
+ type = GTK_TYPE_IMAGE_MENU_ITEM;
+ else if (type_id == quark_type_stock_item)
+ type = GTK_TYPE_IMAGE_MENU_ITEM;
else if (type_id == quark_type_tearoff_item)
type = GTK_TYPE_TEAROFF_MENU_ITEM;
else if (type_id == quark_type_toggle_item)
gchar *ppath, *p;
ppath = g_strdup (entry->path);
- p = strrchr (ppath, '/');
+ p = item_factory_find_separator_r (ppath);
g_return_if_fail (p != NULL);
*p = 0;
pentry.path = ppath;
parent = gtk_item_factory_get_widget (ifactory, parent_path);
g_return_if_fail (parent != NULL);
}
- g_free (parent_path);
- g_return_if_fail (parent != NULL);
+ if (GTK_IS_OPTION_MENU (parent))
+ {
+ option_menu = GTK_OPTION_MENU (parent);
+ if (!option_menu->menu)
+ {
+ GtkWidget *menu = g_object_new (GTK_TYPE_MENU, NULL);
+ gchar *p = g_strconcat (ifactory->path, parent_path, NULL);
+
+ gtk_menu_set_accel_path (GTK_MENU (menu), p);
+ g_free (p);
+ gtk_option_menu_set_menu (option_menu, menu);
+ }
+ parent = option_menu->menu;
+ }
+ g_free (parent_path);
+
+ g_return_if_fail (GTK_IS_CONTAINER (parent));
- tmp_list = gtk_accel_groups_from_object (GTK_OBJECT (parent));
- if (tmp_list)
- parent_accel_group = tmp_list->data;
+ accelerator = entry->accelerator;
widget = gtk_widget_new (type,
- "GtkWidget::visible", TRUE,
- "GtkWidget::sensitive", (type_id != quark_type_separator_item &&
- type_id != quark_type_title),
- "GtkWidget::parent", parent,
+ "visible", TRUE,
+ "sensitive", (type_id != quark_type_separator_item &&
+ type_id != quark_type_title),
+ "parent", parent,
NULL);
+ if (option_menu && !option_menu->menu_item)
+ gtk_option_menu_set_history (option_menu, 0);
if (type == GTK_TYPE_RADIO_MENU_ITEM)
gtk_radio_menu_item_set_group (GTK_RADIO_MENU_ITEM (widget), radio_group);
if (GTK_IS_CHECK_MENU_ITEM (widget))
gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (widget), TRUE);
-
- if ((type_id != quark_type_separator_item) &&
- (type_id != quark_type_tearoff_item) &&
- *name)
+ if (type_id == quark_type_image_item)
{
- GtkWidget *label;
-
- label =
- gtk_widget_new (GTK_TYPE_ACCEL_LABEL,
- "GtkWidget::visible", TRUE,
- "GtkWidget::parent", widget,
- "GtkAccelLabel::accel_widget", widget,
- "GtkMisc::xalign", 0.0,
- NULL);
-
- accel_key = gtk_label_parse_uline (GTK_LABEL (label), name);
-
- if ((accel_key != GDK_VoidSymbol) && GTK_IS_MENU_BAR (parent))
+ GdkPixbuf *pixbuf = NULL;
+
+ image = NULL;
+ pixbuf = gdk_pixbuf_new_from_inline (-1,
+ entry->extra_data,
+ FALSE,
+ NULL);
+ if (pixbuf)
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ if (image)
{
- gtk_widget_add_accelerator (widget,
- "activate_item",
- ifactory->accel_group,
- accel_key, GDK_MOD1_MASK,
- GTK_ACCEL_LOCKED);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
+ gtk_widget_show (image);
}
+ if (pixbuf)
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ if (type_id == quark_type_stock_item)
+ {
+ image = gtk_image_new_from_stock (entry->extra_data, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
+ gtk_widget_show (image);
- if ((accel_key != GDK_VoidSymbol) && parent_accel_group)
+ if (gtk_stock_lookup (entry->extra_data, &stock_item))
{
- gtk_widget_add_accelerator (widget,
- "activate_item",
- parent_accel_group,
- accel_key, 0,
- GTK_ACCEL_LOCKED);
+ if (!accelerator)
+ accelerator = gtk_accelerator_name (stock_item.keyval, stock_item.modifier);
}
}
+ /* install underline accelerators for this item
+ */
+ if (type_id != quark_type_separator_item &&
+ type_id != quark_type_tearoff_item &&
+ *name)
+ {
+ GtkWidget *label;
+
+ label = gtk_widget_new (GTK_TYPE_ACCEL_LABEL,
+ "visible", TRUE,
+ "parent", widget,
+ "accel_widget", widget,
+ "xalign", 0.0,
+ NULL);
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
+ }
+
g_free (name);
-
+
if (type_id == quark_type_branch ||
type_id == quark_type_last_branch)
{
- GtkAccelGroup *menu_group;
+ gchar *p;
if (entry->callback)
g_warning ("gtk_item_factory_create_item(): Can't specify a callback on a branch: \"%s\"",
entry->path);
-
- menu_group = gtk_accel_group_new ();
-
if (type_id == quark_type_last_branch)
- gtk_menu_item_right_justify (GTK_MENU_ITEM (widget));
-
+ gtk_menu_item_set_right_justified (GTK_MENU_ITEM (widget), TRUE);
+
parent = widget;
- widget =
- gtk_widget_new (GTK_TYPE_MENU,
- NULL);
+ widget = gtk_widget_new (GTK_TYPE_MENU, NULL);
+ p = g_strconcat (ifactory->path, path, NULL);
+ gtk_menu_set_accel_path (GTK_MENU (widget), p);
+ g_free (p);
- gtk_accel_group_attach (menu_group, GTK_OBJECT (widget));
gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget);
}
gtk_item_factory_add_item (ifactory,
- path, entry->accelerator,
+ path, accelerator,
(type_id == quark_type_branch ||
type_id == quark_type_last_branch) ?
(GtkItemFactoryCallback) NULL : entry->callback,
callback_type,
item_type_path,
widget);
-
+ if (accelerator != entry->accelerator)
+ g_free (accelerator);
g_free (path);
}
+/**
+ * gtk_item_factory_create_menu_entries:
+ * @n_entries: the length of @entries
+ * @entries: an array of #GtkMenuEntry<!>s
+ *
+ * Creates the menu items from the @entries.
+ */
void
gtk_item_factory_create_menu_entries (guint n_entries,
GtkMenuEntry *entries)
{
- static GtkPatternSpec pspec_separator = { 42, 0 };
- static GtkPatternSpec pspec_check = { 42, 0 };
+ static GPatternSpec *pspec_separator = NULL;
+ static GPatternSpec *pspec_check = NULL;
guint i;
if (!n_entries)
return;
g_return_if_fail (entries != NULL);
- if (pspec_separator.pattern_length == 0)
+ if (!pspec_separator)
{
- gtk_pattern_spec_init (&pspec_separator, "*<separator>*");
- gtk_pattern_spec_init (&pspec_check, "*<check>*");
+ pspec_separator = g_pattern_spec_new ("*<separator>*");
+ pspec_check = g_pattern_spec_new ("*<check>*");
}
for (i = 0; i < n_entries; i++)
entry.accelerator = entries[i].accelerator;
entry.callback = entries[i].callback;
entry.callback_action = 0;
- if (gtk_pattern_match_string (&pspec_separator, path))
- entry.item_type = (gpointer) key_type_separator_item;
- else if (!gtk_pattern_match_string (&pspec_check, path))
+ if (g_pattern_match_string (pspec_separator, path))
+ entry.item_type = "<Separator>";
+ else if (!g_pattern_match_string (pspec_check, path))
entry.item_type = NULL;
else
{
path++;
}
*c = 0;
- entry.item_type = (gpointer) key_type_toggle_item;
+ entry.item_type = "<ToggleItem>";
entry.path = cpath;
}
}
}
+/**
+ * gtk_item_factories_path_delete:
+ * @ifactory_path: a factory path to prepend to @path. May be %NULL if @path
+ * starts with a factory path
+ * @path: a path
+ *
+ * Deletes all widgets constructed from the specified path.
+ */
void
gtk_item_factories_path_delete (const gchar *ifactory_path,
const gchar *path)
}
}
+/**
+ * gtk_item_factory_delete_item:
+ * @ifactory: a #GtkItemFactory
+ * @path: a path
+ *
+ * Deletes the menu item which was created for @path by the given
+ * item factory.
+ */
void
gtk_item_factory_delete_item (GtkItemFactory *ifactory,
const gchar *path)
{
GtkItemFactoryClass *class;
- GtkItemFactoryItem *item;
- gchar *fpath;
+ GtkWidget *widget;
- g_return_if_fail (ifactory != NULL);
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
g_return_if_fail (path != NULL);
- class = GTK_ITEM_FACTORY_CLASS (GTK_OBJECT (ifactory)->klass);
+ class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
- fpath = g_strconcat (ifactory->path, path, NULL);
- item = g_hash_table_lookup (class->item_ht, fpath);
- g_free (fpath);
+ widget = gtk_item_factory_get_widget (ifactory, path);
- if (item)
+ if (widget)
{
- GtkWidget *widget = NULL;
- GSList *slist;
+ if (GTK_IS_MENU (widget))
+ widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
- for (slist = item->widgets; slist; slist = slist->next)
- {
- widget = slist->data;
-
- if (gtk_item_factory_from_widget (widget) == ifactory)
- break;
- }
-
- if (slist)
- gtk_widget_destroy (widget);
+ gtk_widget_destroy (widget);
}
}
+/**
+ * gtk_item_factory_delete_entry:
+ * @ifactory: a #GtkItemFactory
+ * @entry: a #GtkItemFactoryEntry
+ *
+ * Deletes the menu item which was created from @entry by the given
+ * item factory.
+ */
void
gtk_item_factory_delete_entry (GtkItemFactory *ifactory,
GtkItemFactoryEntry *entry)
{
- g_return_if_fail (ifactory != NULL);
+ gchar *path;
+ gchar *parent_path;
+ gchar *name;
+
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
g_return_if_fail (entry != NULL);
+ g_return_if_fail (entry->path != NULL);
+ g_return_if_fail (entry->path[0] == '/');
- gtk_item_factory_delete_item (ifactory, entry->path);
+ if (!gtk_item_factory_parse_path (ifactory, entry->path,
+ &path, &parent_path, &name))
+ return;
+
+ gtk_item_factory_delete_item (ifactory, path);
+
+ g_free (path);
+ g_free (parent_path);
+ g_free (name);
}
+/**
+ * gtk_item_factory_delete_entries:
+ * @ifactory: a #GtkItemFactory
+ * @n_entries: the length of @entries
+ * @entries: an array of #GtkItemFactoryEntry<!>s
+ *
+ * Deletes the menu items which were created from the @entries by the given
+ * item factory.
+ */
void
gtk_item_factory_delete_entries (GtkItemFactory *ifactory,
guint n_entries,
{
guint i;
- g_return_if_fail (ifactory != NULL);
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
if (n_entries > 0)
g_return_if_fail (entries != NULL);
for (i = 0; i < n_entries; i++)
- gtk_item_factory_delete_item (ifactory, (entries + i)->path);
+ gtk_item_factory_delete_entry (ifactory, entries + i);
}
typedef struct
gtk_item_factory_menu_pos (GtkMenu *menu,
gint *x,
gint *y,
+ gboolean *push_in,
gpointer func_data)
{
MenuPos *mpos = func_data;
*y = mpos->y;
}
+/**
+ * gtk_item_factory_popup_data_from_widget:
+ * @widget: a widget
+ * @returns: @popup_data associated with the item factory from
+ * which @widget was created, or %NULL if @widget wasn't created
+ * by an item factory
+ *
+ * Obtains the @popup_data which was passed to
+ * gtk_item_factory_popup_with_data(). This data is available until the menu
+ * is popped down again.
+ */
gpointer
-gtk_item_factory_popup_data_from_widget (GtkWidget *widget)
+gtk_item_factory_popup_data_from_widget (GtkWidget *widget)
{
GtkItemFactory *ifactory;
- g_return_val_if_fail (widget != NULL, NULL);
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
ifactory = gtk_item_factory_from_widget (widget);
return NULL;
}
+/**
+ * gtk_item_factory_popup_data:
+ * @ifactory: a #GtkItemFactory
+ * @returns: @popup_data associated with @ifactory
+ *
+ * Obtains the @popup_data which was passed to
+ * gtk_item_factory_popup_with_data(). This data is available until the menu
+ * is popped down again.
+ */
gpointer
gtk_item_factory_popup_data (GtkItemFactory *ifactory)
{
- g_return_val_if_fail (ifactory != NULL, NULL);
g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
return gtk_object_get_data_by_id (GTK_OBJECT (ifactory), quark_popup_data);
gtk_object_remove_data_by_id (GTK_OBJECT (ifactory), quark_popup_data);
}
+/**
+ * gtk_item_factory_popup:
+ * @ifactory: a #GtkItemFactory of type #GTK_TYPE_MENU (see gtk_item_factory_new())
+ * @x: the x position
+ * @y: the y position
+ * @mouse_button: the mouse button which was pressed to initiate this action
+ * @time: a timestamp for this action
+ *
+ * Pops up the menu constructed from the item factory at (@x, @y).
+ */
void
gtk_item_factory_popup (GtkItemFactory *ifactory,
guint x,
gtk_item_factory_popup_with_data (ifactory, NULL, NULL, x, y, mouse_button, time);
}
+/**
+ * gtk_item_factory_popup_with_data:
+ * @ifactory: a #GtkItemFactory of type #GTK_TYPE_MENU (see gtk_item_factory_new())
+ * @popup_data: data available for callbacks while the menu is posted
+ * @destroy: a #GtkDestroyNotify function to be called on @popup_data when
+ * the menu is unposted
+ * @x: the x position
+ * @y: the y position
+ * @mouse_button: the mouse button which was pressed to initiate this action
+ * @time: a timestamp for this action
+ *
+ * Pops up the menu constructed from the item factory at (@x, @y). Callbacks
+ * can access the @popup_data while the menu is posted via
+ * gtk_item_factory_popup_data() and gtk_item_factory_popup_data_from_widget().
+ */
void
gtk_item_factory_popup_with_data (GtkItemFactory *ifactory,
gpointer popup_data,
guint mouse_button,
guint32 time)
{
- g_return_if_fail (ifactory != NULL);
+ MenuPos *mpos;
+
g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
g_return_if_fail (GTK_IS_MENU (ifactory->widget));
-
- if (!GTK_WIDGET_VISIBLE (ifactory->widget))
- {
- MenuPos *mpos;
-
- mpos = gtk_object_get_data_by_id (GTK_OBJECT (ifactory->widget), quark_if_menu_pos);
-
- if (!mpos)
- {
- mpos = g_new0 (MenuPos, 1);
- gtk_object_set_data_by_id_full (GTK_OBJECT (ifactory->widget),
- quark_if_menu_pos,
- mpos,
- g_free);
- }
-
- mpos->x = x;
- mpos->y = y;
-
- if (popup_data != NULL)
- {
- gtk_object_set_data_by_id_full (GTK_OBJECT (ifactory),
- quark_popup_data,
- popup_data,
- destroy);
- gtk_signal_connect (GTK_OBJECT (ifactory->widget),
- "selection-done",
- GTK_SIGNAL_FUNC (ifactory_delete_popup_data),
- ifactory);
- }
-
- gtk_menu_popup (GTK_MENU (ifactory->widget),
- NULL, NULL,
- gtk_item_factory_menu_pos, mpos,
- mouse_button, time);
- }
-}
-
-static guint
-gtk_item_factory_parse_menu_path (GScanner *scanner,
- GtkItemFactoryClass *class)
-{
- GtkItemFactoryItem *item;
- g_scanner_get_next_token (scanner);
- if (scanner->token != G_TOKEN_STRING)
- return G_TOKEN_STRING;
-
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token != G_TOKEN_STRING)
- {
- g_scanner_get_next_token (scanner);
- return G_TOKEN_STRING;
- }
-
- item = g_hash_table_lookup (class->item_ht, scanner->value.v_string);
- if (!item)
- {
- item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
-
- item->path = g_strdup (scanner->value.v_string);
- item->accelerator_key = 0;
- item->accelerator_mods = 0;
- item->modified = TRUE;
- item->in_propagation = FALSE;
- item->item_type = NULL;
- item->widgets = NULL;
-
- g_hash_table_insert (class->item_ht, item->path, item);
- }
- g_scanner_get_next_token (scanner);
+ mpos = gtk_object_get_data_by_id (GTK_OBJECT (ifactory->widget), quark_if_menu_pos);
- if (!item->in_propagation)
+ if (!mpos)
{
- guint old_keyval;
- guint old_mods;
-
- old_keyval = item->accelerator_key;
- old_mods = item->accelerator_mods;
- gtk_accelerator_parse (scanner->value.v_string,
- &item->accelerator_key,
- &item->accelerator_mods);
- if (old_keyval != item->accelerator_key ||
- old_mods != item->accelerator_mods)
- {
- item->modified = TRUE;
- gtk_item_factory_propagate_accelerator (item, NULL);
- }
+ mpos = g_new0 (MenuPos, 1);
+ gtk_object_set_data_by_id_full (GTK_OBJECT (ifactory->widget),
+ quark_if_menu_pos,
+ mpos,
+ g_free);
}
- g_scanner_get_next_token (scanner);
- if (scanner->token != ')')
- return ')';
- else
- return G_TOKEN_NONE;
-}
-
-static void
-gtk_item_factory_parse_statement (GScanner *scanner,
- GtkItemFactoryClass *class)
-{
- guint expected_token;
+ mpos->x = x;
+ mpos->y = y;
- g_scanner_get_next_token (scanner);
-
- if (scanner->token == G_TOKEN_SYMBOL)
- {
- guint (*parser_func) (GScanner*, GtkItemFactoryClass*);
-
- parser_func = scanner->value.v_symbol;
-
- /* check whether this is a GtkItemFactory symbol.
- */
- if (parser_func == gtk_item_factory_parse_menu_path)
- expected_token = parser_func (scanner, class);
- else
- expected_token = G_TOKEN_SYMBOL;
- }
- else
- expected_token = G_TOKEN_SYMBOL;
-
- /* skip rest of statement on errrors
- */
- if (expected_token != G_TOKEN_NONE)
- {
- register guint level;
-
- level = 1;
- if (scanner->token == ')')
- level--;
- if (scanner->token == '(')
- level++;
-
- while (!g_scanner_eof (scanner) && level > 0)
- {
- g_scanner_get_next_token (scanner);
-
- if (scanner->token == '(')
- level++;
- else if (scanner->token == ')')
- level--;
- }
- }
-}
-
-void
-gtk_item_factory_parse_rc_string (const gchar *rc_string)
-{
- GScanner *scanner;
-
- g_return_if_fail (rc_string != NULL);
-
- ifactory_scanner_config.cpair_comment_single = gtk_item_factory_class->cpair_comment_single;
- scanner = g_scanner_new (&ifactory_scanner_config);
-
- g_scanner_input_text (scanner, rc_string, strlen (rc_string));
-
- gtk_item_factory_parse_rc_scanner (scanner);
-
- g_scanner_destroy (scanner);
-}
-
-void
-gtk_item_factory_parse_rc_scanner (GScanner *scanner)
-{
- gpointer saved_symbol;
-
- g_return_if_fail (scanner != NULL);
-
- if (!gtk_item_factory_class)
- gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
- saved_symbol = g_scanner_lookup_symbol (scanner, "menu-path");
- g_scanner_remove_symbol (scanner, "menu-path");
- g_scanner_add_symbol (scanner, "menu-path", gtk_item_factory_parse_menu_path);
-
- g_scanner_peek_next_token (scanner);
-
- while (scanner->next_token == '(')
+ if (popup_data != NULL)
{
- g_scanner_get_next_token (scanner);
-
- gtk_item_factory_parse_statement (scanner, gtk_item_factory_class);
-
- g_scanner_peek_next_token (scanner);
+ gtk_object_set_data_by_id_full (GTK_OBJECT (ifactory),
+ quark_popup_data,
+ popup_data,
+ destroy);
+ gtk_signal_connect (GTK_OBJECT (ifactory->widget),
+ "selection-done",
+ GTK_SIGNAL_FUNC (ifactory_delete_popup_data),
+ ifactory);
}
-
- g_scanner_remove_symbol (scanner, "menu-path");
- g_scanner_add_symbol (scanner, "menu-path", saved_symbol);
-}
-
-void
-gtk_item_factory_parse_rc (const gchar *file_name)
-{
- gint fd;
- GScanner *scanner;
-
- g_return_if_fail (file_name != NULL);
-
- if (!S_ISREG (g_scanner_stat_mode (file_name)))
- return;
-
- fd = open (file_name, O_RDONLY);
- if (fd < 0)
- return;
-
- ifactory_scanner_config.cpair_comment_single = gtk_item_factory_class->cpair_comment_single;
- scanner = g_scanner_new (&ifactory_scanner_config);
-
- g_scanner_input_file (scanner, fd);
-
- gtk_item_factory_parse_rc_scanner (scanner);
-
- g_scanner_destroy (scanner);
-
- close (fd);
+
+ gtk_menu_popup (GTK_MENU (ifactory->widget),
+ NULL, NULL,
+ gtk_item_factory_menu_pos, mpos,
+ mouse_button, time);
}
+/**
+ * gtk_item_factory_set_translate_func:
+ * @ifactory: a #GtkItemFactory
+ * @func: the #GtkTranslateFunc function to be used to translate path elements
+ * @data: data to pass to @func and @notify
+ * @notify: a #GtkDestroyNotify function to be called when @ifactory is
+ * destroyed and when the translation function is changed again
+ *
+ * Sets a function to be used for translating the path elements before they
+ * are displayed.
+ */
void
gtk_item_factory_set_translate_func (GtkItemFactory *ifactory,
GtkTranslateFunc func,
{
g_return_if_fail (ifactory != NULL);
- if (ifactory->translate_data && ifactory->translate_notify)
+ if (ifactory->translate_notify)
ifactory->translate_notify (ifactory->translate_data);
ifactory->translate_func = func;