1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpmenufactory.c
5  * Copyright (C) 2001-2004 Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include <gegl.h>
26 #include <gtk/gtk.h>
27 
28 #include "libgimpwidgets/gimpwidgets.h"
29 
30 #include "widgets-types.h"
31 
32 #include "core/gimp.h"
33 
34 #include "gimpaction.h"
35 #include "gimpactionfactory.h"
36 #include "gimpactiongroup.h"
37 #include "gimpmenufactory.h"
38 #include "gimpuimanager.h"
39 
40 
41 struct _GimpMenuFactoryPrivate
42 {
43   Gimp              *gimp;
44   GimpActionFactory *action_factory;
45   GList             *registered_menus;
46 };
47 
48 
49 static void   gimp_menu_factory_finalize (GObject *object);
50 
51 
G_DEFINE_TYPE_WITH_PRIVATE(GimpMenuFactory,gimp_menu_factory,GIMP_TYPE_OBJECT)52 G_DEFINE_TYPE_WITH_PRIVATE (GimpMenuFactory, gimp_menu_factory,
53                             GIMP_TYPE_OBJECT)
54 
55 #define parent_class gimp_menu_factory_parent_class
56 
57 
58 static void
59 gimp_menu_factory_class_init (GimpMenuFactoryClass *klass)
60 {
61   GObjectClass *object_class = G_OBJECT_CLASS (klass);
62 
63   object_class->finalize = gimp_menu_factory_finalize;
64 }
65 
66 static void
gimp_menu_factory_init(GimpMenuFactory * factory)67 gimp_menu_factory_init (GimpMenuFactory *factory)
68 {
69   factory->p = gimp_menu_factory_get_instance_private (factory);
70 }
71 
72 static void
gimp_menu_factory_finalize(GObject * object)73 gimp_menu_factory_finalize (GObject *object)
74 {
75   GimpMenuFactory *factory = GIMP_MENU_FACTORY (object);
76   GList           *list;
77 
78   for (list = factory->p->registered_menus; list; list = g_list_next (list))
79     {
80       GimpMenuFactoryEntry *entry = list->data;
81       GList                *uis;
82 
83       g_free (entry->identifier);
84 
85       g_list_free_full (entry->action_groups, (GDestroyNotify) g_free);
86 
87       for (uis = entry->managed_uis; uis; uis = g_list_next (uis))
88         {
89           GimpUIManagerUIEntry *ui_entry = uis->data;
90 
91           g_free (ui_entry->ui_path);
92           g_free (ui_entry->basename);
93 
94           g_slice_free (GimpUIManagerUIEntry, ui_entry);
95         }
96 
97       g_list_free (entry->managed_uis);
98 
99       g_slice_free (GimpMenuFactoryEntry, entry);
100     }
101 
102   g_list_free (factory->p->registered_menus);
103   factory->p->registered_menus = NULL;
104 
105   G_OBJECT_CLASS (parent_class)->finalize (object);
106 }
107 
108 GimpMenuFactory *
gimp_menu_factory_new(Gimp * gimp,GimpActionFactory * action_factory)109 gimp_menu_factory_new (Gimp              *gimp,
110                        GimpActionFactory *action_factory)
111 {
112   GimpMenuFactory *factory;
113 
114   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
115   g_return_val_if_fail (GIMP_IS_ACTION_FACTORY (action_factory), NULL);
116 
117   factory = g_object_new (GIMP_TYPE_MENU_FACTORY, NULL);
118 
119   factory->p->gimp           = gimp;
120   factory->p->action_factory = action_factory;
121 
122   return factory;
123 }
124 
125 void
gimp_menu_factory_manager_register(GimpMenuFactory * factory,const gchar * identifier,const gchar * first_group,...)126 gimp_menu_factory_manager_register (GimpMenuFactory *factory,
127                                     const gchar     *identifier,
128                                     const gchar     *first_group,
129                                     ...)
130 {
131   GimpMenuFactoryEntry *entry;
132   const gchar          *group;
133   const gchar          *ui_path;
134   va_list               args;
135 
136   g_return_if_fail (GIMP_IS_MENU_FACTORY (factory));
137   g_return_if_fail (identifier != NULL);
138   g_return_if_fail (first_group != NULL);
139 
140   entry = g_slice_new0 (GimpMenuFactoryEntry);
141 
142   entry->identifier = g_strdup (identifier);
143 
144   factory->p->registered_menus = g_list_prepend (factory->p->registered_menus, entry);
145 
146   va_start (args, first_group);
147 
148   for (group = first_group;
149        group;
150        group = va_arg (args, const gchar *))
151     {
152       entry->action_groups = g_list_prepend (entry->action_groups,
153                                              g_strdup (group));
154     }
155 
156   entry->action_groups = g_list_reverse (entry->action_groups);
157 
158   ui_path = va_arg (args, const gchar *);
159 
160   while (ui_path)
161     {
162       const gchar            *ui_basename;
163       GimpUIManagerSetupFunc  setup_func;
164       GimpUIManagerUIEntry   *ui_entry;
165 
166       ui_basename = va_arg (args, const gchar *);
167       setup_func  = va_arg (args, GimpUIManagerSetupFunc);
168 
169       ui_entry = g_slice_new0 (GimpUIManagerUIEntry);
170 
171       ui_entry->ui_path    = g_strdup (ui_path);
172       ui_entry->basename   = g_strdup (ui_basename);
173       ui_entry->setup_func = setup_func;
174 
175       entry->managed_uis = g_list_prepend (entry->managed_uis, ui_entry);
176 
177       ui_path = va_arg (args, const gchar *);
178     }
179 
180   entry->managed_uis = g_list_reverse (entry->managed_uis);
181 
182   va_end (args);
183 }
184 
185 GList *
gimp_menu_factory_get_registered_menus(GimpMenuFactory * factory)186 gimp_menu_factory_get_registered_menus (GimpMenuFactory *factory)
187 {
188   g_return_val_if_fail (GIMP_IS_MENU_FACTORY (factory), NULL);
189 
190   return factory->p->registered_menus;
191 }
192 
193 static void
gimp_menu_factory_manager_action_added(GimpActionGroup * group,GimpAction * action,GtkAccelGroup * accel_group)194 gimp_menu_factory_manager_action_added (GimpActionGroup *group,
195                                         GimpAction      *action,
196                                         GtkAccelGroup   *accel_group)
197 {
198   gimp_action_set_accel_group (action, accel_group);
199   gimp_action_connect_accelerator (action);
200 }
201 
202 GimpUIManager *
gimp_menu_factory_manager_new(GimpMenuFactory * factory,const gchar * identifier,gpointer callback_data,gboolean create_tearoff)203 gimp_menu_factory_manager_new (GimpMenuFactory *factory,
204                                const gchar     *identifier,
205                                gpointer         callback_data,
206                                gboolean         create_tearoff)
207 {
208   GList *list;
209 
210   g_return_val_if_fail (GIMP_IS_MENU_FACTORY (factory), NULL);
211   g_return_val_if_fail (identifier != NULL, NULL);
212 
213   for (list = factory->p->registered_menus; list; list = g_list_next (list))
214     {
215       GimpMenuFactoryEntry *entry = list->data;
216 
217       if (! strcmp (entry->identifier, identifier))
218         {
219           GimpUIManager *manager;
220           GtkAccelGroup *accel_group;
221           GList         *list;
222 
223           manager = gimp_ui_manager_new (factory->p->gimp, entry->identifier);
224           gtk_ui_manager_set_add_tearoffs (GTK_UI_MANAGER (manager),
225                                            create_tearoff);
226 
227           accel_group = gimp_ui_manager_get_accel_group (manager);
228 
229           for (list = entry->action_groups; list; list = g_list_next (list))
230             {
231               GimpActionGroup *group;
232               GList           *actions;
233               GList           *list2;
234 
235               group = gimp_action_factory_group_new (factory->p->action_factory,
236                                                      (const gchar *) list->data,
237                                                      callback_data);
238 
239               actions = gimp_action_group_list_actions (group);
240 
241               for (list2 = actions; list2; list2 = g_list_next (list2))
242                 {
243                   GimpAction *action = list2->data;
244 
245                   gimp_action_set_accel_group (action, accel_group);
246                   gimp_action_connect_accelerator (action);
247                 }
248 
249               g_list_free (actions);
250 
251               g_signal_connect_object (group, "action-added",
252                                        G_CALLBACK (gimp_menu_factory_manager_action_added),
253                                        accel_group, 0);
254 
255               gimp_ui_manager_insert_action_group (manager, group, -1);
256               g_object_unref (group);
257             }
258 
259           for (list = entry->managed_uis; list; list = g_list_next (list))
260             {
261               GimpUIManagerUIEntry *ui_entry = list->data;
262 
263               gimp_ui_manager_ui_register (manager,
264                                            ui_entry->ui_path,
265                                            ui_entry->basename,
266                                            ui_entry->setup_func);
267             }
268 
269           return manager;
270         }
271     }
272 
273   g_warning ("%s: no entry registered for \"%s\"",
274              G_STRFUNC, identifier);
275 
276   return NULL;
277 }
278