]> Pileus Git - ~andy/gtk/blob - gtk/gtkactiongroup.c
Namespace the enum values properly. Sorry about the resize grip trouble,
[~andy/gtk] / gtk / gtkactiongroup.c
1 /*
2  * GTK - The GIMP Toolkit
3  * Copyright (C) 1998, 1999 Red Hat, Inc.
4  * All rights reserved.
5  *
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.
10  *
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.
15  *
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.
20  */
21
22 /*
23  * Author: James Henstridge <james@daa.com.au>
24  *
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/. 
29  */
30
31 #include <config.h>
32
33 #include "gtkactiongroup.h"
34 #include "gtktoggleaction.h"
35 #include "gtkradioaction.h"
36 #include "gtkaccelmap.h"
37 #include "gtkintl.h"
38
39 #define GTK_ACTION_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION_GROUP, GtkActionGroupPrivate))
40
41 struct _GtkActionGroupPrivate 
42 {
43   gchar      *name;
44   GHashTable *actions;
45 };
46
47 static void gtk_action_group_init       (GtkActionGroup *self);
48 static void gtk_action_group_class_init (GtkActionGroupClass *class);
49
50 GType
51 gtk_action_group_get_type (void)
52 {
53   static GType type = 0;
54
55   if (!type)
56     {
57       static const GTypeInfo type_info =
58       {
59         sizeof (GtkActionGroupClass),
60         NULL,           /* base_init */
61         NULL,           /* base_finalize */
62         (GClassInitFunc) gtk_action_group_class_init,
63         NULL,           /* class_finalize */
64         NULL,           /* class_data */
65         sizeof (GtkActionGroup),
66         0, /* n_preallocs */
67         (GInstanceInitFunc) gtk_action_group_init,
68       };
69
70       type = g_type_register_static (G_TYPE_OBJECT, "GtkActionGroup",
71                                      &type_info, 0);
72     }
73
74   return type;
75 }
76
77 static GObjectClass *parent_class = NULL;
78 static void       gtk_action_group_finalize        (GObject        *object);
79 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup *self,
80                                                     const gchar    *name);
81
82 static void
83 gtk_action_group_class_init (GtkActionGroupClass *klass)
84 {
85   GObjectClass *gobject_class;
86
87   gobject_class = G_OBJECT_CLASS (klass);
88   parent_class = g_type_class_peek_parent (klass);
89
90   gobject_class->finalize = gtk_action_group_finalize;
91   klass->get_action = gtk_action_group_real_get_action;
92
93   g_type_class_add_private (gobject_class, sizeof (GtkActionGroupPrivate));
94 }
95
96 static void
97 gtk_action_group_init (GtkActionGroup *self)
98 {
99   self->private_data = GTK_ACTION_GROUP_GET_PRIVATE (self);
100   self->private_data->name = NULL;
101   self->private_data->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
102                                                        (GDestroyNotify) g_free,
103                                                        (GDestroyNotify) g_object_unref);
104 }
105
106 /**
107  * gtk_action_group_new:
108  * @name: the name of the action group
109  *
110  * Creates a new #GtkActionGroup object.
111  *
112  * Returns: the new #GtkActionGroup
113  *
114  * Since: 2.4
115  */
116 GtkActionGroup *
117 gtk_action_group_new (const gchar *name)
118 {
119   GtkActionGroup *self;
120
121   self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
122   self->private_data->name = g_strdup (name);
123
124   return self;
125 }
126
127 static void
128 gtk_action_group_finalize (GObject *object)
129 {
130   GtkActionGroup *self;
131
132   self = GTK_ACTION_GROUP (object);
133
134   g_free (self->private_data->name);
135   self->private_data->name = NULL;
136
137   g_hash_table_destroy (self->private_data->actions);
138   self->private_data->actions = NULL;
139
140   if (parent_class->finalize)
141     (* parent_class->finalize) (object);
142 }
143
144 static GtkAction *
145 gtk_action_group_real_get_action (GtkActionGroup *self,
146                                   const gchar    *action_name)
147 {
148   return g_hash_table_lookup (self->private_data->actions, action_name);
149 }
150
151 /**
152  * gtk_action_group_get_name:
153  * @action_group: the action group
154  *
155  * Gets the name of the action group.
156  *
157  * Returns: the name of the action group.
158  * 
159  * Since: 2.4
160  */
161 const gchar *
162 gtk_action_group_get_name (GtkActionGroup *action_group)
163 {
164   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
165
166   return action_group->private_data->name;
167 }
168
169 /**
170  * gtk_action_group_get_action:
171  * @action_group: the action group
172  * @action_name: the name of the action
173  *
174  * Looks up an action in the action group by name.
175  *
176  * Returns: the action, or %NULL if no action by that name exists
177  *
178  * Since: 2.4
179  */
180 GtkAction *
181 gtk_action_group_get_action (GtkActionGroup *action_group,
182                              const gchar    *action_name)
183 {
184   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
185   g_return_val_if_fail (GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
186
187   return (* GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action)
188     (action_group, action_name);
189 }
190
191 /**
192  * gtk_action_group_add_action:
193  * @action_group: the action group
194  * @action: an action
195  *
196  * Adds an action object to the action group.
197  *
198  * Since: 2.4
199  */
200 void
201 gtk_action_group_add_action (GtkActionGroup *action_group,
202                              GtkAction      *action)
203 {
204   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
205   g_return_if_fail (GTK_IS_ACTION (action));
206   g_return_if_fail (gtk_action_get_name (action) != NULL);
207
208   g_hash_table_insert (action_group->private_data->actions, 
209                        g_strdup (gtk_action_get_name (action)),
210                        g_object_ref (action));
211 }
212
213 /**
214  * gtk_action_group_removes_action:
215  * @action_group: the action group
216  * @action: an action
217  *
218  * Removes an action object from the action group.
219  *
220  * Since: 2.4
221  */
222 void
223 gtk_action_group_remove_action (GtkActionGroup *action_group,
224                                 GtkAction      *action)
225 {
226   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
227   g_return_if_fail (GTK_IS_ACTION (action));
228   g_return_if_fail (gtk_action_get_name (action) != NULL);
229
230   /* extra protection to make sure action->name is valid */
231   g_object_ref (action);
232   g_hash_table_remove (action_group->private_data->actions, gtk_action_get_name (action));
233   g_object_unref (action);
234 }
235
236 static void
237 add_single_action (gpointer key, 
238                    gpointer value, 
239                    gpointer user_data)
240 {
241   GList **list = user_data;
242
243   *list = g_list_prepend (*list, value);
244 }
245
246 /**
247  * gtk_action_group_list_actions:
248  * @action_group: the action group
249  *
250  * Lists the actions in the action group.
251  *
252  * Returns: an allocated list of the action objects in the action group
253  * 
254  * Since: 2.4
255  */
256 GList *
257 gtk_action_group_list_actions (GtkActionGroup *action_group)
258 {
259   GList *actions = NULL;
260   
261   g_hash_table_foreach (action_group->private_data->actions, add_single_action, &actions);
262
263   return g_list_reverse (actions);
264 }
265
266
267 /**
268  * gtk_action_group_add_actions:
269  * @action_group: the action group
270  * @entries: an array of action descriptions
271  * @n_entries: the number of entries
272  *
273  * This is a convenience routine to create a number of actions and add
274  * them to the action group.  Each member of the array describes an
275  * action to create.
276  * 
277  * Since: 2.4
278  */
279 void
280 gtk_action_group_add_actions (GtkActionGroup      *action_group,
281                               GtkActionGroupEntry *entries,
282                               guint                n_entries)
283 {
284   guint i;
285
286   for (i = 0; i < n_entries; i++)
287     {
288       GtkAction *action;
289       GType action_type;
290       gchar *accel_path;
291
292       switch (entries[i].entry_type) {
293       case GTK_ACTION_NORMAL:
294         action_type = GTK_TYPE_ACTION;
295         break;
296       case GTK_ACTION_TOGGLE:
297         action_type = GTK_TYPE_TOGGLE_ACTION;
298         break;
299       case GTK_ACTION_RADIO:
300         action_type = GTK_TYPE_RADIO_ACTION;
301         break;
302       default:
303         g_warning ("unsupported action type");
304         action_type = GTK_TYPE_ACTION;
305       }
306
307       action = g_object_new (action_type,
308                              "name", entries[i].name,
309                              "label", _(entries[i].label),
310                              "tooltip", _(entries[i].tooltip),
311                              "stock_id", entries[i].stock_id,
312                              NULL);
313
314       if (entries[i].entry_type == GTK_ACTION_RADIO &&
315           entries[i].extra_data != NULL)
316         {
317           GtkAction *radio_action;
318           GSList *group;
319
320           radio_action =
321             gtk_action_group_get_action (GTK_ACTION_GROUP (action_group),
322                                          entries[i].extra_data);
323           if (radio_action)
324             {
325               group = gtk_radio_action_get_group (GTK_RADIO_ACTION (radio_action));
326               gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group);
327             }
328           else
329             g_warning (G_STRLOC " could not look up `%s'", entries[i].extra_data);
330         }
331
332       if (entries[i].callback)
333         g_signal_connect (action, "activate",
334                           entries[i].callback, entries[i].user_data);
335
336       /* set the accel path for the menu item */
337       accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
338                                 entries[i].name, NULL);
339       if (entries[i].accelerator)
340         {
341           guint accel_key = 0;
342           GdkModifierType accel_mods;
343
344           gtk_accelerator_parse (entries[i].accelerator, &accel_key,
345                                  &accel_mods);
346           if (accel_key)
347             gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
348         }
349
350       gtk_action_set_accel_path (action, accel_path);
351       g_free (accel_path);
352
353       gtk_action_group_add_action (action_group, action);
354       g_object_unref (action);
355     }
356 }