2 * GTK - The GIMP Toolkit
3 * Copyright (C) 1998, 1999 Red Hat, Inc.
6 * This Library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This Library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with the Gnome Library; see the file COPYING.LIB. If not,
18 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * Author: James Henstridge <james@daa.com.au>
25 * Modified by the GTK+ Team and others 2003. See the AUTHORS
26 * file for a list of people on the GTK+ Team. See the ChangeLog
27 * files for a list of changes. These files are distributed with
28 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gtkactiongroup.h"
34 #include "gtktoggleaction.h"
35 #include "gtkradioaction.h"
36 #include "gtkaccelmap.h"
39 #define GTK_ACTION_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION_GROUP, GtkActionGroupPrivate))
41 struct _GtkActionGroupPrivate
46 GtkTranslateFunc translate_func;
47 gpointer translate_data;
48 GtkDestroyNotify translate_notify;
51 static void gtk_action_group_init (GtkActionGroup *self);
52 static void gtk_action_group_class_init (GtkActionGroupClass *class);
55 gtk_action_group_get_type (void)
57 static GType type = 0;
61 static const GTypeInfo type_info =
63 sizeof (GtkActionGroupClass),
65 NULL, /* base_finalize */
66 (GClassInitFunc) gtk_action_group_class_init,
67 NULL, /* class_finalize */
68 NULL, /* class_data */
69 sizeof (GtkActionGroup),
71 (GInstanceInitFunc) gtk_action_group_init,
74 type = g_type_register_static (G_TYPE_OBJECT, "GtkActionGroup",
81 static GObjectClass *parent_class = NULL;
82 static void gtk_action_group_finalize (GObject *object);
83 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup *self,
87 gtk_action_group_class_init (GtkActionGroupClass *klass)
89 GObjectClass *gobject_class;
91 gobject_class = G_OBJECT_CLASS (klass);
92 parent_class = g_type_class_peek_parent (klass);
94 gobject_class->finalize = gtk_action_group_finalize;
95 klass->get_action = gtk_action_group_real_get_action;
97 g_type_class_add_private (gobject_class, sizeof (GtkActionGroupPrivate));
101 gtk_action_group_init (GtkActionGroup *self)
103 self->private_data = GTK_ACTION_GROUP_GET_PRIVATE (self);
104 self->private_data->name = NULL;
105 self->private_data->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
106 (GDestroyNotify) g_free,
107 (GDestroyNotify) g_object_unref);
108 self->private_data->translate_func = NULL;
109 self->private_data->translate_data = NULL;
110 self->private_data->translate_notify = NULL;
114 * gtk_action_group_new:
115 * @name: the name of the action group
117 * Creates a new #GtkActionGroup object.
119 * Returns: the new #GtkActionGroup
124 gtk_action_group_new (const gchar *name)
126 GtkActionGroup *self;
128 self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
129 self->private_data->name = g_strdup (name);
135 gtk_action_group_finalize (GObject *object)
137 GtkActionGroup *self;
139 self = GTK_ACTION_GROUP (object);
141 g_free (self->private_data->name);
142 self->private_data->name = NULL;
144 g_hash_table_destroy (self->private_data->actions);
145 self->private_data->actions = NULL;
147 if (self->private_data->translate_notify)
148 self->private_data->translate_notify (self->private_data->translate_data);
150 if (parent_class->finalize)
151 (* parent_class->finalize) (object);
155 gtk_action_group_real_get_action (GtkActionGroup *self,
156 const gchar *action_name)
158 return g_hash_table_lookup (self->private_data->actions, action_name);
162 * gtk_action_group_get_name:
163 * @action_group: the action group
165 * Gets the name of the action group.
167 * Returns: the name of the action group.
172 gtk_action_group_get_name (GtkActionGroup *action_group)
174 g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
176 return action_group->private_data->name;
180 * gtk_action_group_get_action:
181 * @action_group: the action group
182 * @action_name: the name of the action
184 * Looks up an action in the action group by name.
186 * Returns: the action, or %NULL if no action by that name exists
191 gtk_action_group_get_action (GtkActionGroup *action_group,
192 const gchar *action_name)
194 g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
195 g_return_val_if_fail (GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
197 return (* GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action)
198 (action_group, action_name);
202 * gtk_action_group_add_action:
203 * @action_group: the action group
206 * Adds an action object to the action group.
211 gtk_action_group_add_action (GtkActionGroup *action_group,
214 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
215 g_return_if_fail (GTK_IS_ACTION (action));
216 g_return_if_fail (gtk_action_get_name (action) != NULL);
218 g_hash_table_insert (action_group->private_data->actions,
219 g_strdup (gtk_action_get_name (action)),
220 g_object_ref (action));
224 * gtk_action_group_removes_action:
225 * @action_group: the action group
228 * Removes an action object from the action group.
233 gtk_action_group_remove_action (GtkActionGroup *action_group,
236 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
237 g_return_if_fail (GTK_IS_ACTION (action));
238 g_return_if_fail (gtk_action_get_name (action) != NULL);
240 /* extra protection to make sure action->name is valid */
241 g_object_ref (action);
242 g_hash_table_remove (action_group->private_data->actions, gtk_action_get_name (action));
243 g_object_unref (action);
247 add_single_action (gpointer key,
251 GList **list = user_data;
253 *list = g_list_prepend (*list, value);
257 * gtk_action_group_list_actions:
258 * @action_group: the action group
260 * Lists the actions in the action group.
262 * Returns: an allocated list of the action objects in the action group
267 gtk_action_group_list_actions (GtkActionGroup *action_group)
269 GList *actions = NULL;
270 g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
272 g_hash_table_foreach (action_group->private_data->actions, add_single_action, &actions);
274 return g_list_reverse (actions);
279 * gtk_action_group_add_actions:
280 * @action_group: the action group
281 * @entries: an array of action descriptions
282 * @n_entries: the number of entries
283 * @user_data: data to pass to the action callbacks
285 * This is a convenience routine to create a number of actions and add
286 * them to the action group. Each member of the array describes an
292 gtk_action_group_add_actions (GtkActionGroup *action_group,
293 GtkActionEntry *entries,
297 gtk_action_group_add_actions_full (action_group,
304 * gtk_action_group_add_actions_full:
305 * @action_group: the action group
306 * @entries: an array of action descriptions
307 * @n_entries: the number of entries
308 * @user_data: data to pass to the action callbacks
309 * @destroy: destroy notification callback for @user_data
311 * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
312 * callback for @user_data.
317 gtk_action_group_add_actions_full (GtkActionGroup *action_group,
318 GtkActionEntry *entries,
321 GDestroyNotify destroy)
324 GtkTranslateFunc translate_func;
325 gpointer translate_data;
327 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
329 translate_func = action_group->private_data->translate_func;
330 translate_data = action_group->private_data->translate_data;
332 for (i = 0; i < n_entries; i++)
340 if (entries[i].is_toggle)
341 action_type = GTK_TYPE_TOGGLE_ACTION;
343 action_type = GTK_TYPE_ACTION;
347 label = translate_func (entries[i].label, translate_data);
348 tooltip = translate_func (entries[i].tooltip, translate_data);
352 label = entries[i].label;
353 tooltip = entries[i].tooltip;
356 action = g_object_new (action_type,
357 "name", entries[i].name,
360 "stock_id", entries[i].stock_id,
363 if (entries[i].callback)
364 g_signal_connect_data (action, "activate",
366 user_data, (GClosureNotify)destroy, 0);
368 /* set the accel path for the menu item */
369 accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
370 entries[i].name, NULL);
371 if (entries[i].accelerator)
374 GdkModifierType accel_mods;
376 gtk_accelerator_parse (entries[i].accelerator, &accel_key,
379 gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
382 gtk_action_set_accel_path (action, accel_path);
385 gtk_action_group_add_action (action_group, action);
386 g_object_unref (action);
391 * gtk_action_group_add_radio_actions:
392 * @action_group: the action group
393 * @entries: an array of radio action descriptions
394 * @n_entries: the number of entries
395 * @on_change: the callback to connect to the changed signal
396 * @user_data: data to pass to the action callbacks
398 * This is a convenience routine to create a group of radio actions and
399 * add them to the action group. Each member of the array describes a
400 * radio action to create.
406 gtk_action_group_add_radio_actions (GtkActionGroup *action_group,
407 GtkRadioActionEntry *entries,
412 gtk_action_group_add_radio_actions_full (action_group,
414 on_change, user_data, NULL);
418 gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group,
419 GtkRadioActionEntry *entries,
423 GDestroyNotify destroy)
426 GtkTranslateFunc translate_func;
427 gpointer translate_data;
429 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
431 translate_func = action_group->private_data->translate_func;
432 translate_data = action_group->private_data->translate_data;
434 for (i = 0; i < n_entries; i++)
443 label = translate_func (entries[i].label, translate_data);
444 tooltip = translate_func (entries[i].tooltip, translate_data);
448 label = entries[i].label;
449 tooltip = entries[i].tooltip;
452 action = g_object_new (GTK_TYPE_RADIO_ACTION,
453 "name", entries[i].name,
456 "stock_id", entries[i].stock_id,
457 "value", entries[i].value,
463 g_signal_connect_data (action, "changed",
464 on_change, user_data,
465 (GClosureNotify)destroy, 0);
469 GSList *group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
470 gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group);
473 /* set the accel path for the menu item */
474 accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
475 entries[i].name, NULL);
476 if (entries[i].accelerator)
479 GdkModifierType accel_mods;
481 gtk_accelerator_parse (entries[i].accelerator, &accel_key,
484 gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
487 gtk_action_set_accel_path (action, accel_path);
490 gtk_action_group_add_action (action_group, action);
491 g_object_unref (action);
496 * gtk_action_group_set_translate_func:
497 * @action_group: a #GtkActionGroup
498 * @func: a #GtkTranslateFunc
499 * @data: data to be passed to @func and @notify
500 * @notify: a #GtkDestroyNotify function to be called when @action_group is
501 * destroyed and when the translation function is changed again
503 * Sets a function to be used for translating the @label and @tooltip of
504 * #GtkActionGroupEntry<!-- -->s added by gtk_action_group_add_actions().
506 * If you're using gettext(), it is enough to set the translation domain
507 * with gtk_action_group_set_translation_domain().
512 gtk_action_group_set_translate_func (GtkActionGroup *action_group,
513 GtkTranslateFunc func,
515 GtkDestroyNotify notify)
517 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
519 if (action_group->private_data->translate_notify)
520 action_group->private_data->translate_notify (action_group->private_data->translate_data);
522 action_group->private_data->translate_func = func;
523 action_group->private_data->translate_data = data;
524 action_group->private_data->translate_notify = notify;
528 dgettext_swapped (const gchar *msgid,
529 const gchar *domainname)
531 return dgettext (domainname, msgid);
535 * gtk_action_group_set_translation_domain:
536 * @action_group: a #GtkActionGroup
537 * @domain: the translation domain to use for dgettext() calls
539 * Sets the translation domain and uses dgettext() for translating the
540 * @label and @tooltip of #GtkActionEntry<!-- -->s added by
541 * gtk_action_group_add_actions().
543 * If you're not using gettext() for localization, see
544 * gtk_action_group_set_translate_func().
549 gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
552 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
554 gtk_action_group_set_translate_func (action_group,
555 (GtkTranslateFunc)dgettext_swapped,