1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * GtkItemFactory: Flexible item factory with automatic rc handling
5  * Copyright (C) 1998 Tim Janik
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
23 /*
24  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GTK+ Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28  */
29 
30 #include	<config.h>
31 
32 #undef GTK_DISABLE_DEPRECATED
33 #include	"gtkitemfactory.h"
34 #include	"gtkoptionmenu.h"
35 #include	"gtkmenubar.h"
36 #include	"gtkmenu.h"
37 #include	"gtkmenuitem.h"
38 #include	"gtkradiomenuitem.h"
39 #include	"gtkcheckmenuitem.h"
40 #include	"gtkimagemenuitem.h"
41 #include	"gtktearoffmenuitem.h"
42 #include	"gtkaccelmap.h"
43 #include	"gtkaccellabel.h"
44 #include        "gdk/gdkkeysyms.h"
45 #include	"gtkimage.h"
46 #include	"gtkstock.h"
47 #include	"gtkiconfactory.h"
48 #include	"gtkintl.h"
49 #include	<string.h>
50 #include	<fcntl.h>
51 #ifdef HAVE_UNISTD_H
52 #include	<unistd.h>
53 #endif
54 #include	<stdio.h>
55 
56 #include "gtkalias.h"
57 
58 /* --- defines --- */
59 #define		ITEM_FACTORY_STRING	((gchar*) item_factory_string)
60 #define		ITEM_BLOCK_SIZE		(128)
61 
62 
63 /* --- structures --- */
64 typedef struct	_GtkIFCBData		GtkIFCBData;
65 typedef struct  _GtkIFDumpData		GtkIFDumpData;
66 struct _GtkIFCBData
67 {
68   GtkItemFactoryCallback  func;
69   guint			  callback_type;
70   gpointer		  func_data;
71   guint			  callback_action;
72 };
73 
74 
75 /* --- prototypes --- */
76 static void	gtk_item_factory_destroy		(GtkObject	      *object);
77 static void	gtk_item_factory_finalize		(GObject	      *object);
78 
79 
80 /* --- static variables --- */
81 static const gchar	 item_factory_string[] = "Gtk-<ItemFactory>";
82 static GQuark		 quark_popup_data = 0;
83 static GQuark		 quark_if_menu_pos = 0;
84 static GQuark		 quark_item_factory = 0;
85 static GQuark		 quark_item_path = 0;
86 static GQuark		 quark_action = 0;
87 static GQuark		 quark_accel_group = 0;
88 static GQuark		 quark_type_item = 0;
89 static GQuark		 quark_type_title = 0;
90 static GQuark		 quark_type_radio_item = 0;
91 static GQuark		 quark_type_check_item = 0;
92 static GQuark		 quark_type_toggle_item = 0;
93 static GQuark		 quark_type_image_item = 0;
94 static GQuark		 quark_type_stock_item = 0;
95 static GQuark		 quark_type_tearoff_item = 0;
96 static GQuark		 quark_type_separator_item = 0;
97 static GQuark		 quark_type_branch = 0;
98 static GQuark		 quark_type_last_branch = 0;
99 
G_DEFINE_TYPE(GtkItemFactory,gtk_item_factory,GTK_TYPE_OBJECT)100 G_DEFINE_TYPE (GtkItemFactory, gtk_item_factory, GTK_TYPE_OBJECT)
101 
102 /* --- functions --- */
103 static void
104 gtk_item_factory_class_init (GtkItemFactoryClass  *class)
105 {
106   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
107   GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
108 
109   gobject_class->finalize = gtk_item_factory_finalize;
110 
111   object_class->destroy = gtk_item_factory_destroy;
112 
113   class->item_ht = g_hash_table_new (g_str_hash, g_str_equal);
114 
115   quark_popup_data		= g_quark_from_static_string ("GtkItemFactory-popup-data");
116   quark_if_menu_pos		= g_quark_from_static_string ("GtkItemFactory-menu-position");
117   quark_item_factory		= g_quark_from_static_string ("GtkItemFactory");
118   quark_item_path		= g_quark_from_static_string ("GtkItemFactory-path");
119   quark_action			= g_quark_from_static_string ("GtkItemFactory-action");
120   quark_accel_group		= g_quark_from_static_string ("GtkAccelGroup");
121   quark_type_item		= g_quark_from_static_string ("<Item>");
122   quark_type_title		= g_quark_from_static_string ("<Title>");
123   quark_type_radio_item		= g_quark_from_static_string ("<RadioItem>");
124   quark_type_check_item		= g_quark_from_static_string ("<CheckItem>");
125   quark_type_toggle_item	= g_quark_from_static_string ("<ToggleItem>");
126   quark_type_image_item         = g_quark_from_static_string ("<ImageItem>");
127   quark_type_stock_item         = g_quark_from_static_string ("<StockItem>");
128   quark_type_separator_item	= g_quark_from_static_string ("<Separator>");
129   quark_type_tearoff_item	= g_quark_from_static_string ("<Tearoff>");
130   quark_type_branch		= g_quark_from_static_string ("<Branch>");
131   quark_type_last_branch	= g_quark_from_static_string ("<LastBranch>");
132 }
133 
134 static void
gtk_item_factory_init(GtkItemFactory * ifactory)135 gtk_item_factory_init (GtkItemFactory	    *ifactory)
136 {
137   ifactory->path = NULL;
138   ifactory->accel_group = NULL;
139   ifactory->widget = NULL;
140   ifactory->items = NULL;
141   ifactory->translate_func = NULL;
142   ifactory->translate_data = NULL;
143   ifactory->translate_notify = NULL;
144 }
145 
146 /**
147  * gtk_item_factory_new:
148  * @container_type: the kind of menu to create; can be
149  *    #GTK_TYPE_MENU_BAR, #GTK_TYPE_MENU or #GTK_TYPE_OPTION_MENU
150  * @path: the factory path of the new item factory, a string of the form
151  *    <literal>"&lt;name&gt;"</literal>
152  * @accel_group: (allow-none): a #GtkAccelGroup to which the accelerators for the
153  *    menu items will be added, or %NULL to create a new one
154  * @returns: a new #GtkItemFactory
155  *
156  * Creates a new #GtkItemFactory.
157  *
158  * Beware that the returned object does not have a floating reference.
159  *
160  * Deprecated: 2.4: Use #GtkUIManager instead.
161  */
162 GtkItemFactory*
gtk_item_factory_new(GType container_type,const gchar * path,GtkAccelGroup * accel_group)163 gtk_item_factory_new (GType	     container_type,
164 		      const gchar   *path,
165 		      GtkAccelGroup *accel_group)
166 {
167   GtkItemFactory *ifactory;
168 
169   g_return_val_if_fail (path != NULL, NULL);
170 
171   ifactory = g_object_new (GTK_TYPE_ITEM_FACTORY, NULL);
172   gtk_item_factory_construct (ifactory, container_type, path, accel_group);
173 
174   return ifactory;
175 }
176 
177 static void
gtk_item_factory_callback_marshal(GtkWidget * widget,gpointer func_data)178 gtk_item_factory_callback_marshal (GtkWidget *widget,
179 				   gpointer   func_data)
180 {
181   GtkIFCBData *data;
182 
183   data = func_data;
184 
185   if (data->callback_type == 1)
186     {
187       GtkItemFactoryCallback1 func1 = (GtkItemFactoryCallback1) data->func;
188       func1 (data->func_data, data->callback_action, widget);
189     }
190   else if (data->callback_type == 2)
191     {
192       GtkItemFactoryCallback2 func2 = (GtkItemFactoryCallback2) data->func;
193       func2 (widget, data->func_data, data->callback_action);
194     }
195 }
196 
197 static void
gtk_item_factory_item_remove_widget(GtkWidget * widget,GtkItemFactoryItem * item)198 gtk_item_factory_item_remove_widget (GtkWidget		*widget,
199 				     GtkItemFactoryItem *item)
200 {
201   item->widgets = g_slist_remove (item->widgets, widget);
202   g_object_set_qdata (G_OBJECT (widget), quark_item_factory, NULL);
203   g_object_set_qdata (G_OBJECT (widget), quark_item_path, NULL);
204 }
205 
206 /**
207  * gtk_item_factory_add_foreign:
208  * @accel_widget:     widget to install an accelerator on
209  * @full_path:	      the full path for the @accel_widget
210  * @accel_group:      the accelerator group to install the accelerator in
211  * @keyval:           key value of the accelerator
212  * @modifiers:        modifier combination of the accelerator
213  *
214  * Installs an accelerator for @accel_widget in @accel_group, that causes
215  * the ::activate signal to be emitted if the accelerator is activated.
216  *
217  * This function can be used to make widgets participate in the accel
218  * saving/restoring functionality provided by gtk_accel_map_save() and
219  * gtk_accel_map_load(), even if they haven't been created by an item
220  * factory.
221  *
222  * Deprecated: 2.4: The recommended API for this purpose are the functions
223  * gtk_menu_item_set_accel_path() and gtk_widget_set_accel_path(); don't
224  * use gtk_item_factory_add_foreign() in new code, since it is likely to
225  * be removed in the future.
226  */
227 void
gtk_item_factory_add_foreign(GtkWidget * accel_widget,const gchar * full_path,GtkAccelGroup * accel_group,guint keyval,GdkModifierType modifiers)228 gtk_item_factory_add_foreign (GtkWidget      *accel_widget,
229 			      const gchar    *full_path,
230 			      GtkAccelGroup  *accel_group,
231 			      guint           keyval,
232 			      GdkModifierType modifiers)
233 {
234   GtkItemFactoryClass *class;
235   GtkItemFactoryItem *item;
236 
237   g_return_if_fail (GTK_IS_WIDGET (accel_widget));
238   g_return_if_fail (full_path != NULL);
239 
240   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
241 
242   keyval = keyval != GDK_VoidSymbol ? keyval : 0;
243 
244   item = g_hash_table_lookup (class->item_ht, full_path);
245   if (!item)
246     {
247       item = g_slice_new (GtkItemFactoryItem);
248 
249       item->path = g_strdup (full_path);
250       item->widgets = NULL;
251 
252       g_hash_table_insert (class->item_ht, item->path, item);
253     }
254 
255   item->widgets = g_slist_prepend (item->widgets, accel_widget);
256   g_signal_connect (accel_widget,
257 		    "destroy",
258 		    G_CALLBACK (gtk_item_factory_item_remove_widget),
259 		    item);
260 
261   /* set the item path for the widget
262    */
263   g_object_set_qdata (G_OBJECT (accel_widget), quark_item_path, item->path);
264   gtk_widget_set_name (accel_widget, item->path);
265   if (accel_group)
266     {
267       g_object_ref (accel_group);
268       g_object_set_qdata_full (G_OBJECT (accel_widget),
269 			       quark_accel_group,
270 			       accel_group,
271 			       g_object_unref);
272     }
273   else
274     g_object_set_qdata (G_OBJECT (accel_widget), quark_accel_group, NULL);
275 
276   /* install defined accelerators
277    */
278   if (g_signal_lookup ("activate", G_TYPE_FROM_INSTANCE (accel_widget)))
279     {
280       if (accel_group)
281 	{
282 	  gtk_accel_map_add_entry (full_path, keyval, modifiers);
283 	  gtk_widget_set_accel_path (accel_widget, full_path, accel_group);
284 	}
285     }
286 }
287 
288 static void
ifactory_cb_data_free(gpointer mem)289 ifactory_cb_data_free (gpointer mem)
290 {
291   g_slice_free (GtkIFCBData, mem);
292 }
293 
294 static void
gtk_item_factory_add_item(GtkItemFactory * ifactory,const gchar * path,const gchar * accelerator,GtkItemFactoryCallback callback,guint callback_action,gpointer callback_data,guint callback_type,gchar * item_type,GtkWidget * widget)295 gtk_item_factory_add_item (GtkItemFactory		*ifactory,
296 			   const gchar			*path,
297 			   const gchar			*accelerator,
298 			   GtkItemFactoryCallback	callback,
299 			   guint			callback_action,
300 			   gpointer			callback_data,
301 			   guint			callback_type,
302 			   gchar			*item_type,
303 			   GtkWidget			*widget)
304 {
305   GtkItemFactoryClass *class;
306   GtkItemFactoryItem *item;
307   gchar *fpath;
308   guint keyval;
309   GdkModifierType mods;
310 
311   g_return_if_fail (widget != NULL);
312   g_return_if_fail (item_type != NULL);
313 
314   class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
315 
316   /* set accelerator group on menu widgets
317    */
318   if (GTK_IS_MENU (widget))
319     gtk_menu_set_accel_group ((GtkMenu*) widget, ifactory->accel_group);
320 
321   /* connect callback if necessary
322    */
323   if (callback)
324     {
325       GtkIFCBData *data;
326 
327       data = g_slice_new (GtkIFCBData);
328       data->func = callback;
329       data->callback_type = callback_type;
330       data->func_data = callback_data;
331       data->callback_action = callback_action;
332 
333       g_object_weak_ref (G_OBJECT (widget),
334 			 (GWeakNotify) ifactory_cb_data_free,
335 			 data);
336       g_signal_connect (widget,
337 			"activate",
338 			G_CALLBACK (gtk_item_factory_callback_marshal),
339 			data);
340     }
341 
342   /* link the widget into its item-entry
343    * and keep back pointer on both the item factory and the widget
344    */
345   g_object_set_qdata (G_OBJECT (widget), quark_action, GUINT_TO_POINTER (callback_action));
346   g_object_set_qdata (G_OBJECT (widget), quark_item_factory, ifactory);
347   if (accelerator)
348     gtk_accelerator_parse (accelerator, &keyval, &mods);
349   else
350     {
351       keyval = 0;
352       mods = 0;
353     }
354   fpath = g_strconcat (ifactory->path, path, NULL);
355   gtk_item_factory_add_foreign (widget, fpath, ifactory->accel_group, keyval, mods);
356   item = g_hash_table_lookup (class->item_ht, fpath);
357   g_free (fpath);
358 
359   g_return_if_fail (item != NULL);
360 
361   if (!g_slist_find (ifactory->items, item))
362     ifactory->items = g_slist_prepend (ifactory->items, item);
363 }
364 
365 /**
366  * gtk_item_factory_construct:
367  * @ifactory: a #GtkItemFactory
368  * @container_type: the kind of menu to create; can be
369  *    #GTK_TYPE_MENU_BAR, #GTK_TYPE_MENU or #GTK_TYPE_OPTION_MENU
370  * @path: the factory path of @ifactory, a string of the form
371  *    <literal>"&lt;name&gt;"</literal>
372  * @accel_group: a #GtkAccelGroup to which the accelerators for the
373  *    menu items will be added, or %NULL to create a new one
374  *
375  * Initializes an item factory.
376  *
377  * Deprecated: 2.4: Use #GtkUIManager instead.
378  */
379 void
gtk_item_factory_construct(GtkItemFactory * ifactory,GType container_type,const gchar * path,GtkAccelGroup * accel_group)380 gtk_item_factory_construct (GtkItemFactory	*ifactory,
381 			    GType		 container_type,
382 			    const gchar		*path,
383 			    GtkAccelGroup	*accel_group)
384 {
385   guint len;
386 
387   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
388   g_return_if_fail (ifactory->accel_group == NULL);
389   g_return_if_fail (path != NULL);
390   if (!g_type_is_a (container_type, GTK_TYPE_OPTION_MENU))
391     g_return_if_fail (g_type_is_a (container_type, GTK_TYPE_MENU_SHELL));
392 
393   len = strlen (path);
394 
395   if (path[0] != '<' && path[len - 1] != '>')
396     {
397       g_warning ("GtkItemFactory: invalid factory path `%s'", path);
398       return;
399     }
400 
401   if (accel_group)
402     {
403       ifactory->accel_group = accel_group;
404       g_object_ref (ifactory->accel_group);
405     }
406   else
407     ifactory->accel_group = gtk_accel_group_new ();
408 
409   ifactory->path = g_strdup (path);
410   ifactory->widget = g_object_connect (g_object_new (container_type, NULL),
411 				       "signal::destroy", gtk_widget_destroyed, &ifactory->widget,
412 				       NULL);
413   g_object_ref_sink (ifactory);
414 
415   gtk_item_factory_add_item (ifactory,
416 			     "", NULL,
417 			     NULL, 0, NULL, 0,
418 			     ITEM_FACTORY_STRING,
419 			     ifactory->widget);
420 }
421 
422 /**
423  * gtk_item_factory_from_path:
424  * @path: a string starting with a factory path of the form
425  *   <literal>"&lt;name&gt;"</literal>
426  * @returns: (allow-none): the #GtkItemFactory created for the given factory path, or %NULL
427  *
428  * Finds an item factory which has been constructed using the
429  * <literal>"&lt;name&gt;"</literal> prefix of @path as the @path argument
430  * for gtk_item_factory_new().
431  *
432  * Deprecated: 2.4: Use #GtkUIManager instead.
433  */
434 GtkItemFactory*
gtk_item_factory_from_path(const gchar * path)435 gtk_item_factory_from_path (const gchar      *path)
436 {
437   GtkItemFactoryClass *class;
438   GtkItemFactoryItem *item;
439   gchar *fname;
440   guint i;
441 
442   g_return_val_if_fail (path != NULL, NULL);
443   g_return_val_if_fail (path[0] == '<', NULL);
444 
445   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
446 
447   i = 0;
448   while (path[i] && path[i] != '>')
449     i++;
450   if (path[i] != '>')
451     {
452       g_warning ("gtk_item_factory_from_path(): invalid factory path \"%s\"",
453 		 path);
454       return NULL;
455     }
456   fname = g_new (gchar, i + 2);
457   g_memmove (fname, path, i + 1);
458   fname[i + 1] = 0;
459 
460   item = g_hash_table_lookup (class->item_ht, fname);
461 
462   g_free (fname);
463 
464   if (item && item->widgets)
465     return gtk_item_factory_from_widget (item->widgets->data);
466 
467   return NULL;
468 }
469 
470 static void
gtk_item_factory_destroy(GtkObject * object)471 gtk_item_factory_destroy (GtkObject *object)
472 {
473   GtkItemFactory *ifactory = (GtkItemFactory*) object;
474   GSList *slist;
475 
476   if (ifactory->widget)
477     {
478       GtkObject *dobj;
479 
480       dobj = GTK_OBJECT (ifactory->widget);
481 
482       g_object_ref_sink (dobj);
483       gtk_object_destroy (dobj);
484       g_object_unref (dobj);
485 
486       ifactory->widget = NULL;
487     }
488 
489   for (slist = ifactory->items; slist; slist = slist->next)
490     {
491       GtkItemFactoryItem *item = slist->data;
492       GSList *link;
493 
494       for (link = item->widgets; link; link = link->next)
495 	if (g_object_get_qdata (link->data, quark_item_factory) == ifactory)
496 	  g_object_set_qdata (link->data, quark_item_factory, NULL);
497     }
498   g_slist_free (ifactory->items);
499   ifactory->items = NULL;
500 
501   GTK_OBJECT_CLASS (gtk_item_factory_parent_class)->destroy (object);
502 }
503 
504 static void
gtk_item_factory_finalize(GObject * object)505 gtk_item_factory_finalize (GObject *object)
506 {
507   GtkItemFactory *ifactory = GTK_ITEM_FACTORY (object);
508 
509   if (ifactory->accel_group)
510     g_object_unref (ifactory->accel_group);
511 
512   g_free (ifactory->path);
513   g_assert (ifactory->widget == NULL);
514 
515   if (ifactory->translate_notify)
516     ifactory->translate_notify (ifactory->translate_data);
517 
518   G_OBJECT_CLASS (gtk_item_factory_parent_class)->finalize (object);
519 }
520 
521 /**
522  * gtk_item_factory_from_widget:
523  * @widget: a widget
524  * @returns: (allow-none): the item factory from which @widget was created, or %NULL
525  *
526  * Obtains the item factory from which a widget was created.
527  *
528  * Deprecated: 2.4: Use #GtkUIManager instead.
529  */
530 GtkItemFactory*
gtk_item_factory_from_widget(GtkWidget * widget)531 gtk_item_factory_from_widget (GtkWidget	       *widget)
532 {
533   GtkItemFactory *ifactory;
534 
535   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
536 
537   ifactory = g_object_get_qdata (G_OBJECT (widget), quark_item_factory);
538 
539   if (ifactory == NULL && GTK_IS_MENU_ITEM (widget) &&
540       GTK_MENU_ITEM (widget)->submenu != NULL)
541     {
542       GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
543       ifactory = g_object_get_qdata (G_OBJECT (menu), quark_item_factory);
544     }
545 
546   return ifactory;
547 }
548 
549 /**
550  * gtk_item_factory_path_from_widget:
551  * @widget: a widget
552  * @returns: the full path to @widget if it has been created by an item
553  *   factory, %NULL otherwise. This value is owned by GTK+ and must not be
554  *   modified or freed.
555  *
556  * If @widget has been created by an item factory, returns the full path
557  * to it. (The full path of a widget is the concatenation of the factory
558  * path specified in gtk_item_factory_new() with the path specified in the
559  * #GtkItemFactoryEntry from which the widget was created.)
560  *
561  * Deprecated: 2.4: Use #GtkUIManager instead.
562  */
563 const gchar*
gtk_item_factory_path_from_widget(GtkWidget * widget)564 gtk_item_factory_path_from_widget (GtkWidget	    *widget)
565 {
566   gchar* path;
567 
568   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
569 
570   path = g_object_get_qdata (G_OBJECT (widget), quark_item_path);
571 
572   if (path == NULL && GTK_IS_MENU_ITEM (widget) &&
573       GTK_MENU_ITEM (widget)->submenu != NULL)
574     {
575       GtkWidget *menu = GTK_MENU_ITEM (widget)->submenu;
576       path = g_object_get_qdata (G_OBJECT (menu), quark_item_path);
577     }
578 
579   return path;
580 }
581 
582 /**
583  * gtk_item_factory_create_items:
584  * @ifactory: a #GtkItemFactory
585  * @n_entries: the length of @entries
586  * @entries: an array of #GtkItemFactoryEntry<!-- -->s whose @callback members
587  *    must by of type #GtkItemFactoryCallback1
588  * @callback_data: data passed to the callback functions of all entries
589  *
590  * Creates the menu items from the @entries.
591  *
592  * Deprecated: 2.4: Use #GtkUIManager instead.
593  */
594 void
gtk_item_factory_create_items(GtkItemFactory * ifactory,guint n_entries,GtkItemFactoryEntry * entries,gpointer callback_data)595 gtk_item_factory_create_items (GtkItemFactory	   *ifactory,
596 			       guint		    n_entries,
597 			       GtkItemFactoryEntry *entries,
598 			       gpointer		    callback_data)
599 {
600   gtk_item_factory_create_items_ac (ifactory, n_entries, entries, callback_data, 1);
601 }
602 
603 /**
604  * gtk_item_factory_create_items_ac:
605  * @ifactory: a #GtkItemFactory
606  * @n_entries: the length of @entries
607  * @entries: an array of #GtkItemFactoryEntry<!-- -->s
608  * @callback_data: data passed to the callback functions of all entries
609  * @callback_type: 1 if the callback functions in @entries are of type
610  *    #GtkItemFactoryCallback1, 2 if they are of type #GtkItemFactoryCallback2
611  *
612  * Creates the menu items from the @entries.
613  *
614  * Deprecated: 2.4: Use #GtkUIManager instead.
615  */
616 void
gtk_item_factory_create_items_ac(GtkItemFactory * ifactory,guint n_entries,GtkItemFactoryEntry * entries,gpointer callback_data,guint callback_type)617 gtk_item_factory_create_items_ac (GtkItemFactory      *ifactory,
618 				  guint		       n_entries,
619 				  GtkItemFactoryEntry *entries,
620 				  gpointer	       callback_data,
621 				  guint		       callback_type)
622 {
623   guint i;
624 
625   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
626   g_return_if_fail (callback_type >= 1 && callback_type <= 2);
627 
628   if (n_entries == 0)
629     return;
630 
631   g_return_if_fail (entries != NULL);
632 
633   for (i = 0; i < n_entries; i++)
634     gtk_item_factory_create_item (ifactory, entries + i, callback_data, callback_type);
635 }
636 
637 /**
638  * gtk_item_factory_get_widget:
639  * @ifactory: a #GtkItemFactory
640  * @path: the path to the widget
641  * @returns: (allow-none): the widget for the given path, or %NULL if @path doesn't lead
642  *   to a widget
643  *
644  * Obtains the widget which corresponds to @path.
645  *
646  * If the widget corresponding to @path is a menu item which opens a
647  * submenu, then the submenu is returned. If you are interested in the menu
648  * item, use gtk_item_factory_get_item() instead.
649  *
650  * Deprecated: 2.4: Use #GtkUIManager instead.
651  */
652 GtkWidget*
gtk_item_factory_get_widget(GtkItemFactory * ifactory,const gchar * path)653 gtk_item_factory_get_widget (GtkItemFactory *ifactory,
654 			     const gchar    *path)
655 {
656   GtkItemFactoryClass *class;
657   GtkItemFactoryItem *item;
658 
659   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
660   g_return_val_if_fail (path != NULL, NULL);
661 
662   class = GTK_ITEM_FACTORY_GET_CLASS (ifactory);
663 
664   if (path[0] == '<')
665     item = g_hash_table_lookup (class->item_ht, (gpointer) path);
666   else
667     {
668       gchar *fpath;
669 
670       fpath = g_strconcat (ifactory->path, path, NULL);
671       item = g_hash_table_lookup (class->item_ht, fpath);
672       g_free (fpath);
673     }
674 
675   if (item)
676     {
677       GSList *slist;
678 
679       for (slist = item->widgets; slist; slist = slist->next)
680 	{
681 	  if (gtk_item_factory_from_widget (slist->data) == ifactory)
682 	    return slist->data;
683 	}
684     }
685 
686   return NULL;
687 }
688 
689 /**
690  * gtk_item_factory_get_widget_by_action:
691  * @ifactory: a #GtkItemFactory
692  * @action: an action as specified in the @callback_action field
693  *   of #GtkItemFactoryEntry
694  * @returns: (allow-none): the widget which corresponds to the given action, or %NULL
695  *   if no widget was found
696  *
697  * Obtains the widget which was constructed from the #GtkItemFactoryEntry
698  * with the given @action.
699  *
700  * If there are multiple items with the same action, the result is
701  * undefined.
702  *
703  * Deprecated: 2.4: Use #GtkUIManager instead.
704  */
705 GtkWidget*
gtk_item_factory_get_widget_by_action(GtkItemFactory * ifactory,guint action)706 gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory,
707 				       guint	       action)
708 {
709   GSList *slist;
710 
711   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
712 
713   for (slist = ifactory->items; slist; slist = slist->next)
714     {
715       GtkItemFactoryItem *item = slist->data;
716       GSList *link;
717 
718       for (link = item->widgets; link; link = link->next)
719 	if (g_object_get_qdata (link->data, quark_item_factory) == ifactory &&
720 	    g_object_get_qdata (link->data, quark_action) == GUINT_TO_POINTER (action))
721 	  return link->data;
722     }
723 
724   return NULL;
725 }
726 
727 /**
728  * gtk_item_factory_get_item:
729  * @ifactory: a #GtkItemFactory
730  * @path: the path to the menu item
731  * @returns: (allow-none): the menu item for the given path, or %NULL if @path doesn't
732  *   lead to a menu item
733  *
734  * Obtains the menu item which corresponds to @path.
735  *
736  * If the widget corresponding to @path is a menu item which opens a
737  * submenu, then the item is returned. If you are interested in the submenu,
738  * use gtk_item_factory_get_widget() instead.
739  *
740  * Deprecated: 2.4: Use #GtkUIManager instead.
741  */
742 GtkWidget*
gtk_item_factory_get_item(GtkItemFactory * ifactory,const gchar * path)743 gtk_item_factory_get_item (GtkItemFactory *ifactory,
744 			   const gchar    *path)
745 {
746   GtkWidget *widget;
747 
748   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
749   g_return_val_if_fail (path != NULL, NULL);
750 
751   widget = gtk_item_factory_get_widget (ifactory, path);
752 
753   if (GTK_IS_MENU (widget))
754     widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
755 
756   return GTK_IS_ITEM (widget) ? widget : NULL;
757 }
758 
759 
760 /**
761  * gtk_item_factory_get_item_by_action:
762  * @ifactory: a #GtkItemFactory
763  * @action: an action as specified in the @callback_action field
764  *   of #GtkItemFactoryEntry
765  * @returns: (allow-none): the menu item which corresponds to the given action, or %NULL
766  *   if no menu item was found
767  *
768  * Obtains the menu item which was constructed from the first
769  * #GtkItemFactoryEntry with the given @action.
770  *
771  * Deprecated: 2.4: Use #GtkUIManager instead.
772  */
773 GtkWidget*
gtk_item_factory_get_item_by_action(GtkItemFactory * ifactory,guint action)774 gtk_item_factory_get_item_by_action (GtkItemFactory *ifactory,
775 				     guint	     action)
776 {
777   GtkWidget *widget;
778 
779   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
780 
781   widget = gtk_item_factory_get_widget_by_action (ifactory, action);
782 
783   if (GTK_IS_MENU (widget))
784     widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
785 
786   return GTK_IS_ITEM (widget) ? widget : NULL;
787 }
788 
789 static char *
item_factory_find_separator_r(char * path)790 item_factory_find_separator_r (char *path)
791 {
792   gchar *result = NULL;
793   gboolean escaped = FALSE;
794 
795   while (*path)
796     {
797       if (escaped)
798 	escaped = FALSE;
799       else
800 	{
801 	  if (*path == '\\')
802 	    escaped = TRUE;
803 	  else if (*path == '/')
804 	    result = path;
805 	}
806 
807       path++;
808     }
809 
810   return result;
811 }
812 
813 static char *
item_factory_unescape_label(const char * label)814 item_factory_unescape_label (const char *label)
815 {
816   char *new = g_malloc (strlen (label) + 1);
817   char *p = new;
818   gboolean escaped = FALSE;
819 
820   while (*label)
821     {
822       if (escaped)
823 	{
824 	  *p++ = *label;
825 	  escaped = FALSE;
826 	}
827       else
828 	{
829 	  if (*label == '\\')
830 	    escaped = TRUE;
831 	  else
832 	    *p++ = *label;
833 	}
834 
835       label++;
836     }
837 
838   *p = '\0';
839 
840   return new;
841 }
842 
843 static gboolean
gtk_item_factory_parse_path(GtkItemFactory * ifactory,gchar * str,gchar ** path,gchar ** parent_path,gchar ** item)844 gtk_item_factory_parse_path (GtkItemFactory *ifactory,
845 			     gchar          *str,
846 			     gchar         **path,
847 			     gchar         **parent_path,
848 			     gchar         **item)
849 {
850   gchar *translation;
851   gchar *p, *q;
852 
853   *path = g_strdup (str);
854 
855   p = q = *path;
856   while (*p)
857     {
858       if (*p == '_')
859 	{
860 	  if (p[1] == '_')
861 	    {
862 	      p++;
863 	      *q++ = '_';
864 	    }
865 	}
866       else
867 	{
868 	  *q++ = *p;
869 	}
870       p++;
871     }
872   *q = 0;
873 
874   *parent_path = g_strdup (*path);
875   p = item_factory_find_separator_r (*parent_path);
876   if (!p)
877     {
878       g_warning ("GtkItemFactory: invalid entry path `%s'", str);
879       return FALSE;
880     }
881   *p = 0;
882 
883   if (ifactory->translate_func)
884     translation = ifactory->translate_func (str, ifactory->translate_data);
885   else
886     translation = str;
887 
888   p = item_factory_find_separator_r (translation);
889   if (p)
890     p++;
891   else
892     p = translation;
893 
894   *item = item_factory_unescape_label (p);
895 
896   return TRUE;
897 }
898 
899 /**
900  * gtk_item_factory_create_item:
901  * @ifactory: a #GtkItemFactory
902  * @entry: the #GtkItemFactoryEntry to create an item for
903  * @callback_data: data passed to the callback function of @entry
904  * @callback_type: 1 if the callback function of @entry is of type
905  *    #GtkItemFactoryCallback1, 2 if it is of type #GtkItemFactoryCallback2
906  *
907  * Creates an item for @entry.
908  *
909  * Deprecated: 2.4: Use #GtkUIManager instead.
910  */
911 void
gtk_item_factory_create_item(GtkItemFactory * ifactory,GtkItemFactoryEntry * entry,gpointer callback_data,guint callback_type)912 gtk_item_factory_create_item (GtkItemFactory	     *ifactory,
913 			      GtkItemFactoryEntry    *entry,
914 			      gpointer		      callback_data,
915 			      guint		      callback_type)
916 {
917   GtkOptionMenu *option_menu = NULL;
918   GtkWidget *parent;
919   GtkWidget *widget;
920   GtkWidget *image;
921   GSList *radio_group;
922   gchar *name;
923   gchar *parent_path;
924   gchar *path;
925   gchar *accelerator;
926   guint type_id;
927   GType type;
928   gchar *item_type_path;
929   GtkStockItem stock_item;
930 
931   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
932   g_return_if_fail (entry != NULL);
933   g_return_if_fail (entry->path != NULL);
934   g_return_if_fail (entry->path[0] == '/');
935   g_return_if_fail (callback_type >= 1 && callback_type <= 2);
936 
937   if (!entry->item_type ||
938       entry->item_type[0] == 0)
939     {
940       item_type_path = "<Item>";
941       type_id = quark_type_item;
942     }
943   else
944     {
945       item_type_path = entry->item_type;
946       type_id = g_quark_try_string (item_type_path);
947     }
948 
949   radio_group = NULL;
950   if (type_id == quark_type_item)
951     type = GTK_TYPE_MENU_ITEM;
952   else if (type_id == quark_type_title)
953     type = GTK_TYPE_MENU_ITEM;
954   else if (type_id == quark_type_radio_item)
955     type = GTK_TYPE_RADIO_MENU_ITEM;
956   else if (type_id == quark_type_check_item)
957     type = GTK_TYPE_CHECK_MENU_ITEM;
958   else if (type_id == quark_type_image_item)
959     type = GTK_TYPE_IMAGE_MENU_ITEM;
960   else if (type_id == quark_type_stock_item)
961     type = GTK_TYPE_IMAGE_MENU_ITEM;
962   else if (type_id == quark_type_tearoff_item)
963     type = GTK_TYPE_TEAROFF_MENU_ITEM;
964   else if (type_id == quark_type_toggle_item)
965     type = GTK_TYPE_CHECK_MENU_ITEM;
966   else if (type_id == quark_type_separator_item)
967     type = GTK_TYPE_SEPARATOR_MENU_ITEM;
968   else if (type_id == quark_type_branch)
969     type = GTK_TYPE_MENU_ITEM;
970   else if (type_id == quark_type_last_branch)
971     type = GTK_TYPE_MENU_ITEM;
972   else
973     {
974       GtkWidget *radio_link;
975 
976       radio_link = gtk_item_factory_get_widget (ifactory, item_type_path);
977       if (radio_link && GTK_IS_RADIO_MENU_ITEM (radio_link))
978 	{
979 	  type = GTK_TYPE_RADIO_MENU_ITEM;
980 	  radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (radio_link));
981 	}
982       else
983 	{
984 	  g_warning ("GtkItemFactory: entry path `%s' has invalid type `%s'",
985 		     entry->path,
986 		     item_type_path);
987 	  return;
988 	}
989     }
990 
991   if (!gtk_item_factory_parse_path (ifactory, entry->path,
992 				    &path, &parent_path, &name))
993     return;
994 
995   parent = gtk_item_factory_get_widget (ifactory, parent_path);
996   if (!parent)
997     {
998       GtkItemFactoryEntry pentry;
999       gchar *ppath, *p;
1000 
1001       ppath = g_strdup (entry->path);
1002       p = item_factory_find_separator_r (ppath);
1003       g_return_if_fail (p != NULL);
1004       *p = 0;
1005       pentry.path = ppath;
1006       pentry.accelerator = NULL;
1007       pentry.callback = NULL;
1008       pentry.callback_action = 0;
1009       pentry.item_type = "<Branch>";
1010 
1011       gtk_item_factory_create_item (ifactory, &pentry, NULL, 1);
1012       g_free (ppath);
1013 
1014       parent = gtk_item_factory_get_widget (ifactory, parent_path);
1015       g_return_if_fail (parent != NULL);
1016     }
1017 
1018   if (GTK_IS_OPTION_MENU (parent))
1019     {
1020       option_menu = GTK_OPTION_MENU (parent);
1021       if (!option_menu->menu)
1022 	{
1023 	  GtkWidget *menu = g_object_new (GTK_TYPE_MENU, NULL);
1024 	  gchar *p = g_strconcat (ifactory->path, parent_path, NULL);
1025 
1026 	  gtk_menu_set_accel_path (GTK_MENU (menu), p);
1027 	  g_free (p);
1028 	  gtk_option_menu_set_menu (option_menu, menu);
1029 	}
1030       parent = option_menu->menu;
1031     }
1032   g_free (parent_path);
1033 
1034   g_return_if_fail (GTK_IS_CONTAINER (parent));
1035 
1036   accelerator = entry->accelerator;
1037 
1038   widget = g_object_new (type,
1039 			   "visible", TRUE,
1040 			   "sensitive", (type_id != quark_type_separator_item &&
1041 					 type_id != quark_type_title),
1042 			   "parent", parent,
1043 			   NULL);
1044   if (option_menu && !option_menu->menu_item)
1045     gtk_option_menu_set_history (option_menu, 0);
1046 
1047   if (GTK_IS_RADIO_MENU_ITEM (widget))
1048     gtk_radio_menu_item_set_group (GTK_RADIO_MENU_ITEM (widget), radio_group);
1049   if (type_id == quark_type_image_item)
1050     {
1051       GdkPixbuf *pixbuf = NULL;
1052       image = NULL;
1053       if (entry->extra_data)
1054 	{
1055 	  pixbuf = gdk_pixbuf_new_from_inline (-1,
1056 					       entry->extra_data,
1057 					       FALSE,
1058 					       NULL);
1059 	  if (pixbuf)
1060 	    image = gtk_image_new_from_pixbuf (pixbuf);
1061 	}
1062       if (image)
1063 	{
1064 	  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
1065 	  gtk_widget_show (image);
1066 	}
1067       if (pixbuf)
1068 	g_object_unref (pixbuf);
1069     }
1070   if (type_id == quark_type_stock_item)
1071     {
1072       image = gtk_image_new_from_stock (entry->extra_data, GTK_ICON_SIZE_MENU);
1073       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
1074       gtk_widget_show (image);
1075 
1076       if (gtk_stock_lookup (entry->extra_data, &stock_item))
1077 	{
1078 	  if (!accelerator)
1079 	    accelerator = gtk_accelerator_name (stock_item.keyval, stock_item.modifier);
1080 	}
1081     }
1082 
1083   /* install underline accelerators for this item
1084    */
1085   if (type_id != quark_type_separator_item &&
1086       type_id != quark_type_tearoff_item &&
1087       *name)
1088     {
1089       GtkWidget *label;
1090 
1091       label = g_object_new (GTK_TYPE_ACCEL_LABEL,
1092 			      "visible", TRUE,
1093 			      "parent", widget,
1094 			      "accel-widget", widget,
1095 			      "xalign", 0.0,
1096 			      NULL);
1097       gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
1098     }
1099 
1100   g_free (name);
1101 
1102   if (type_id == quark_type_branch ||
1103       type_id == quark_type_last_branch)
1104     {
1105       gchar *p;
1106 
1107       if (entry->callback)
1108 	g_warning ("gtk_item_factory_create_item(): Can't specify a callback on a branch: \"%s\"",
1109 		   entry->path);
1110       if (type_id == quark_type_last_branch)
1111 	gtk_menu_item_set_right_justified (GTK_MENU_ITEM (widget), TRUE);
1112 
1113       parent = widget;
1114       widget = g_object_new (GTK_TYPE_MENU, NULL);
1115       p = g_strconcat (ifactory->path, path, NULL);
1116       gtk_menu_set_accel_path (GTK_MENU (widget), p);
1117       g_free (p);
1118 
1119       gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget);
1120     }
1121 
1122   gtk_item_factory_add_item (ifactory,
1123 			     path, accelerator,
1124 			     (type_id == quark_type_branch ||
1125 			      type_id == quark_type_last_branch) ?
1126 			      (GtkItemFactoryCallback) NULL : entry->callback,
1127 			     entry->callback_action, callback_data,
1128 			     callback_type,
1129 			     item_type_path,
1130 			     widget);
1131   if (accelerator != entry->accelerator)
1132     g_free (accelerator);
1133   g_free (path);
1134 }
1135 
1136 /**
1137  * gtk_item_factory_create_menu_entries:
1138  * @n_entries: the length of @entries
1139  * @entries: an array of #GtkMenuEntry<!-- -->s
1140  *
1141  * Creates the menu items from the @entries.
1142  *
1143  * Deprecated: 2.4: Use #GtkUIManager instead.
1144  */
1145 void
gtk_item_factory_create_menu_entries(guint n_entries,GtkMenuEntry * entries)1146 gtk_item_factory_create_menu_entries (guint              n_entries,
1147 				      GtkMenuEntry      *entries)
1148 {
1149   static GPatternSpec *pspec_separator = NULL;
1150   static GPatternSpec *pspec_check = NULL;
1151   guint i;
1152 
1153   if (!n_entries)
1154     return;
1155   g_return_if_fail (entries != NULL);
1156 
1157   if (!pspec_separator)
1158     {
1159       pspec_separator = g_pattern_spec_new ("*<separator>*");
1160       pspec_check = g_pattern_spec_new ("*<check>*");
1161     }
1162 
1163   for (i = 0; i < n_entries; i++)
1164     {
1165       GtkItemFactory *ifactory;
1166       GtkItemFactoryEntry entry;
1167       gchar *path;
1168       gchar *cpath;
1169 
1170       path = entries[i].path;
1171       ifactory = gtk_item_factory_from_path (path);
1172       if (!ifactory)
1173 	{
1174 	  g_warning ("gtk_item_factory_create_menu_entries(): "
1175 		     "entry[%u] refers to unknown item factory: \"%s\"",
1176 		     i, entries[i].path);
1177 	  continue;
1178 	}
1179 
1180       while (*path != '>')
1181 	path++;
1182       path++;
1183       cpath = NULL;
1184 
1185       entry.path = path;
1186       entry.accelerator = entries[i].accelerator;
1187       entry.callback = entries[i].callback;
1188       entry.callback_action = 0;
1189       if (g_pattern_match_string (pspec_separator, path))
1190 	entry.item_type = "<Separator>";
1191       else if (!g_pattern_match_string (pspec_check, path))
1192 	entry.item_type = NULL;
1193       else
1194 	{
1195 	  gboolean in_brace = FALSE;
1196 	  gchar *c;
1197 
1198 	  cpath = g_new (gchar, strlen (path));
1199 	  c = cpath;
1200 	  while (*path != 0)
1201 	    {
1202 	      if (*path == '<')
1203 		in_brace = TRUE;
1204 	      else if (*path == '>')
1205 		in_brace = FALSE;
1206 	      else if (!in_brace)
1207 		*(c++) = *path;
1208 	      path++;
1209 	    }
1210 	  *c = 0;
1211 	  entry.item_type = "<ToggleItem>";
1212 	  entry.path = cpath;
1213 	}
1214 
1215       gtk_item_factory_create_item (ifactory, &entry, entries[i].callback_data, 2);
1216       entries[i].widget = gtk_item_factory_get_widget (ifactory, entries[i].path);
1217       g_free (cpath);
1218     }
1219 }
1220 
1221 /**
1222  * gtk_item_factories_path_delete:
1223  * @ifactory_path: a factory path to prepend to @path. May be %NULL if @path
1224  *   starts with a factory path
1225  * @path: a path
1226  *
1227  * Deletes all widgets constructed from the specified path.
1228  *
1229  * Deprecated: 2.4: Use #GtkUIManager instead.
1230  */
1231 void
gtk_item_factories_path_delete(const gchar * ifactory_path,const gchar * path)1232 gtk_item_factories_path_delete (const gchar *ifactory_path,
1233 				const gchar *path)
1234 {
1235   GtkItemFactoryClass *class;
1236   GtkItemFactoryItem *item;
1237 
1238   g_return_if_fail (path != NULL);
1239 
1240   class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
1241 
1242   if (path[0] == '<')
1243     item = g_hash_table_lookup (class->item_ht, (gpointer) path);
1244   else
1245     {
1246       gchar *fpath;
1247 
1248       g_return_if_fail (ifactory_path != NULL);
1249 
1250       fpath = g_strconcat (ifactory_path, path, NULL);
1251       item = g_hash_table_lookup (class->item_ht, fpath);
1252       g_free (fpath);
1253     }
1254 
1255   if (item)
1256     {
1257       GSList *widget_list;
1258       GSList *slist;
1259 
1260       widget_list = NULL;
1261       for (slist = item->widgets; slist; slist = slist->next)
1262 	{
1263 	  GtkWidget *widget;
1264 
1265 	  widget = slist->data;
1266 	  widget_list = g_slist_prepend (widget_list, widget);
1267 	  g_object_ref (widget);
1268 	}
1269 
1270       for (slist = widget_list; slist; slist = slist->next)
1271 	{
1272 	  GtkWidget *widget;
1273 
1274 	  widget = slist->data;
1275 	  gtk_widget_destroy (widget);
1276 	  g_object_unref (widget);
1277 	}
1278       g_slist_free (widget_list);
1279     }
1280 }
1281 
1282 /**
1283  * gtk_item_factory_delete_item:
1284  * @ifactory: a #GtkItemFactory
1285  * @path: a path
1286  *
1287  * Deletes the menu item which was created for @path by the given
1288  * item factory.
1289  *
1290  * Deprecated: 2.4: Use #GtkUIManager instead.
1291  */
1292 void
gtk_item_factory_delete_item(GtkItemFactory * ifactory,const gchar * path)1293 gtk_item_factory_delete_item (GtkItemFactory         *ifactory,
1294 			      const gchar            *path)
1295 {
1296   GtkWidget *widget;
1297 
1298   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1299   g_return_if_fail (path != NULL);
1300 
1301   widget = gtk_item_factory_get_widget (ifactory, path);
1302 
1303   if (widget)
1304     {
1305       if (GTK_IS_MENU (widget))
1306 	widget = gtk_menu_get_attach_widget (GTK_MENU (widget));
1307 
1308       gtk_widget_destroy (widget);
1309     }
1310 }
1311 
1312 /**
1313  * gtk_item_factory_delete_entry:
1314  * @ifactory: a #GtkItemFactory
1315  * @entry: a #GtkItemFactoryEntry
1316  *
1317  * Deletes the menu item which was created from @entry by the given
1318  * item factory.
1319  *
1320  * Deprecated: 2.4: Use #GtkUIManager instead.
1321  */
1322 void
gtk_item_factory_delete_entry(GtkItemFactory * ifactory,GtkItemFactoryEntry * entry)1323 gtk_item_factory_delete_entry (GtkItemFactory         *ifactory,
1324 			       GtkItemFactoryEntry    *entry)
1325 {
1326   gchar *path;
1327   gchar *parent_path;
1328   gchar *name;
1329 
1330   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1331   g_return_if_fail (entry != NULL);
1332   g_return_if_fail (entry->path != NULL);
1333   g_return_if_fail (entry->path[0] == '/');
1334 
1335   if (!gtk_item_factory_parse_path (ifactory, entry->path,
1336 				    &path, &parent_path, &name))
1337     return;
1338 
1339   gtk_item_factory_delete_item (ifactory, path);
1340 
1341   g_free (path);
1342   g_free (parent_path);
1343   g_free (name);
1344 }
1345 
1346 /**
1347  * gtk_item_factory_delete_entries:
1348  * @ifactory: a #GtkItemFactory
1349  * @n_entries: the length of @entries
1350  * @entries: an array of #GtkItemFactoryEntry<!-- -->s
1351  *
1352  * Deletes the menu items which were created from the @entries by the given
1353  * item factory.
1354  *
1355  * Deprecated: 2.4: Use #GtkUIManager instead.
1356  */
1357 void
gtk_item_factory_delete_entries(GtkItemFactory * ifactory,guint n_entries,GtkItemFactoryEntry * entries)1358 gtk_item_factory_delete_entries (GtkItemFactory         *ifactory,
1359 				 guint                   n_entries,
1360 				 GtkItemFactoryEntry    *entries)
1361 {
1362   guint i;
1363 
1364   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1365   if (n_entries > 0)
1366     g_return_if_fail (entries != NULL);
1367 
1368   for (i = 0; i < n_entries; i++)
1369     gtk_item_factory_delete_entry (ifactory, entries + i);
1370 }
1371 
1372 typedef struct
1373 {
1374   guint x;
1375   guint y;
1376 } MenuPos;
1377 
1378 static void
gtk_item_factory_menu_pos(GtkMenu * menu,gint * x,gint * y,gboolean * push_in,gpointer func_data)1379 gtk_item_factory_menu_pos (GtkMenu  *menu,
1380 			   gint     *x,
1381 			   gint     *y,
1382                            gboolean *push_in,
1383 			   gpointer  func_data)
1384 {
1385   MenuPos *mpos = func_data;
1386 
1387   *x = mpos->x;
1388   *y = mpos->y;
1389 }
1390 
1391 /**
1392  * gtk_item_factory_popup_data_from_widget:
1393  * @widget: a widget
1394  * @returns: @popup_data associated with the item factory from
1395  *   which @widget was created, or %NULL if @widget wasn't created
1396  *   by an item factory
1397  *
1398  * Obtains the @popup_data which was passed to
1399  * gtk_item_factory_popup_with_data(). This data is available until the menu
1400  * is popped down again.
1401  *
1402  * Deprecated: 2.4: Use #GtkUIManager instead.
1403  */
1404 gpointer
gtk_item_factory_popup_data_from_widget(GtkWidget * widget)1405 gtk_item_factory_popup_data_from_widget (GtkWidget *widget)
1406 {
1407   GtkItemFactory *ifactory;
1408 
1409   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
1410 
1411   ifactory = gtk_item_factory_from_widget (widget);
1412   if (ifactory)
1413     return g_object_get_qdata (G_OBJECT (ifactory), quark_popup_data);
1414 
1415   return NULL;
1416 }
1417 
1418 /**
1419  * gtk_item_factory_popup_data:
1420  * @ifactory: a #GtkItemFactory
1421  * @returns: @popup_data associated with @ifactory
1422  *
1423  * Obtains the @popup_data which was passed to
1424  * gtk_item_factory_popup_with_data(). This data is available until the menu
1425  * is popped down again.
1426  *
1427  * Deprecated: 2.4: Use #GtkUIManager instead.
1428  */
1429 gpointer
gtk_item_factory_popup_data(GtkItemFactory * ifactory)1430 gtk_item_factory_popup_data (GtkItemFactory *ifactory)
1431 {
1432   g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL);
1433 
1434   return g_object_get_qdata (G_OBJECT (ifactory), quark_popup_data);
1435 }
1436 
1437 static void
ifactory_delete_popup_data(GtkObject * object,GtkItemFactory * ifactory)1438 ifactory_delete_popup_data (GtkObject	   *object,
1439 			    GtkItemFactory *ifactory)
1440 {
1441   g_signal_handlers_disconnect_by_func (object,
1442 					ifactory_delete_popup_data,
1443 					ifactory);
1444   g_object_set_qdata (G_OBJECT (ifactory), quark_popup_data, NULL);
1445 }
1446 
1447 /**
1448  * gtk_item_factory_popup:
1449  * @ifactory: a #GtkItemFactory of type #GTK_TYPE_MENU (see gtk_item_factory_new())
1450  * @x: the x position
1451  * @y: the y position
1452  * @mouse_button: the mouse button which was pressed to initiate the popup
1453  * @time_: the time at which the activation event occurred
1454  *
1455  * Pops up the menu constructed from the item factory at (@x, @y).
1456  *
1457  * The @mouse_button parameter should be the mouse button pressed to initiate
1458  * the menu popup. If the menu popup was initiated by something other than
1459  * a mouse button press, such as a mouse button release or a keypress,
1460  * @mouse_button should be 0.
1461  *
1462  * The @time_ parameter should be the time stamp of the event that
1463  * initiated the popup. If such an event is not available, use
1464  * gtk_get_current_event_time() instead.
1465  *
1466  * The operation of the @mouse_button and the @time_ parameter is the same
1467  * as the @button and @activation_time parameters for gtk_menu_popup().
1468  *
1469  * Deprecated: 2.4: Use #GtkUIManager instead.
1470  */
1471 void
gtk_item_factory_popup(GtkItemFactory * ifactory,guint x,guint y,guint mouse_button,guint32 time)1472 gtk_item_factory_popup (GtkItemFactory		*ifactory,
1473 			guint			 x,
1474 			guint			 y,
1475 			guint			 mouse_button,
1476 			guint32			 time)
1477 {
1478   gtk_item_factory_popup_with_data (ifactory, NULL, NULL, x, y, mouse_button, time);
1479 }
1480 
1481 /**
1482  * gtk_item_factory_popup_with_data:
1483  * @ifactory: a #GtkItemFactory of type #GTK_TYPE_MENU (see gtk_item_factory_new())
1484  * @popup_data: data available for callbacks while the menu is posted
1485  * @destroy: a #GDestroyNotify function to be called on @popup_data when
1486  *  the menu is unposted
1487  * @x: the x position
1488  * @y: the y position
1489  * @mouse_button: the mouse button which was pressed to initiate the popup
1490  * @time_: the time at which the activation event occurred
1491  *
1492  * Pops up the menu constructed from the item factory at (@x, @y). Callbacks
1493  * can access the @popup_data while the menu is posted via
1494  * gtk_item_factory_popup_data() and gtk_item_factory_popup_data_from_widget().
1495  *
1496  * The @mouse_button parameter should be the mouse button pressed to initiate
1497  * the menu popup. If the menu popup was initiated by something other than
1498  * a mouse button press, such as a mouse button release or a keypress,
1499  * @mouse_button should be 0.
1500  *
1501  * The @time_ parameter should be the time stamp of the event that
1502  * initiated the popup. If such an event is not available, use
1503  * gtk_get_current_event_time() instead.
1504  *
1505  * The operation of the @mouse_button and the @time_ parameters is the same
1506  * as the @button and @activation_time parameters for gtk_menu_popup().
1507  *
1508  * Deprecated: 2.4: Use #GtkUIManager instead.
1509  */
1510 void
gtk_item_factory_popup_with_data(GtkItemFactory * ifactory,gpointer popup_data,GDestroyNotify destroy,guint x,guint y,guint mouse_button,guint32 time)1511 gtk_item_factory_popup_with_data (GtkItemFactory	*ifactory,
1512 				  gpointer		 popup_data,
1513 				  GDestroyNotify         destroy,
1514 				  guint			 x,
1515 				  guint			 y,
1516 				  guint			 mouse_button,
1517 				  guint32		 time)
1518 {
1519   MenuPos *mpos;
1520 
1521   g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory));
1522   g_return_if_fail (GTK_IS_MENU (ifactory->widget));
1523 
1524   mpos = g_object_get_qdata (G_OBJECT (ifactory->widget), quark_if_menu_pos);
1525 
1526   if (!mpos)
1527     {
1528       mpos = g_new0 (MenuPos, 1);
1529       g_object_set_qdata_full (G_OBJECT (ifactory->widget),
1530 			       quark_if_menu_pos,
1531 			       mpos,
1532 			       g_free);
1533     }
1534 
1535   mpos->x = x;
1536   mpos->y = y;
1537 
1538   if (popup_data != NULL)
1539     {
1540       g_object_set_qdata_full (G_OBJECT (ifactory),
1541 			       quark_popup_data,
1542 			       popup_data,
1543 			       destroy);
1544       g_signal_connect (ifactory->widget,
1545 			"selection-done",
1546 			G_CALLBACK (ifactory_delete_popup_data),
1547 			ifactory);
1548     }
1549 
1550   gtk_menu_popup (GTK_MENU (ifactory->widget),
1551 		  NULL, NULL,
1552 		  gtk_item_factory_menu_pos, mpos,
1553 		  mouse_button, time);
1554 }
1555 
1556 /**
1557  * gtk_item_factory_set_translate_func:
1558  * @ifactory: a #GtkItemFactory
1559  * @func: the #GtkTranslateFunc function to be used to translate path elements
1560  * @data: data to pass to @func and @notify
1561  * @notify: a #GDestroyNotify function to be called when @ifactory is
1562  *   destroyed and when the translation function is changed again
1563  *
1564  * Sets a function to be used for translating the path elements before they
1565  * are displayed.
1566  *
1567  * Deprecated: 2.4: Use #GtkUIManager instead.
1568  */
1569 void
gtk_item_factory_set_translate_func(GtkItemFactory * ifactory,GtkTranslateFunc func,gpointer data,GDestroyNotify notify)1570 gtk_item_factory_set_translate_func (GtkItemFactory    *ifactory,
1571 				     GtkTranslateFunc   func,
1572 				     gpointer           data,
1573 				     GDestroyNotify     notify)
1574 {
1575   g_return_if_fail (ifactory != NULL);
1576 
1577   if (ifactory->translate_notify)
1578     ifactory->translate_notify (ifactory->translate_data);
1579 
1580   ifactory->translate_func = func;
1581   ifactory->translate_data = data;
1582   ifactory->translate_notify = notify;
1583 }
1584 
1585 #define __GTK_ITEM_FACTORY_C__
1586 #include "gtkaliasdef.c"
1587