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