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. The name of the action group
118 * is used when associating <link linkend="Action-Accel">keybindings</link>
121 * Returns: the new #GtkActionGroup
126 gtk_action_group_new (const gchar *name)
128 GtkActionGroup *self;
130 self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
131 self->private_data->name = g_strdup (name);
137 gtk_action_group_finalize (GObject *object)
139 GtkActionGroup *self;
141 self = GTK_ACTION_GROUP (object);
143 g_free (self->private_data->name);
144 self->private_data->name = NULL;
146 g_hash_table_destroy (self->private_data->actions);
147 self->private_data->actions = NULL;
149 if (self->private_data->translate_notify)
150 self->private_data->translate_notify (self->private_data->translate_data);
152 if (parent_class->finalize)
153 (* parent_class->finalize) (object);
157 gtk_action_group_real_get_action (GtkActionGroup *self,
158 const gchar *action_name)
160 return g_hash_table_lookup (self->private_data->actions, action_name);
164 * gtk_action_group_get_name:
165 * @action_group: the action group
167 * Gets the name of the action group.
169 * Returns: the name of the action group.
174 gtk_action_group_get_name (GtkActionGroup *action_group)
176 g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
178 return action_group->private_data->name;
182 * gtk_action_group_get_action:
183 * @action_group: the action group
184 * @action_name: the name of the action
186 * Looks up an action in the action group by name.
188 * Returns: the action, or %NULL if no action by that name exists
193 gtk_action_group_get_action (GtkActionGroup *action_group,
194 const gchar *action_name)
196 g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
197 g_return_val_if_fail (GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
199 return (* GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action)
200 (action_group, action_name);
204 * gtk_action_group_add_action:
205 * @action_group: the action group
208 * Adds an action object to the action group.
213 gtk_action_group_add_action (GtkActionGroup *action_group,
216 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
217 g_return_if_fail (GTK_IS_ACTION (action));
218 g_return_if_fail (gtk_action_get_name (action) != NULL);
220 g_hash_table_insert (action_group->private_data->actions,
221 g_strdup (gtk_action_get_name (action)),
222 g_object_ref (action));
226 * gtk_action_group_removes_action:
227 * @action_group: the action group
230 * Removes an action object from the action group.
235 gtk_action_group_remove_action (GtkActionGroup *action_group,
238 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
239 g_return_if_fail (GTK_IS_ACTION (action));
240 g_return_if_fail (gtk_action_get_name (action) != NULL);
242 /* extra protection to make sure action->name is valid */
243 g_object_ref (action);
244 g_hash_table_remove (action_group->private_data->actions, gtk_action_get_name (action));
245 g_object_unref (action);
249 add_single_action (gpointer key,
253 GList **list = user_data;
255 *list = g_list_prepend (*list, value);
259 * gtk_action_group_list_actions:
260 * @action_group: the action group
262 * Lists the actions in the action group.
264 * Returns: an allocated list of the action objects in the action group
269 gtk_action_group_list_actions (GtkActionGroup *action_group)
271 GList *actions = NULL;
272 g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
274 g_hash_table_foreach (action_group->private_data->actions, add_single_action, &actions);
276 return g_list_reverse (actions);
281 * gtk_action_group_add_actions:
282 * @action_group: the action group
283 * @entries: an array of action descriptions
284 * @n_entries: the number of entries
285 * @user_data: data to pass to the action callbacks
287 * This is a convenience routine to create a number of actions and add
288 * them to the action group. Each member of the array describes an
294 gtk_action_group_add_actions (GtkActionGroup *action_group,
295 GtkActionEntry *entries,
299 gtk_action_group_add_actions_full (action_group,
306 * gtk_action_group_add_actions_full:
307 * @action_group: the action group
308 * @entries: an array of action descriptions
309 * @n_entries: the number of entries
310 * @user_data: data to pass to the action callbacks
311 * @destroy: destroy notification callback for @user_data
313 * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
314 * callback for @user_data.
319 gtk_action_group_add_actions_full (GtkActionGroup *action_group,
320 GtkActionEntry *entries,
323 GDestroyNotify destroy)
326 GtkTranslateFunc translate_func;
327 gpointer translate_data;
329 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
331 translate_func = action_group->private_data->translate_func;
332 translate_data = action_group->private_data->translate_data;
334 for (i = 0; i < n_entries; i++)
342 if (entries[i].is_toggle)
343 action_type = GTK_TYPE_TOGGLE_ACTION;
345 action_type = GTK_TYPE_ACTION;
349 label = translate_func (entries[i].label, translate_data);
350 tooltip = translate_func (entries[i].tooltip, translate_data);
354 label = entries[i].label;
355 tooltip = entries[i].tooltip;
358 action = g_object_new (action_type,
359 "name", entries[i].name,
362 "stock_id", entries[i].stock_id,
365 if (entries[i].callback)
366 g_signal_connect_data (action, "activate",
368 user_data, (GClosureNotify)destroy, 0);
370 /* set the accel path for the menu item */
371 accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
372 entries[i].name, NULL);
373 if (entries[i].accelerator)
376 GdkModifierType accel_mods;
378 gtk_accelerator_parse (entries[i].accelerator, &accel_key,
381 gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
384 gtk_action_set_accel_path (action, accel_path);
387 gtk_action_group_add_action (action_group, action);
388 g_object_unref (action);
393 * gtk_action_group_add_radio_actions:
394 * @action_group: the action group
395 * @entries: an array of radio action descriptions
396 * @n_entries: the number of entries
397 * @on_change: the callback to connect to the changed signal
398 * @user_data: data to pass to the action callbacks
400 * This is a convenience routine to create a group of radio actions and
401 * add them to the action group. Each member of the array describes a
402 * radio action to create.
407 gtk_action_group_add_radio_actions (GtkActionGroup *action_group,
408 GtkRadioActionEntry *entries,
413 gtk_action_group_add_radio_actions_full (action_group,
415 on_change, user_data, NULL);
419 * gtk_action_group_add_radio_actions_full:
420 * @action_group: the action group
421 * @entries: an array of radio action descriptions
422 * @n_entries: the number of entries
423 * @on_change: the callback to connect to the changed signal
424 * @user_data: data to pass to the action callbacks
425 * @destroy: destroy notification callback for @user_data
427 * This variant of gtk_action_group_add_radio_actions() adds a
428 * #GDestroyNotify callback for @user_data.
433 gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group,
434 GtkRadioActionEntry *entries,
438 GDestroyNotify destroy)
441 GtkTranslateFunc translate_func;
442 gpointer translate_data;
443 GSList *group = NULL;
445 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
447 translate_func = action_group->private_data->translate_func;
448 translate_data = action_group->private_data->translate_data;
450 for (i = 0; i < n_entries; i++)
459 label = translate_func (entries[i].label, translate_data);
460 tooltip = translate_func (entries[i].tooltip, translate_data);
464 label = entries[i].label;
465 tooltip = entries[i].tooltip;
468 action = g_object_new (GTK_TYPE_RADIO_ACTION,
469 "name", entries[i].name,
472 "stock_id", entries[i].stock_id,
473 "value", entries[i].value,
479 g_signal_connect_data (action, "changed",
480 on_change, user_data,
481 (GClosureNotify)destroy, 0);
483 gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group);
484 group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
486 /* set the accel path for the menu item */
487 accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
488 entries[i].name, NULL);
489 if (entries[i].accelerator)
492 GdkModifierType accel_mods;
494 gtk_accelerator_parse (entries[i].accelerator, &accel_key,
497 gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
500 gtk_action_set_accel_path (action, accel_path);
503 gtk_action_group_add_action (action_group, action);
504 g_object_unref (action);
509 * gtk_action_group_set_translate_func:
510 * @action_group: a #GtkActionGroup
511 * @func: a #GtkTranslateFunc
512 * @data: data to be passed to @func and @notify
513 * @notify: a #GtkDestroyNotify function to be called when @action_group is
514 * destroyed and when the translation function is changed again
516 * Sets a function to be used for translating the @label and @tooltip of
517 * #GtkActionGroupEntry<!-- -->s added by gtk_action_group_add_actions().
519 * If you're using gettext(), it is enough to set the translation domain
520 * with gtk_action_group_set_translation_domain().
525 gtk_action_group_set_translate_func (GtkActionGroup *action_group,
526 GtkTranslateFunc func,
528 GtkDestroyNotify notify)
530 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
532 if (action_group->private_data->translate_notify)
533 action_group->private_data->translate_notify (action_group->private_data->translate_data);
535 action_group->private_data->translate_func = func;
536 action_group->private_data->translate_data = data;
537 action_group->private_data->translate_notify = notify;
541 dgettext_swapped (const gchar *msgid,
542 const gchar *domainname)
544 return dgettext (domainname, msgid);
548 * gtk_action_group_set_translation_domain:
549 * @action_group: a #GtkActionGroup
550 * @domain: the translation domain to use for dgettext() calls
552 * Sets the translation domain and uses dgettext() for translating the
553 * @label and @tooltip of #GtkActionEntry<!-- -->s added by
554 * gtk_action_group_add_actions().
556 * If you're not using gettext() for localization, see
557 * gtk_action_group_set_translate_func().
562 gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
565 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
567 gtk_action_group_set_translate_func (action_group,
568 (GtkTranslateFunc)dgettext_swapped,