Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / libanjuta / anjuta-ui.c
blobfec9448a2f57a9715b04f04cab231fee88fcf117
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>
78 #include <gtk/gtkcellrendereraccel.h>
80 #include "resources.h"
81 #include "anjuta-ui.h"
82 #include "anjuta-utils.h"
83 #include "anjuta-debug.h"
85 struct _AnjutaUIPrivate {
86 GtkIconFactory *icon_factory;
87 GtkTreeModel *model;
88 GHashTable *customizable_actions_hash;
89 GHashTable *uncustomizable_actions_hash;
92 enum {
93 COLUMN_PIXBUF,
94 COLUMN_ACTION_LABEL,
95 COLUMN_VISIBLE,
96 COLUMN_SENSITIVE,
97 COLUMN_ACTION,
98 COLUMN_GROUP,
99 N_COLUMNS
102 #if 0
103 static void
104 sensitivity_toggled (GtkCellRendererToggle *cell,
105 const gchar *path_str, GtkTreeModel *model)
107 GtkTreePath *path;
108 GtkTreeIter iter;
109 GtkAction *action;
110 gboolean sensitive;
112 path = gtk_tree_path_new_from_string (path_str);
113 gtk_tree_model_get_iter (model, &iter, path);
115 gtk_tree_model_get (model, &iter,
116 COLUMN_SENSITIVE, &sensitive,
117 COLUMN_ACTION, &action, -1);
118 g_object_set (G_OBJECT (action), "sensitive", !sensitive, NULL);
119 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
120 COLUMN_SENSITIVE, !sensitive, -1);
121 gtk_tree_path_free (path);
123 #endif
125 static void
126 visibility_toggled (GtkCellRendererToggle *cell,
127 const gchar *path_str, GtkTreeModel *model)
129 GtkTreePath *path;
130 GtkTreeIter iter;
131 GtkAction *action;
132 gboolean visible;
134 path = gtk_tree_path_new_from_string (path_str);
135 gtk_tree_model_get_iter (model, &iter, path);
137 gtk_tree_model_get (model, &iter,
138 COLUMN_VISIBLE, &visible,
139 COLUMN_ACTION, &action, -1);
140 g_object_set (G_OBJECT (action), "visible", !visible, NULL);
141 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
142 COLUMN_VISIBLE, !visible, -1);
143 gtk_tree_path_free (path);
146 static gchar*
147 get_action_label (GtkAction *action)
149 gchar *action_label = NULL;
151 g_object_get (G_OBJECT (action), "label", &action_label, NULL);
152 if (action_label && strlen (action_label))
154 gchar *s, *d;
155 s = d = action_label;
156 while (*s)
158 /* FIXME: May break with multibyte chars */
159 if (*s == '_')
160 s++;
161 *d = *s; d++; s++;
163 *d = '\0';
165 else
166 action_label = g_strdup (gtk_action_get_name (action));
167 return action_label;
170 static void
171 accel_edited_callback (GtkCellRendererAccel *cell,
172 const char *path_string,
173 guint keyval,
174 GdkModifierType mask,
175 guint hardware_keycode,
176 gpointer data)
178 GtkTreeModel *model = (GtkTreeModel *)data;
179 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
180 GtkTreeIter iter;
181 GtkAction *action;
182 const gchar *accel_path;
184 gtk_tree_model_get_iter (model, &iter, path);
185 gtk_tree_model_get (model, &iter,
186 COLUMN_ACTION, &action, -1);
188 /* sanity check */
189 if (action == NULL)
190 return;
192 accel_path = gtk_action_get_accel_path (action);
193 if (accel_path) {
194 gtk_accel_map_change_entry (accel_path, keyval, mask, TRUE);
197 gtk_tree_path_free (path);
200 static void
201 accel_cleared_callback (GtkCellRendererAccel *cell,
202 const char *path_string,
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 const gchar *accel_path;
212 gtk_tree_model_get_iter (model, &iter, path);
213 gtk_tree_model_get (model, &iter,
214 COLUMN_ACTION, &action, -1);
216 /* sanity check */
217 if (action == NULL)
218 return;
220 accel_path = gtk_action_get_accel_path (action);
221 if (accel_path) {
222 gtk_accel_map_change_entry (accel_path, 0, 0, TRUE);
225 gtk_tree_path_free (path);
230 static gint
231 iter_compare_func (GtkTreeModel *model, GtkTreeIter *a,
232 GtkTreeIter *b, gpointer user_data)
234 gchar *text_a;
235 gchar *text_b;
236 gint retval = 0;
238 gtk_tree_model_get (model, a, COLUMN_ACTION_LABEL, &text_a, -1);
239 gtk_tree_model_get (model, b, COLUMN_ACTION_LABEL, &text_b, -1);
240 if (text_a == NULL && text_b == NULL) retval = 0;
241 else if (text_a == NULL) retval = -1;
242 else if (text_b == NULL) retval = 1;
243 else retval = strcasecmp (text_a, text_b);
245 g_free(text_a);
246 g_free(text_b);
248 return retval;
251 static void
252 accel_set_func (GtkTreeViewColumn *tree_column,
253 GtkCellRenderer *cell,
254 GtkTreeModel *model,
255 GtkTreeIter *iter,
256 gpointer data)
258 GtkAction *action;
259 const gchar *accel_path;
260 GtkAccelKey key;
262 gtk_tree_model_get (model, iter,
263 COLUMN_ACTION, &action, -1);
264 if (action == NULL)
265 g_object_set (G_OBJECT (cell), "visible", FALSE, NULL);
266 else
268 if ((accel_path = gtk_action_get_accel_path (action)))
270 if (gtk_accel_map_lookup_entry (accel_path, &key))
272 g_object_set (G_OBJECT (cell), "visible", TRUE,
273 "accel-key", key.accel_key,
274 "accel-mods", key.accel_mods, NULL);
276 else
277 g_object_set (G_OBJECT (cell), "visible", TRUE,
278 "accel-key", 0,
279 "accel-mods", 0, NULL);
284 G_DEFINE_TYPE(AnjutaUI, anjuta_ui, GTK_TYPE_UI_MANAGER)
286 static void
287 anjuta_ui_dispose (GObject *obj)
289 AnjutaUI *ui = ANJUTA_UI (obj);
291 if (ui->priv->model) {
292 /* This will also release the refs on actions.
293 * Clear is necessary because following unref() might not actually
294 * finalize the model. It basically ensures all refs on actions
295 * are released irrespective of whether the model is finalized
296 * or not.
298 gtk_tree_store_clear (GTK_TREE_STORE (ui->priv->model));
300 g_object_unref (G_OBJECT (ui->priv->model));
301 ui->priv->model = NULL;
303 if (ui->priv->customizable_actions_hash)
305 /* This will also release the refs on all action groups */
306 g_hash_table_destroy (ui->priv->customizable_actions_hash);
307 ui->priv->customizable_actions_hash = NULL;
309 if (ui->priv->uncustomizable_actions_hash)
311 /* This will also release the refs on all action groups */
312 g_hash_table_destroy (ui->priv->uncustomizable_actions_hash);
313 ui->priv->uncustomizable_actions_hash = NULL;
315 if (ui->priv->icon_factory) {
316 g_object_unref (G_OBJECT (ui->priv->icon_factory));
317 ui->priv->icon_factory = NULL;
319 G_OBJECT_CLASS (anjuta_ui_parent_class)->dispose (obj);
322 static void
323 anjuta_ui_finalize (GObject *obj)
325 AnjutaUI *ui = ANJUTA_UI (obj);
326 g_free (ui->priv);
327 G_OBJECT_CLASS (anjuta_ui_parent_class)->finalize (obj);
330 static void
331 anjuta_ui_class_init (AnjutaUIClass *class)
333 GObjectClass *object_class = G_OBJECT_CLASS (class);
335 object_class->dispose = anjuta_ui_dispose;
336 object_class->finalize = anjuta_ui_finalize;
339 static void
340 anjuta_ui_init (AnjutaUI *ui)
342 GtkTreeStore *store;
344 /* Initialize member data */
345 ui->priv = g_new0 (AnjutaUIPrivate, 1);
346 ui->priv->customizable_actions_hash =
347 g_hash_table_new_full (g_str_hash,
348 g_str_equal,
349 (GDestroyNotify) g_free,
350 NULL);
351 ui->priv->uncustomizable_actions_hash =
352 g_hash_table_new_full (g_str_hash,
353 g_str_equal,
354 (GDestroyNotify) g_free,
355 NULL);
356 /* Create Icon factory */
357 ui->priv->icon_factory = gtk_icon_factory_new ();
358 gtk_icon_factory_add_default (ui->priv->icon_factory);
360 /* Create Accel editor model */
361 store = gtk_tree_store_new (N_COLUMNS,
362 GDK_TYPE_PIXBUF,
363 G_TYPE_STRING,
364 G_TYPE_BOOLEAN,
365 G_TYPE_BOOLEAN,
366 G_TYPE_OBJECT,
367 G_TYPE_STRING);
368 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(store), COLUMN_ACTION_LABEL,
369 iter_compare_func, NULL, NULL);
370 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
371 COLUMN_ACTION_LABEL, GTK_SORT_ASCENDING);
373 /* unreferenced in dispose() method. */
374 ui->priv->model = GTK_TREE_MODEL (store);
378 * anjuta_ui_new:
380 * Creates a new instance of #AnjutaUI.
382 * Return value: A #AnjutaUI object
384 AnjutaUI *
385 anjuta_ui_new (void)
387 return g_object_new (ANJUTA_TYPE_UI, NULL);
391 * anjuta_ui_add_action_group_entries:
392 * @ui: A #AnjutaUI object.
393 * @action_group_name: Untranslated name of the action group.
394 * @action_group_label: Translated label of the action group.
395 * @entries: An array of action entries.
396 * @num_entries: Number of elements in the action entries array.
397 * @can_customize: If true the actions are customizable by user.
398 * @translation_domain: The translation domain used to translated the entries.
399 * It is usually the GETTEXT_PACKAGE macro in a project.
400 * @user_data: User data to pass to action objects. This is the data that
401 * will come as user_data in "activate" signal of the actions.
403 * #GtkAction objects are created from the #GtkActionEntry structures and
404 * added to the UI Manager. "activate" signal of #GtkAction is connected for
405 * all the action objects using the callback in the entry structure and the
406 * @user_data passed here.
408 * This group of actions are registered with the name @action_group_name
409 * in #AnjutaUI. A #GtkAction object from this action group can be later
410 * retrieved by anjuta_ui_get_action() using @action_group_name and action name.
411 * @action_group_label is used as the display name for the action group in
412 * UI manager dialog where action shortcuts are configured.
414 * Return value: A #GtkActionGroup object holding all the action objects.
416 GtkActionGroup*
417 anjuta_ui_add_action_group_entries (AnjutaUI *ui,
418 const gchar *action_group_name,
419 const gchar *action_group_label,
420 GtkActionEntry *entries,
421 gint num_entries,
422 const gchar *translation_domain,
423 gboolean can_customize,
424 gpointer user_data)
426 GtkActionGroup *action_group;
428 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
429 g_return_val_if_fail (action_group_name != NULL, NULL);
430 g_return_val_if_fail (action_group_name != NULL, NULL);
432 action_group = gtk_action_group_new (action_group_name);
434 gtk_action_group_set_translation_domain (action_group, translation_domain);
435 gtk_action_group_add_actions (action_group, entries, num_entries,
436 user_data);
437 anjuta_ui_add_action_group (ui, action_group_name,
438 action_group_label, action_group,
439 can_customize);
440 return action_group;
444 * anjuta_ui_add_toggle_action_group_entries:
445 * @ui: A #AnjutaUI object.
446 * @action_group_name: Untranslated name of the action group.
447 * @action_group_label: Translated label of the action group.
448 * @entries: An array of action entries.
449 * @num_entries: Number of elements in the action entries array.
450 * @translation_domain: The translation domain used to translated the entries.
451 * It is usually the GETTEXT_PACKAGE macro in a project.
452 * @user_data: User data to pass to action objects. This is the data that
453 * will come as user_data in "activate" signal of the actions.
455 * This is similar to anjuta_ui_add_action_group_entries(), except that
456 * it adds #GtkToggleAction objects after creating them from the @entries.
458 * Return value: A #GtkActionGroup object holding all the action objects.
460 GtkActionGroup*
461 anjuta_ui_add_toggle_action_group_entries (AnjutaUI *ui,
462 const gchar *action_group_name,
463 const gchar *action_group_label,
464 GtkToggleActionEntry *entries,
465 gint num_entries,
466 const gchar *translation_domain,
467 gboolean can_customize,
468 gpointer user_data)
470 GtkActionGroup *action_group;
472 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
473 g_return_val_if_fail (action_group_name != NULL, NULL);
474 g_return_val_if_fail (action_group_name != NULL, NULL);
476 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_toggle_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_action_group:
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 * @action_group: #GtkActionGroup object to add.
493 * This is similar to anjuta_ui_add_action_group_entries(), except that
494 * it adds #GtkActionGroup object @action_group directly. All actions in this
495 * group are automatically registered in #AnjutaUI and can be retrieved
496 * normally with anjuta_ui_get_action().
498 void
499 anjuta_ui_add_action_group (AnjutaUI *ui,
500 const gchar *action_group_name,
501 const gchar *action_group_label,
502 GtkActionGroup *action_group,
503 gboolean can_customize)
505 GList *actions, *l;
506 GtkTreeIter parent;
507 GdkPixbuf *pixbuf;
508 gint n_actions_added = 0;
510 g_return_if_fail (ANJUTA_IS_UI (ui));
511 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
512 g_return_if_fail (action_group_name != NULL);
513 g_return_if_fail (action_group_name != NULL);
515 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), action_group, 0);
517 if (can_customize)
519 g_hash_table_insert (ui->priv->customizable_actions_hash,
520 g_strdup (action_group_name), action_group);
522 else
524 g_hash_table_insert (ui->priv->uncustomizable_actions_hash,
525 g_strdup (action_group_name), action_group);
528 actions = gtk_action_group_list_actions (action_group);
529 gtk_tree_store_append (GTK_TREE_STORE (ui->priv->model),
530 &parent, NULL);
531 pixbuf = NULL;
532 gtk_tree_store_set (GTK_TREE_STORE (ui->priv->model), &parent,
533 COLUMN_PIXBUF, pixbuf,
534 COLUMN_ACTION_LABEL, action_group_label,
535 COLUMN_GROUP, action_group_name,
536 -1);
537 for (l = actions; l; l = l->next)
539 gchar *action_label;
540 gchar *icon;
541 guint signal_id;
542 gint n_handlers;
543 GtkTreeIter iter;
544 GtkAction *action = l->data;
546 if (!action)
547 continue;
549 signal_id = g_signal_lookup ("activate", GTK_TYPE_ACTION);
550 n_handlers = g_signal_has_handler_pending (action, signal_id,
551 0, TRUE);
552 if (n_handlers == 0)
553 continue; /* The action element is not user configuration */
555 n_actions_added++;
557 gtk_tree_store_append (GTK_TREE_STORE (ui->priv->model),
558 &iter, &parent);
559 action_label = get_action_label (action);
560 g_object_get (G_OBJECT (action), "stock-id", &icon, NULL);
561 if (icon)
563 GtkWidget *dummy = gtk_label_new ("Dummy");
564 g_object_ref_sink(G_OBJECT(dummy));
565 pixbuf = gtk_widget_render_icon (dummy, icon,
566 GTK_ICON_SIZE_MENU, NULL);
567 if (pixbuf)
569 gtk_tree_store_set (GTK_TREE_STORE (ui->priv->model), &iter,
570 COLUMN_PIXBUF, pixbuf,
571 COLUMN_ACTION_LABEL, action_label,
572 COLUMN_VISIBLE, gtk_action_get_visible (action),
573 COLUMN_SENSITIVE, gtk_action_get_sensitive(action),
574 COLUMN_ACTION, action,
575 COLUMN_GROUP, action_group_name,
576 -1);
577 g_object_unref (G_OBJECT (pixbuf));
579 g_object_unref (dummy);
580 g_free (icon);
582 else
584 gtk_tree_store_set (GTK_TREE_STORE (ui->priv->model), &iter,
585 COLUMN_ACTION_LABEL, action_label,
586 COLUMN_VISIBLE, gtk_action_get_visible (action),
587 COLUMN_SENSITIVE, gtk_action_get_sensitive (action),
588 COLUMN_ACTION, action,
589 COLUMN_GROUP, action_group_name,
590 -1);
592 g_free (action_label);
595 g_list_free(actions);
597 /* If there are no actions in the group, removed the group node */
598 if (n_actions_added == 0)
599 gtk_tree_store_remove (GTK_TREE_STORE (ui->priv->model),
600 &parent);
603 static gboolean
604 on_action_group_remove_hash (gpointer key, gpointer value, gpointer data)
606 if (data == value)
607 return TRUE;
608 else
609 return FALSE;
613 * anjuta_ui_remove_action_group:
614 * @ui: A #AnjutaUI object
615 * @action_group: #GtkActionGroup object to remove.
617 * Removes a previous added action group. All actions in this group are
618 * also unregistered from UI manager.
620 void
621 anjuta_ui_remove_action_group (AnjutaUI *ui, GtkActionGroup *action_group)
623 GtkTreeModel *model;
624 GtkTreeIter iter;
625 gboolean valid;
627 g_return_if_fail (ANJUTA_IS_UI (ui));
629 const gchar *name;
630 name = gtk_action_group_get_name (action_group);
631 model = ui->priv->model;
632 valid = gtk_tree_model_get_iter_first (model, &iter);
633 while (valid)
635 gchar *group;
636 const gchar *group_name;
638 gtk_tree_model_get (model, &iter, COLUMN_GROUP, &group, -1);
639 group_name = gtk_action_group_get_name (GTK_ACTION_GROUP (action_group));
641 if (group_name == NULL || group == NULL)
643 valid = gtk_tree_model_iter_next (model, &iter);
644 continue;
646 if (strcmp (group_name, group) == 0)
648 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
650 else
651 valid = gtk_tree_model_iter_next (model, &iter);
652 g_free(group);
654 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (ui), action_group);
656 g_hash_table_foreach_remove (ui->priv->customizable_actions_hash,
657 on_action_group_remove_hash, action_group);
658 g_hash_table_foreach_remove (ui->priv->uncustomizable_actions_hash,
659 on_action_group_remove_hash, action_group);
663 * anjuta_ui_get_action:
664 * @ui: This #AnjutaUI object
665 * @action_group_name: Group name.
666 * @action_name: Action name.
667 * returns: A #GtkAction object
669 * Returns the action object with the name @action_name in @action_group_name.
670 * Note that it will be only sucessully returned if the group has been added
671 * using methods in #AnjutaUI.
673 GtkAction*
674 anjuta_ui_get_action (AnjutaUI *ui, const gchar *action_group_name,
675 const gchar *action_name)
677 GtkActionGroup *action_group;
678 GtkAction *action;
680 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
682 action_group = g_hash_table_lookup (ui->priv->customizable_actions_hash,
683 action_group_name);
684 if (!action_group)
686 action_group = g_hash_table_lookup (ui->priv->uncustomizable_actions_hash,
687 action_group_name);
689 if (GTK_IS_ACTION_GROUP (action_group) == FALSE)
691 g_warning ("Unable to find action group \"%s\"", action_group_name);
692 return NULL;
694 action = gtk_action_group_get_action (action_group, action_name);
695 if (GTK_IS_ACTION (action))
696 return action;
697 g_warning ("Unable to find action \"%s\" in group \"%s\"",
698 action_name, action_group_name);
699 return NULL;
703 * anjuta_ui_activate_action_by_path:
704 * @ui: This #AnjutaUI object
705 * @action_path: Path of the action in the form "GroupName/ActionName"
707 * Activates the action represented by @action_path. The path is in the form
708 * "ActionGroupName/ActionName". Note that it will only work if the group has
709 * been added using methods in #AnjutaUI.
711 void
712 anjuta_ui_activate_action_by_path (AnjutaUI *ui, const gchar *action_path)
714 const gchar *action_group_name;
715 const gchar *action_name;
716 GtkAction *action;
717 gchar **strv;
719 g_return_if_fail (ANJUTA_IS_UI (ui));
720 g_return_if_fail (action_path != NULL);
722 strv = g_strsplit (action_path, "/", 2);
723 action_group_name = strv[0];
724 action_name = strv[1];
726 g_return_if_fail (action_group_name != NULL && action_name != NULL);
728 action = anjuta_ui_get_action (ui, action_group_name, action_name);
729 if (action)
730 gtk_action_activate (action);
731 g_strfreev (strv);
735 * anjuta_ui_activate_action_by_group:
736 * @ui: This #AnjutaUI object
737 * @action_group: Action group.
738 * @action_name: Action name.
740 * Activates the action @action_name in the #GtkActionGroup @action_group.
741 * "ActionGroupName/ActionName". Note that it will only work if the group has
742 * been added using methods in #AnjutaUI.
744 void
745 anjuta_ui_activate_action_by_group (AnjutaUI *ui, GtkActionGroup *action_group,
746 const gchar *action_name)
748 GtkAction *action;
750 g_return_if_fail (ANJUTA_IS_UI (ui));
751 g_return_if_fail (action_group != NULL && action_name != NULL);
753 action = gtk_action_group_get_action (action_group, action_name);
754 if (GTK_IS_ACTION (action))
755 gtk_action_activate (action);
759 * anjuta_ui_merge:
760 * @ui: A #AnjutaUI object.
761 * @ui_filename: UI file to merge into UI manager.
763 * Merges XML UI definition in @ui_filename. UI elements defined in the xml
764 * are merged with existing UI elements in UI manager. The format of the
765 * file content is the standard XML UI definition tree. For more detail,
766 * read the documentation for #GtkUIManager.
768 * Return value: Integer merge ID
770 gint
771 anjuta_ui_merge (AnjutaUI *ui, const gchar *ui_filename)
773 gint id;
774 GError *err = NULL;
776 g_return_val_if_fail (ANJUTA_IS_UI (ui), -1);
777 g_return_val_if_fail (ui_filename != NULL, -1);
778 id = gtk_ui_manager_add_ui_from_file(GTK_UI_MANAGER (ui),
779 ui_filename, &err);
780 #ifdef DEBUG
782 gchar *basename = g_path_get_basename (ui_filename);
783 DEBUG_PRINT ("merged [%d] %s", id, basename);
784 g_free(basename);
786 #endif
787 if (err != NULL)
788 g_warning ("Could not merge [%s]: %s", ui_filename, err->message);
789 return id;
793 * anjuta_ui_unmerge:
794 * @ui: A #AnjutaUI object.
795 * @id: Merge ID returned by anjuta_ui_merge().
797 * Unmerges UI with the ID value @id (returned by anjuta_ui_merge() when
798 * it was merged. For more detail, read the documentation for #GtkUIManager.
800 void
801 anjuta_ui_unmerge (AnjutaUI *ui, gint id)
803 /* DEBUG_PRINT ("Menu unmerging %d", id); */
804 g_return_if_fail (ANJUTA_IS_UI (ui));
805 gtk_ui_manager_remove_ui(GTK_UI_MANAGER (ui), id);
809 * anjuta_ui_get_accel_group:
810 * @ui: A #AnjutaUI object.
811 * returns: A #GtkAccelGroup object.
813 * Returns the #GtkAccelGroup object associated with this UI manager.
815 GtkAccelGroup*
816 anjuta_ui_get_accel_group (AnjutaUI *ui)
818 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
819 return gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (ui));
823 * anjuta_ui_get_accel_editor:
824 * @ui: A #AnjutaUI object.
825 * returns: A #GtkWidget object.
827 * Creates an accel editor widget and returns it. It should be added to
828 * container and displayed to users.
830 * Returns a #GtkWidget containing the editor.
832 GtkWidget *
833 anjuta_ui_get_accel_editor (AnjutaUI *ui)
835 GtkWidget *tree_view, *sw;
836 GtkTreeStore *store;
837 GtkTreeViewColumn *column;
838 GtkCellRenderer *renderer;
840 store = GTK_TREE_STORE (ui->priv->model);
842 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
843 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
845 /* Columns */
846 column = gtk_tree_view_column_new ();
847 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
848 gtk_tree_view_column_set_title (column, _("Action"));
850 renderer = gtk_cell_renderer_pixbuf_new ();
851 gtk_tree_view_column_pack_start (column, renderer, FALSE);
852 gtk_tree_view_column_add_attribute (column, renderer, "pixbuf",
853 COLUMN_PIXBUF);
855 renderer = gtk_cell_renderer_text_new ();
856 gtk_tree_view_column_pack_start (column, renderer, TRUE);
857 gtk_tree_view_column_add_attribute (column, renderer, "text",
858 COLUMN_ACTION_LABEL);
859 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
860 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree_view), column);
861 gtk_tree_view_column_set_sort_column_id (column, 0);
863 renderer = gtk_cell_renderer_toggle_new ();
864 g_signal_connect (G_OBJECT (renderer), "toggled",
865 G_CALLBACK (visibility_toggled), store);
866 column = gtk_tree_view_column_new_with_attributes (_("Visible"),
867 renderer,
868 "active",
869 COLUMN_VISIBLE,
870 NULL);
871 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
872 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
873 #if 0
874 renderer = gtk_cell_renderer_toggle_new ();
875 g_signal_connect (G_OBJECT (renderer), "toggled",
876 G_CALLBACK (sensitivity_toggled), store);
877 column = gtk_tree_view_column_new_with_attributes (_("Sensitive"),
878 renderer,
879 "active",
880 COLUMN_SENSITIVE,
881 NULL);
882 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
883 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
884 #endif
885 column = gtk_tree_view_column_new ();
886 gtk_tree_view_column_set_title (column, _("Shortcut"));
887 /* gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); */
888 renderer = g_object_new (GTK_TYPE_CELL_RENDERER_ACCEL,
889 "editable", TRUE,
890 NULL);
891 g_signal_connect (G_OBJECT (renderer), "accel-edited",
892 G_CALLBACK (accel_edited_callback),
893 store);
894 g_signal_connect (G_OBJECT (renderer), "accel-cleared",
895 G_CALLBACK (accel_cleared_callback),
896 store);
897 g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
898 gtk_tree_view_column_pack_start (column, renderer, TRUE);
899 gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
900 gtk_tree_view_column_set_sort_column_id (column, COLUMN_ACTION);
901 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
903 sw = gtk_scrolled_window_new (NULL, NULL);
904 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
905 GTK_POLICY_AUTOMATIC,
906 GTK_POLICY_AUTOMATIC);
907 gtk_container_add (GTK_CONTAINER (sw), tree_view);
908 gtk_widget_show_all (sw);
909 return sw;
913 * anjuta_ui_get_icon_factory:
914 * @ui: A #AnjutaUI object
916 * This returns the IconFactory object. All icons should be registered using
917 * this icon factory. Read the documentation for #GtkIconFactory on how to
918 * use it.
920 * Return value: The #GtkIconFactory object used by it
922 GtkIconFactory*
923 anjuta_ui_get_icon_factory (AnjutaUI *ui)
925 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
926 return ui->priv->icon_factory;
930 * anjuta_ui_dump_tree:
931 * @ui: A #AnjutaUI object.
933 * Dumps the current UI XML tree in STDOUT. Useful for debugging.
935 void
936 anjuta_ui_dump_tree (AnjutaUI *ui)
938 gchar *ui_str;
940 g_return_if_fail (ANJUTA_IS_UI(ui));
942 gtk_ui_manager_ensure_update (GTK_UI_MANAGER (ui));
943 ui_str = gtk_ui_manager_get_ui (GTK_UI_MANAGER (ui));
944 /* DEBUG_PRINT ("%s", ui_str); */
945 g_free (ui_str);
949 * Accels
951 static gchar *
952 anjuta_ui_get_accel_file (void)
954 return anjuta_util_get_user_config_file_path ("anjuta-accels", NULL);
957 void
958 anjuta_ui_load_accels (void)
960 gchar *filename;
962 filename = anjuta_ui_get_accel_file ();
963 if (filename != NULL)
965 gtk_accel_map_load (filename);
966 g_free (filename);
970 void
971 anjuta_ui_save_accels (void)
973 gchar *filename;
975 filename = anjuta_ui_get_accel_file ();
976 if (filename != NULL)
978 gtk_accel_map_save (filename);
979 g_free (filename);