Updated Spanish translation
[anjuta-git-plugin.git] / libanjuta / anjuta-ui.c
blob350f0ddcb4888785cd293286c399aceec8ddb9e8
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-ui.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /**
22 * SECTION:anjuta-ui
23 * @short_description: User Interface manager
24 * @see_also: #GtkAction, #GtkActionEntry, #GtkToggleAction,
25 * #GtkToggleActionEntry, #GtkRadioAction, #GtkRadioActionEntry,
26 * #GtkActionGroup, #GtkUIManager
27 * @stability: Unstable
28 * @include: libanjuta/
30 * #AnjutaUI subclasses #GtkUIManager, so you should really read #GtkUIManager
31 * documentation first to know about Actions, UI merging and UI XML file
32 * format. This documentation will cover only the relevent APIs.
34 * #AnjutaUI has its own methods for adding action groups, which is differnt
35 * from #GtkUIManager methods. All #AnjutaPlugin based classes should use
36 * these methods instead of #GtkUIManager methods. The reason is, in addition
37 * to adding the actions and groups to the UI manager, it also resgisters
38 * them for UI customization and accellerators editing. It also keeps
39 * record of all actions.
41 * An interesting side effect of this is that these
42 * actions could be conveniently accessed or activated with
43 * anjuta_ui_get_action() or anjuta_ui_activate_action_by_path(), without
44 * the need of original action group object. This makes it is possible for
45 * activating actions remotely from other plugins.
47 * anjuta_ui_get_accel_editor() will return a widget containing the
48 * UI customization and accellerators editor. All actions and action groups
49 * are organized into a tree view, which should be added to a visible
50 * container (e.g. a #GtkDialog based object) and displayed to users.
52 * <note>
53 * <para>
54 * Any actions additions/removals using #GtkUIManager are not
55 * registred with #AnjutaUI and hence their accellerators
56 * cannot be edited. Nor will they be listed in UI manager
57 * dialog. Hence, use #AnjutaUI methods whenever possible.
58 * </para>
59 * </note>
62 #ifdef HAVE_CONFIG_H
63 # include <config.h>
64 #endif
66 #include <stdio.h>
67 #include <string.h>
68 #include <glib/gi18n.h>
69 #include <gtk/gtkscrolledwindow.h>
70 #include <gtk/gtkiconfactory.h>
71 #include <gtk/gtktreeview.h>
72 #include <gtk/gtktreestore.h>
73 #include <gtk/gtkcellrenderertoggle.h>
74 #include <gtk/gtkaccelmap.h>
75 #include <gtk/gtkcellrendererpixbuf.h>
76 #include <gtk/gtkimage.h>
77 #include <gtk/gtklabel.h>
79 #include <libgnome/gnome-macros.h>
81 #include <libegg/treeviewutils/eggcellrendererkeys.h>
83 #include "resources.h"
84 #include "anjuta-ui.h"
85 #include "anjuta-debug.h"
87 struct _AnjutaUIPrivate {
88 GtkIconFactory *icon_factory;
89 GtkTreeModel *model;
90 GHashTable *customizable_actions_hash;
91 GHashTable *uncustomizable_actions_hash;
94 enum {
95 COLUMN_PIXBUF,
96 COLUMN_ACTION,
97 COLUMN_VISIBLE,
98 COLUMN_SENSITIVE,
99 COLUMN_DATA,
100 COLUMN_GROUP,
101 N_COLUMNS
104 #if 0
105 static void
106 sensitivity_toggled (GtkCellRendererToggle *cell,
107 const gchar *path_str, GtkTreeModel *model)
109 GtkTreePath *path;
110 GtkTreeIter iter;
111 GtkAction *action;
112 gboolean sensitive;
114 path = gtk_tree_path_new_from_string (path_str);
115 gtk_tree_model_get_iter (model, &iter, path);
117 gtk_tree_model_get (model, &iter,
118 COLUMN_SENSITIVE, &sensitive,
119 COLUMN_DATA, &action, -1);
120 g_object_set (G_OBJECT (action), "sensitive", !sensitive, NULL);
121 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
122 COLUMN_SENSITIVE, !sensitive, -1);
123 gtk_tree_path_free (path);
125 #endif
127 static void
128 visibility_toggled (GtkCellRendererToggle *cell,
129 const gchar *path_str, GtkTreeModel *model)
131 GtkTreePath *path;
132 GtkTreeIter iter;
133 GtkAction *action;
134 gboolean visible;
136 path = gtk_tree_path_new_from_string (path_str);
137 gtk_tree_model_get_iter (model, &iter, path);
139 gtk_tree_model_get (model, &iter,
140 COLUMN_VISIBLE, &visible,
141 COLUMN_DATA, &action, -1);
142 g_object_set (G_OBJECT (action), "visible", !visible, NULL);
143 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
144 COLUMN_VISIBLE, !visible, -1);
145 gtk_tree_path_free (path);
148 static gchar*
149 get_action_label (GtkAction *action)
151 gchar *action_label = NULL;
153 g_object_get (G_OBJECT (action), "label", &action_label, NULL);
154 if (action_label && strlen (action_label))
156 gchar *s, *d;
157 s = d = action_label;
158 while (*s)
160 /* FIXME: May break with multibyte chars */
161 if (*s == '_')
162 s++;
163 *d = *s; d++; s++;
165 *d = '\0';
167 else
168 action_label = g_strdup (gtk_action_get_name (action));
169 return action_label;
172 static gchar*
173 get_action_accel_path (GtkAction *action, const gchar *group_name)
175 gchar *accel_path;
176 accel_path = g_strconcat ("<Actions>/", group_name,
177 "/", gtk_action_get_name (action), NULL);
178 return accel_path;
181 static gchar*
182 get_action_accel (GtkAction *action, const gchar *group_name)
184 gchar *accel_path;
185 gchar *accel_name;
186 GtkAccelKey key;
188 accel_path = get_action_accel_path (action, group_name);
189 if ( gtk_accel_map_lookup_entry (accel_path, &key))
190 accel_name = gtk_accelerator_name (key.accel_key, key.accel_mods);
191 else
192 accel_name = strdup ("");
193 g_free (accel_path);
194 return accel_name;
197 static void
198 accel_edited_callback (GtkCellRendererText *cell,
199 const char *path_string,
200 guint keyval,
201 GdkModifierType mask,
202 guint hardware_keycode,
203 gpointer data)
205 GtkTreeModel *model = (GtkTreeModel *)data;
206 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
207 GtkTreeIter iter;
208 GtkAction *action;
209 gchar *accel_path, *action_group;
211 gtk_tree_model_get_iter (model, &iter, path);
212 gtk_tree_model_get (model, &iter,
213 COLUMN_DATA, &action,
214 COLUMN_GROUP, &action_group, -1);
216 /* sanity check */
217 if (action == NULL || action_group == NULL)
218 return;
220 accel_path = get_action_accel_path (action, action_group);
221 if (accel_path) {
222 gtk_accel_map_change_entry (accel_path, keyval, mask, TRUE);
223 g_free (accel_path);
226 gtk_tree_path_free (path);
229 static gint
230 iter_compare_func (GtkTreeModel *model, GtkTreeIter *a,
231 GtkTreeIter *b, gpointer user_data)
233 gchar *text_a;
234 gchar *text_b;
235 gint retval = 0;
237 gtk_tree_model_get (model, a, COLUMN_ACTION, &text_a, -1);
238 gtk_tree_model_get (model, b, COLUMN_ACTION, &text_b, -1);
239 if (text_a == NULL && text_b == NULL) retval = 0;
240 else if (text_a == NULL) retval = -1;
241 else if (text_b == NULL) retval = 1;
242 else retval = strcasecmp (text_a, text_b);
244 g_free(text_a);
245 g_free(text_b);
247 return retval;
250 static gboolean
251 binding_from_string (const char *str,
252 guint *accelerator_key,
253 GdkModifierType *accelerator_mods)
255 EggVirtualModifierType virtual;
257 g_return_val_if_fail (accelerator_key != NULL, FALSE);
259 if (str == NULL || (str && strcmp (str, "disabled") == 0))
261 *accelerator_key = 0;
262 *accelerator_mods = 0;
263 return TRUE;
266 if (!egg_accelerator_parse_virtual (str, accelerator_key, &virtual))
267 return FALSE;
269 egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_default (),
270 virtual,
271 accelerator_mods);
273 /* Be sure the GTK accelerator system will be able to handle this
274 * accelerator. Be sure to allow no-accelerator accels like F1.
276 if ((*accelerator_mods & gtk_accelerator_get_default_mod_mask ()) == 0 &&
277 *accelerator_mods != 0)
278 return FALSE;
280 if (*accelerator_key == 0)
281 return FALSE;
282 else
283 return TRUE;
286 static void
287 accel_set_func (GtkTreeViewColumn *tree_column,
288 GtkCellRenderer *cell,
289 GtkTreeModel *model,
290 GtkTreeIter *iter,
291 gpointer data)
293 GtkAction *action;
294 gchar *accel_name;
295 gchar *group_name;
296 guint keyval;
297 GdkModifierType keymods;
299 gtk_tree_model_get (model, iter,
300 COLUMN_DATA, &action,
301 COLUMN_GROUP, &group_name, -1);
302 if (action == NULL)
303 g_object_set (G_OBJECT (cell), "visible", FALSE, NULL);
304 else
306 accel_name = get_action_accel (action, group_name);
307 if (binding_from_string (accel_name, &keyval, &keymods))
309 g_object_set (G_OBJECT (cell), "visible", TRUE,
310 "accel_key", keyval,
311 "accel_mask", keymods, NULL);
313 else
314 g_object_set (G_OBJECT (cell), "visible", TRUE,
315 "accel_key", 0,
316 "accel_mask", 0, NULL);
317 g_free (accel_name);
321 static void anjuta_ui_class_init (AnjutaUIClass *class);
322 static void anjuta_ui_instance_init (AnjutaUI *ui);
324 GNOME_CLASS_BOILERPLATE (AnjutaUI, anjuta_ui,
325 GtkUIManager, GTK_TYPE_UI_MANAGER);
327 static void
328 anjuta_ui_dispose (GObject *obj)
330 AnjutaUI *ui = ANJUTA_UI (obj);
332 if (ui->priv->model) {
333 /* This will also release the refs on actions.
334 * Clear is necessary because following unref() might not actually
335 * finalize the model. It basically ensures all refs on actions
336 * are released irrespective of whether the model is finalized
337 * or not.
339 gtk_tree_store_clear (GTK_TREE_STORE (ui->priv->model));
341 g_object_unref (G_OBJECT (ui->priv->model));
342 ui->priv->model = NULL;
344 if (ui->priv->customizable_actions_hash)
346 /* This will also release the refs on all action groups */
347 g_hash_table_destroy (ui->priv->customizable_actions_hash);
348 ui->priv->customizable_actions_hash = NULL;
350 if (ui->priv->uncustomizable_actions_hash)
352 /* This will also release the refs on all action groups */
353 g_hash_table_destroy (ui->priv->uncustomizable_actions_hash);
354 ui->priv->uncustomizable_actions_hash = NULL;
356 if (ui->priv->icon_factory) {
357 g_object_unref (G_OBJECT (ui->priv->icon_factory));
358 ui->priv->icon_factory = NULL;
360 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
363 static void
364 anjuta_ui_finalize (GObject *obj)
366 AnjutaUI *ui = ANJUTA_UI (obj);
367 g_free (ui->priv);
368 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
371 static void
372 anjuta_ui_class_init (AnjutaUIClass *class)
374 GObjectClass *object_class = G_OBJECT_CLASS (class);
376 parent_class = g_type_class_peek_parent (class);
378 object_class->dispose = anjuta_ui_dispose;
379 object_class->finalize = anjuta_ui_finalize;
382 static void
383 anjuta_ui_instance_init (AnjutaUI *ui)
385 GtkTreeStore *store;
387 /* Initialize member data */
388 ui->priv = g_new0 (AnjutaUIPrivate, 1);
389 ui->priv->customizable_actions_hash =
390 g_hash_table_new_full (g_str_hash,
391 g_str_equal,
392 (GDestroyNotify) g_free,
393 NULL);
394 ui->priv->uncustomizable_actions_hash =
395 g_hash_table_new_full (g_str_hash,
396 g_str_equal,
397 (GDestroyNotify) g_free,
398 NULL);
399 /* Create Icon factory */
400 ui->priv->icon_factory = gtk_icon_factory_new ();
401 gtk_icon_factory_add_default (ui->priv->icon_factory);
403 /* Create Accel editor model */
404 store = gtk_tree_store_new (N_COLUMNS,
405 GDK_TYPE_PIXBUF,
406 G_TYPE_STRING,
407 G_TYPE_BOOLEAN,
408 G_TYPE_BOOLEAN,
409 G_TYPE_OBJECT,
410 G_TYPE_STRING);
411 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(store), COLUMN_ACTION,
412 iter_compare_func, NULL, NULL);
413 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
414 COLUMN_ACTION, GTK_SORT_ASCENDING);
416 /* unreferenced in dispose() method. */
417 ui->priv->model = GTK_TREE_MODEL (store);
421 * anjuta_ui_new:
423 * Creates a new instance of #AnjutaUI.
425 * Return value: A #AnjutaUI object
427 AnjutaUI *
428 anjuta_ui_new (void)
430 return g_object_new (ANJUTA_TYPE_UI, NULL);
434 * anjuta_ui_add_action_group_entries:
435 * @ui: A #AnjutaUI object.
436 * @action_group_name: Untranslated name of the action group.
437 * @action_group_label: Translated label of the action group.
438 * @entries: An array of action entries.
439 * @num_entries: Number of elements in the action entries array.
440 * @can_customize: If true the actions are customizable by user.
441 * @translation_domain: The translation domain used to translated the entries.
442 * It is usually the GETTEXT_PACKAGE macro in a project.
443 * @user_data: User data to pass to action objects. This is the data that
444 * will come as user_data in "activate" signal of the actions.
446 * #GtkAction objects are created from the #GtkActionEntry structures and
447 * added to the UI Manager. "activate" signal of #GtkAction is connected for
448 * all the action objects using the callback in the entry structure and the
449 * @user_data passed here.
451 * This group of actions are registered with the name @action_group_name
452 * in #AnjutaUI. A #GtkAction object from this action group can be later
453 * retrieved by anjuta_ui_get_action() using @action_group_name and action name.
454 * @action_group_label is used as the display name for the action group in
455 * UI manager dialog where action shortcuts are configured.
457 * Return value: A #GtkActionGroup object holding all the action objects.
459 GtkActionGroup*
460 anjuta_ui_add_action_group_entries (AnjutaUI *ui,
461 const gchar *action_group_name,
462 const gchar *action_group_label,
463 GtkActionEntry *entries,
464 gint num_entries,
465 const gchar *translation_domain,
466 gboolean can_customize,
467 gpointer user_data)
469 GtkActionGroup *action_group;
471 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
472 g_return_val_if_fail (action_group_name != NULL, NULL);
473 g_return_val_if_fail (action_group_name != NULL, NULL);
475 action_group = gtk_action_group_new (action_group_name);
477 gtk_action_group_set_translation_domain (action_group, translation_domain);
478 gtk_action_group_add_actions (action_group, entries, num_entries,
479 user_data);
480 anjuta_ui_add_action_group (ui, action_group_name,
481 action_group_label, action_group,
482 can_customize);
483 return action_group;
487 * anjuta_ui_add_toggle_action_group_entries:
488 * @ui: A #AnjutaUI object.
489 * @action_group_name: Untranslated name of the action group.
490 * @action_group_label: Translated label of the action group.
491 * @entries: An array of action entries.
492 * @num_entries: Number of elements in the action entries array.
493 * @translation_domain: The translation domain used to translated the entries.
494 * It is usually the GETTEXT_PACKAGE macro in a project.
495 * @user_data: User data to pass to action objects. This is the data that
496 * will come as user_data in "activate" signal of the actions.
498 * This is similar to anjuta_ui_add_action_group_entries(), except that
499 * it adds #GtkToggleAction objects after creating them from the @entries.
501 * Return value: A #GtkActionGroup object holding all the action objects.
503 GtkActionGroup*
504 anjuta_ui_add_toggle_action_group_entries (AnjutaUI *ui,
505 const gchar *action_group_name,
506 const gchar *action_group_label,
507 GtkToggleActionEntry *entries,
508 gint num_entries,
509 const gchar *translation_domain,
510 gboolean can_customize,
511 gpointer user_data)
513 GtkActionGroup *action_group;
515 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
516 g_return_val_if_fail (action_group_name != NULL, NULL);
517 g_return_val_if_fail (action_group_name != NULL, NULL);
519 action_group = gtk_action_group_new (action_group_name);
520 gtk_action_group_set_translation_domain (action_group, translation_domain);
521 gtk_action_group_add_toggle_actions (action_group, entries, num_entries,
522 user_data);
523 anjuta_ui_add_action_group (ui, action_group_name,
524 action_group_label, action_group,
525 can_customize);
526 return action_group;
530 * anjuta_ui_add_action_group:
531 * @ui: A #AnjutaUI object.
532 * @action_group_name: Untranslated name of the action group.
533 * @action_group_label: Translated label of the action group.
534 * @action_group: #GtkActionGroup object to add.
536 * This is similar to anjuta_ui_add_action_group_entries(), except that
537 * it adds #GtkActionGroup object @action_group directly. All actions in this
538 * group are automatically registered in #AnjutaUI and can be retrieved
539 * normally with anjuta_ui_get_action().
541 void
542 anjuta_ui_add_action_group (AnjutaUI *ui,
543 const gchar *action_group_name,
544 const gchar *action_group_label,
545 GtkActionGroup *action_group,
546 gboolean can_customize)
548 GList *actions, *l;
549 GtkTreeIter parent;
550 GdkPixbuf *pixbuf;
551 gint n_actions_added = 0;
553 g_return_if_fail (ANJUTA_IS_UI (ui));
554 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
555 g_return_if_fail (action_group_name != NULL);
556 g_return_if_fail (action_group_name != NULL);
558 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), action_group, 0);
560 if (can_customize)
562 g_hash_table_insert (ui->priv->customizable_actions_hash,
563 g_strdup (action_group_name), action_group);
565 else
567 g_hash_table_insert (ui->priv->uncustomizable_actions_hash,
568 g_strdup (action_group_name), action_group);
571 actions = gtk_action_group_list_actions (action_group);
572 gtk_tree_store_append (GTK_TREE_STORE (ui->priv->model),
573 &parent, NULL);
574 pixbuf = NULL;
575 gtk_tree_store_set (GTK_TREE_STORE (ui->priv->model), &parent,
576 COLUMN_PIXBUF, pixbuf,
577 COLUMN_ACTION, action_group_label,
578 COLUMN_GROUP, action_group_name,
579 -1);
580 for (l = actions; l; l = l->next)
582 gchar *action_label;
583 gchar *icon;
584 guint signal_id;
585 gint n_handlers;
586 GtkTreeIter iter;
587 GtkAction *action = l->data;
589 if (!action)
590 continue;
592 signal_id = g_signal_lookup ("activate", GTK_TYPE_ACTION);
593 n_handlers = g_signal_has_handler_pending (action, signal_id,
594 0, TRUE);
595 if (n_handlers == 0)
596 continue; /* The action element is not user configuration */
598 n_actions_added++;
600 gtk_tree_store_append (GTK_TREE_STORE (ui->priv->model),
601 &iter, &parent);
602 action_label = get_action_label (action);
603 g_object_get (G_OBJECT (action), "stock-id", &icon, NULL);
604 if (icon)
606 GtkWidget *dummy = gtk_label_new ("Dummy");
607 g_object_ref_sink(G_OBJECT(dummy));
608 pixbuf = gtk_widget_render_icon (dummy, icon,
609 GTK_ICON_SIZE_MENU, NULL);
610 if (pixbuf)
612 gtk_tree_store_set (GTK_TREE_STORE (ui->priv->model), &iter,
613 COLUMN_PIXBUF, pixbuf,
614 COLUMN_ACTION, action_label,
615 COLUMN_VISIBLE, gtk_action_get_visible (action),
616 COLUMN_SENSITIVE, gtk_action_get_sensitive(action),
617 COLUMN_DATA, action,
618 COLUMN_GROUP, action_group_name,
619 -1);
620 g_object_unref (G_OBJECT (pixbuf));
622 g_object_unref (dummy);
623 g_free (icon);
625 else
627 gtk_tree_store_set (GTK_TREE_STORE (ui->priv->model), &iter,
628 COLUMN_ACTION, action_label,
629 COLUMN_VISIBLE, gtk_action_get_visible (action),
630 COLUMN_SENSITIVE, gtk_action_get_sensitive (action),
631 COLUMN_DATA, action,
632 COLUMN_GROUP, action_group_name,
633 -1);
635 g_free (action_label);
638 g_list_free(actions);
640 /* If there are no actions in the group, removed the group node */
641 if (n_actions_added == 0)
642 gtk_tree_store_remove (GTK_TREE_STORE (ui->priv->model),
643 &parent);
646 static gboolean
647 on_action_group_remove_hash (gpointer key, gpointer value, gpointer data)
649 if (data == value)
650 return TRUE;
651 else
652 return FALSE;
656 * anjuta_ui_remove_action_group:
657 * @ui: A #AnjutaUI object
658 * @action_group: #GtkActionGroup object to remove.
660 * Removes a previous added action group. All actions in this group are
661 * also unregistered from UI manager.
663 void
664 anjuta_ui_remove_action_group (AnjutaUI *ui, GtkActionGroup *action_group)
666 GtkTreeModel *model;
667 GtkTreeIter iter;
668 gboolean valid;
670 g_return_if_fail (ANJUTA_IS_UI (ui));
672 const gchar *name;
673 name = gtk_action_group_get_name (action_group);
674 model = ui->priv->model;
675 valid = gtk_tree_model_get_iter_first (model, &iter);
676 while (valid)
678 gchar *group;
679 const gchar *group_name;
681 gtk_tree_model_get (model, &iter, COLUMN_GROUP, &group, -1);
682 group_name = gtk_action_group_get_name (GTK_ACTION_GROUP (action_group));
684 if (group_name == NULL || group == NULL)
686 valid = gtk_tree_model_iter_next (model, &iter);
687 continue;
689 if (strcmp (group_name, group) == 0)
691 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
693 else
694 valid = gtk_tree_model_iter_next (model, &iter);
695 g_free(group);
697 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (ui), action_group);
699 g_hash_table_foreach_remove (ui->priv->customizable_actions_hash,
700 on_action_group_remove_hash, action_group);
701 g_hash_table_foreach_remove (ui->priv->uncustomizable_actions_hash,
702 on_action_group_remove_hash, action_group);
706 * anjuta_ui_get_action:
707 * @ui: This #AnjutaUI object
708 * @action_group_name: Group name.
709 * @action_name: Action name.
710 * returns: A #GtkAction object
712 * Returns the action object with the name @action_name in @action_group_name.
713 * Note that it will be only sucessully returned if the group has been added
714 * using methods in #AnjutaUI.
716 GtkAction*
717 anjuta_ui_get_action (AnjutaUI *ui, const gchar *action_group_name,
718 const gchar *action_name)
720 GtkActionGroup *action_group;
721 GtkAction *action;
723 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
725 action_group = g_hash_table_lookup (ui->priv->customizable_actions_hash,
726 action_group_name);
727 if (!action_group)
729 action_group = g_hash_table_lookup (ui->priv->uncustomizable_actions_hash,
730 action_group_name);
732 if (GTK_IS_ACTION_GROUP (action_group) == FALSE)
734 g_warning ("Unable to find action group \"%s\"", action_group_name);
735 return NULL;
737 action = gtk_action_group_get_action (action_group, action_name);
738 if (GTK_IS_ACTION (action))
739 return action;
740 g_warning ("Unable to find action \"%s\" in group \"%s\"",
741 action_name, action_group_name);
742 return NULL;
746 * anjuta_ui_activate_action_by_path:
747 * @ui: This #AnjutaUI object
748 * @action_path: Path of the action in the form "GroupName/ActionName"
750 * Activates the action represented by @action_path. The path is in the form
751 * "ActionGroupName/ActionName". Note that it will only work if the group has
752 * been added using methods in #AnjutaUI.
754 void
755 anjuta_ui_activate_action_by_path (AnjutaUI *ui, const gchar *action_path)
757 const gchar *action_group_name;
758 const gchar *action_name;
759 GtkAction *action;
760 gchar **strv;
762 g_return_if_fail (ANJUTA_IS_UI (ui));
763 g_return_if_fail (action_path != NULL);
765 strv = g_strsplit (action_path, "/", 2);
766 action_group_name = strv[0];
767 action_name = strv[1];
769 g_return_if_fail (action_group_name != NULL && action_name != NULL);
771 action = anjuta_ui_get_action (ui, action_group_name, action_name);
772 if (action)
773 gtk_action_activate (action);
774 g_strfreev (strv);
778 * anjuta_ui_activate_action_by_group:
779 * @ui: This #AnjutaUI object
780 * @action_group: Action group.
781 * @action_name: Action name.
783 * Activates the action @action_name in the #GtkActionGroup @action_group.
784 * "ActionGroupName/ActionName". Note that it will only work if the group has
785 * been added using methods in #AnjutaUI.
787 void
788 anjuta_ui_activate_action_by_group (AnjutaUI *ui, GtkActionGroup *action_group,
789 const gchar *action_name)
791 GtkAction *action;
793 g_return_if_fail (ANJUTA_IS_UI (ui));
794 g_return_if_fail (action_group != NULL && action_name != NULL);
796 action = gtk_action_group_get_action (action_group, action_name);
797 if (GTK_IS_ACTION (action))
798 gtk_action_activate (action);
802 * anjuta_ui_merge:
803 * @ui: A #AnjutaUI object.
804 * @ui_filename: UI file to merge into UI manager.
806 * Merges XML UI definition in @ui_filename. UI elements defined in the xml
807 * are merged with existing UI elements in UI manager. The format of the
808 * file content is the standard XML UI definition tree. For more detail,
809 * read the documentation for #GtkUIManager.
811 * Return value: Integer merge ID
813 gint
814 anjuta_ui_merge (AnjutaUI *ui, const gchar *ui_filename)
816 gint id;
817 GError *err = NULL;
819 g_return_val_if_fail (ANJUTA_IS_UI (ui), -1);
820 g_return_val_if_fail (ui_filename != NULL, -1);
821 id = gtk_ui_manager_add_ui_from_file(GTK_UI_MANAGER (ui),
822 ui_filename, &err);
823 #ifdef DEBUG
825 gchar *basename = g_path_get_basename (ui_filename);
826 DEBUG_PRINT ("merged [%d] %s", id, basename);
827 g_free(basename);
829 #endif
830 if (err != NULL)
831 g_warning ("Could not merge [%s]: %s", ui_filename, err->message);
832 return id;
836 * anjuta_ui_unmerge:
837 * @ui: A #AnjutaUI object.
838 * @id: Merge ID returned by anjuta_ui_merge().
840 * Unmerges UI with the ID value @id (returned by anjuta_ui_merge() when
841 * it was merged. For more detail, read the documentation for #GtkUIManager.
843 void
844 anjuta_ui_unmerge (AnjutaUI *ui, gint id)
846 /* DEBUG_PRINT ("Menu unmerging %d", id); */
847 g_return_if_fail (ANJUTA_IS_UI (ui));
848 gtk_ui_manager_remove_ui(GTK_UI_MANAGER (ui), id);
852 * anjuta_ui_get_accel_group:
853 * @ui: A #AnjutaUI object.
854 * returns: A #GtkAccelGroup object.
856 * Returns the #GtkAccelGroup object associated with this UI manager.
858 GtkAccelGroup*
859 anjuta_ui_get_accel_group (AnjutaUI *ui)
861 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
862 return gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (ui));
866 * anjuta_ui_get_accel_editor:
867 * @ui: A #AnjutaUI object.
868 * returns: A #GtkWidget object.
870 * Creates an accel editor widget and returns it. It should be added to
871 * container and displayed to users.
873 * Returns a #GtkWidget containing the editor.
875 GtkWidget *
876 anjuta_ui_get_accel_editor (AnjutaUI *ui)
878 GtkWidget *tree_view, *sw;
879 GtkTreeStore *store;
880 GtkTreeViewColumn *column;
881 GtkCellRenderer *renderer;
883 store = GTK_TREE_STORE (ui->priv->model);
885 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
886 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
888 /* Columns */
889 column = gtk_tree_view_column_new ();
890 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
891 gtk_tree_view_column_set_title (column, _("Action"));
893 renderer = gtk_cell_renderer_pixbuf_new ();
894 gtk_tree_view_column_pack_start (column, renderer, FALSE);
895 gtk_tree_view_column_add_attribute (column, renderer, "pixbuf",
896 COLUMN_PIXBUF);
898 renderer = gtk_cell_renderer_text_new ();
899 gtk_tree_view_column_pack_start (column, renderer, TRUE);
900 gtk_tree_view_column_add_attribute (column, renderer, "text",
901 COLUMN_ACTION);
902 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
903 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree_view), column);
904 gtk_tree_view_column_set_sort_column_id (column, 0);
906 renderer = gtk_cell_renderer_toggle_new ();
907 g_signal_connect (G_OBJECT (renderer), "toggled",
908 G_CALLBACK (visibility_toggled), store);
909 column = gtk_tree_view_column_new_with_attributes (_("Visible"),
910 renderer,
911 "active",
912 COLUMN_VISIBLE,
913 NULL);
914 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
915 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
916 #if 0
917 renderer = gtk_cell_renderer_toggle_new ();
918 g_signal_connect (G_OBJECT (renderer), "toggled",
919 G_CALLBACK (sensitivity_toggled), store);
920 column = gtk_tree_view_column_new_with_attributes (_("Sensitive"),
921 renderer,
922 "active",
923 COLUMN_SENSITIVE,
924 NULL);
925 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
926 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
927 #endif
928 column = gtk_tree_view_column_new ();
929 gtk_tree_view_column_set_title (column, _("Shortcut"));
930 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
931 renderer = g_object_new (EGG_TYPE_CELL_RENDERER_KEYS,
932 "editable", TRUE,
933 "accel_mode", EGG_CELL_RENDERER_KEYS_MODE_GTK,
934 NULL);
935 g_signal_connect (G_OBJECT (renderer), "keys_edited",
936 G_CALLBACK (accel_edited_callback),
937 store);
938 g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
939 gtk_tree_view_column_pack_start (column, renderer, TRUE);
940 gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
941 gtk_tree_view_column_set_sort_column_id (column, COLUMN_DATA);
942 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
944 sw = gtk_scrolled_window_new (NULL, NULL);
945 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
946 GTK_POLICY_AUTOMATIC,
947 GTK_POLICY_AUTOMATIC);
948 gtk_container_add (GTK_CONTAINER (sw), tree_view);
949 gtk_widget_show_all (sw);
950 return sw;
954 * anjuta_ui_get_icon_factory:
955 * @ui: A #AnjutaUI object
957 * This returns the IconFactory object. All icons should be registered using
958 * this icon factory. Read the documentation for #GtkIconFactory on how to
959 * use it.
961 * Return value: The #GtkIconFactory object used by it
963 GtkIconFactory*
964 anjuta_ui_get_icon_factory (AnjutaUI *ui)
966 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
967 return ui->priv->icon_factory;
971 * anjuta_ui_dump_tree:
972 * @ui: A #AnjutaUI object.
974 * Dumps the current UI XML tree in STDOUT. Useful for debugging.
976 void
977 anjuta_ui_dump_tree (AnjutaUI *ui)
979 gchar *ui_str;
981 g_return_if_fail (ANJUTA_IS_UI(ui));
983 gtk_ui_manager_ensure_update (GTK_UI_MANAGER (ui));
984 ui_str = gtk_ui_manager_get_ui (GTK_UI_MANAGER (ui));
985 /* DEBUG_PRINT ("%s", ui_str); */
986 g_free (ui_str);