libanjuta: bgo #696984 - Fix function argument name typos in documentation comments
[anjuta.git] / libanjuta / anjuta-ui.c
blob04a67c76f5abdfa406fe6cf50f69643face08c2f
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/gtk.h>
71 #include "resources.h"
72 #include "anjuta-ui.h"
73 #include "anjuta-utils.h"
74 #include "anjuta-debug.h"
76 struct _AnjutaUIPrivate {
77 GtkIconFactory *icon_factory;
78 GtkTreeModel *name_model;
79 GtkTreeModel *accel_model;
80 GHashTable *customizable_actions_hash;
81 GHashTable *uncustomizable_actions_hash;
84 enum {
85 COLUMN_PIXBUF,
86 COLUMN_ACTION_LABEL,
87 COLUMN_VISIBLE,
88 COLUMN_SHOW_VISIBLE,
89 COLUMN_SENSITIVE,
90 COLUMN_ACTION,
91 COLUMN_GROUP,
92 N_COLUMNS
95 static gchar*
96 get_action_label (GtkAction *action)
98 gchar *action_label = NULL;
100 g_object_get (G_OBJECT (action), "label", &action_label, NULL);
101 if (action_label && strlen (action_label))
103 gchar *s, *d;
104 s = d = action_label;
105 while (*s)
107 /* FIXME: May break with multibyte chars */
108 if (*s == '_')
109 s++;
110 *d = *s; d++; s++;
112 *d = '\0';
114 else
115 action_label = g_strdup (gtk_action_get_name (action));
116 return action_label;
119 /* Find action in tree */
120 static gboolean
121 find_action (GtkTreeModel *model, GtkTreeIter *iter, GtkAction *action)
123 GtkTreeIter group;
124 gboolean valid;
126 for (valid = gtk_tree_model_get_iter_first (model, &group);
127 valid;
128 valid = gtk_tree_model_iter_next (model, &group))
130 for (valid = gtk_tree_model_iter_children (model, iter, &group);
131 valid;
132 valid = gtk_tree_model_iter_next (model, iter))
134 GtkAction *child_action;
136 gtk_tree_model_get (model, iter, COLUMN_ACTION, &child_action, -1);
137 g_object_unref (child_action);
138 if (action == child_action) return TRUE;
142 return FALSE;
145 /* Find group in tree starting after sibling or from beginning if sibling is
146 * NULL */
147 static gboolean
148 find_group_after (GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *sibling, const gchar *group_label)
150 gboolean valid;
152 if (sibling == NULL)
154 valid = gtk_tree_model_get_iter_first (model, iter);
156 else
158 *iter = *sibling;
159 valid = gtk_tree_model_iter_next (model, iter);
161 while (valid)
163 gchar *label;
164 gint comp;
166 gtk_tree_model_get (model, iter, COLUMN_ACTION_LABEL, &label, -1);
167 comp = strcmp (label, group_label);
168 g_free (label);
170 if (comp == 0) return TRUE;
172 valid = gtk_tree_model_iter_next (model, iter);
175 return FALSE;
178 /* Find position for new label */
179 static GtkTreeIter *
180 find_sorted_name (GtkTreeModel *model, GtkTreeIter *iter, const gchar *label)
182 gboolean valid;
186 gchar *iter_label;
187 gint comp;
189 gtk_tree_model_get (model, iter, COLUMN_ACTION_LABEL, &iter_label, -1);
191 comp = g_utf8_collate (label, iter_label);
192 g_free (iter_label);
194 if (comp <= 0) return iter;
196 valid = gtk_tree_model_iter_next (model, iter);
197 } while (valid);
199 return NULL;
202 /* Find position for new accel */
203 static gboolean
204 find_sorted_accel (GtkTreeModel *model, GtkTreeIter *iter, GtkAction *action)
206 GtkTreeIter group;
207 gboolean valid;
208 const gchar *accel_path;
209 GtkAccelKey key;
211 accel_path = gtk_action_get_accel_path (action);
212 if ((accel_path == NULL) ||
213 !gtk_accel_map_lookup_entry (accel_path, &key) ||
214 ((key.accel_key == 0) && (key.accel_mods == 0)))
216 /* No accelerator */
217 return FALSE;
220 for (valid = gtk_tree_model_get_iter_first (model, &group);
221 valid;
222 valid = gtk_tree_model_iter_next (model, &group))
224 for (valid = gtk_tree_model_iter_children (model, iter, &group);
225 valid;
226 valid = gtk_tree_model_iter_next (model, iter))
228 GtkAction *child_action;
229 GtkAccelKey child_key;
231 gtk_tree_model_get (model, iter, COLUMN_ACTION, &child_action, -1);
232 accel_path = gtk_action_get_accel_path (child_action);
233 g_object_unref (child_action);
234 if ((accel_path == NULL) ||
235 !gtk_accel_map_lookup_entry (accel_path, &child_key) ||
236 ((child_key.accel_key == 0) && (child_key.accel_mods == 0)))
238 /* No more accelerator and as accelerators are sorted, there is
239 * no need to go further */
240 return TRUE;
243 if ((child_key.accel_key > key.accel_key) ||
244 ((child_key.accel_key == key.accel_key) && (child_key.accel_mods >= key.accel_mods)))
246 /* Find next accelerator */
247 return TRUE;
252 return FALSE;
255 static void
256 insert_sorted_by_accel (GtkTreeModel *model, GtkTreeIter *iter, const gchar *group_label, GtkAction *action)
258 GtkTreeIter next;
259 GtkTreeIter parent;
261 if (find_sorted_accel (model, &next, action))
263 gchar *label;
265 /* Try to set next action in an already existing parent */
266 gtk_tree_model_iter_parent (model, &parent, &next);
267 gtk_tree_model_get (model, &parent, COLUMN_ACTION_LABEL, &label, -1);
268 if (strcmp (label, group_label) == 0)
270 /* Already the right group, just insert action */
271 gtk_tree_store_insert_before (GTK_TREE_STORE (model), iter, &parent, &next);
273 else
275 /* Try to put in the previous group */
276 GtkTreePath *path;
277 gboolean prev;
279 path = gtk_tree_model_get_path (model, &next);
280 prev = gtk_tree_path_prev (path);
281 gtk_tree_path_free (path);
283 if (!prev)
285 path = gtk_tree_model_get_path (model, &parent);
286 if (gtk_tree_path_prev (path))
288 g_free (label);
289 gtk_tree_model_get_iter (model, &parent, path);
290 gtk_tree_model_get (model, &parent, COLUMN_ACTION_LABEL, &label, -1);
291 if (strcmp (label, group_label) != 0)
293 /* Create new parent */
294 next = parent;
295 gtk_tree_store_insert_after (GTK_TREE_STORE (model), &parent, NULL, &next);
298 else
300 next = parent;
301 gtk_tree_store_insert_before (GTK_TREE_STORE (model), &parent, NULL, &next);
303 gtk_tree_path_free (path);
304 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
305 COLUMN_ACTION_LABEL, group_label,
306 COLUMN_SHOW_VISIBLE, FALSE,
307 -1);
309 /* Add action at the end */
310 gtk_tree_store_append (GTK_TREE_STORE (model), iter, &parent);
312 else
314 /* Split parent and add new parent in the middle */
315 GtkTreeIter split;
316 gboolean valid;
318 gtk_tree_store_insert_after (GTK_TREE_STORE (model), &split, NULL, &parent);
319 gtk_tree_store_set (GTK_TREE_STORE (model), &split,
320 COLUMN_ACTION_LABEL, label,
321 COLUMN_SHOW_VISIBLE, FALSE,
322 -1);
326 GtkTreeIter child;
327 GdkPixbuf *pixbuf;
328 gchar *action_label;
329 gboolean visible;
330 gboolean sensitive;
331 GtkAction *action;
332 gpointer action_group;
334 gtk_tree_model_get (model, &next,
335 COLUMN_PIXBUF, &pixbuf,
336 COLUMN_ACTION_LABEL, &action_label,
337 COLUMN_VISIBLE, &visible,
338 COLUMN_SENSITIVE, &sensitive,
339 COLUMN_ACTION, &action,
340 COLUMN_GROUP, &action_group,
341 -1);
342 gtk_tree_store_append (GTK_TREE_STORE (model), &child, &split);
343 gtk_tree_store_set (GTK_TREE_STORE (model), &child,
344 COLUMN_PIXBUF, pixbuf,
345 COLUMN_ACTION_LABEL, action_label,
346 COLUMN_VISIBLE, visible,
347 COLUMN_SHOW_VISIBLE, TRUE,
348 COLUMN_SENSITIVE, sensitive,
349 COLUMN_ACTION, action,
350 COLUMN_GROUP, action_group,
351 -1);
352 if (pixbuf) g_object_unref (pixbuf);
353 if (action) g_object_unref (action);
354 g_free (action_label);
356 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &next);
357 } while (valid);
359 /* Add new parent */
360 gtk_tree_store_insert_before (GTK_TREE_STORE (model), &parent, NULL, &split);
361 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
362 COLUMN_ACTION_LABEL, group_label,
363 COLUMN_SHOW_VISIBLE, FALSE,
364 -1);
366 gtk_tree_store_append (GTK_TREE_STORE (model), iter, &parent);
369 g_free (label);
371 else
373 if (find_group_after (model, &parent, NULL, group_label))
375 GtkTreeIter child;
376 GtkAction *child_action;
377 const gchar *accel_path;
378 GtkAccelKey key;
380 /* Find last group */
381 while (find_group_after (model, &next, &parent, group_label))
383 parent = next;
386 gtk_tree_model_iter_children (model, &child, &parent);
387 gtk_tree_model_get (model, &child, COLUMN_ACTION, &child_action, -1);
389 accel_path = gtk_action_get_accel_path (child_action);
390 g_object_unref (child_action);
391 if ((accel_path != NULL) &&
392 gtk_accel_map_lookup_entry (accel_path, &key) &&
393 ((key.accel_key != 0) || (key.accel_mods != 0)))
395 /* Create new group */
396 gtk_tree_store_append (GTK_TREE_STORE (model), &parent, NULL);
397 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
398 COLUMN_ACTION_LABEL, group_label,
399 COLUMN_SHOW_VISIBLE, FALSE,
400 -1);
404 else
406 /* Create new group */
407 gtk_tree_store_append (GTK_TREE_STORE (model), &parent, NULL);
408 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
409 COLUMN_ACTION_LABEL, group_label,
410 COLUMN_SHOW_VISIBLE, FALSE,
411 -1);
414 /* Append action */
415 gtk_tree_store_append (GTK_TREE_STORE (model), iter, &parent);
419 static void
420 insert_sorted_by_name (GtkTreeModel *model, GtkTreeIter *iter, const gchar *group_label, GtkAction *action)
422 GtkTreeIter parent;
423 GtkTreeIter child;
424 GtkTreeIter *sibling;
425 gchar *label;
427 if (!find_group_after (model, &parent, NULL, group_label))
429 /* Insert group for label */
430 if (gtk_tree_model_get_iter_first (model, &child))
432 sibling = find_sorted_name (model, &child, group_label);
434 else
436 sibling = NULL;
438 gtk_tree_store_insert_before (GTK_TREE_STORE (model), &parent, NULL, sibling);
439 gtk_tree_store_set (GTK_TREE_STORE (model), &parent,
440 COLUMN_ACTION_LABEL, group_label,
441 COLUMN_SHOW_VISIBLE, FALSE,
442 -1);
445 if (gtk_tree_model_iter_children (model, &child, &parent))
447 label = get_action_label (action);
448 sibling = find_sorted_name (model, &child, label);
449 g_free (label);
451 else
453 sibling = NULL;
456 gtk_tree_store_insert_before (GTK_TREE_STORE (model), iter, &parent, sibling);
459 static void
460 fill_action_data (GtkTreeModel *model, GtkTreeIter *iter, GtkAction *action, GtkActionGroup *group)
462 gchar *action_label;
463 gchar *icon;
464 GdkPixbuf *pixbuf = NULL;
465 GtkWidget *dummy = NULL;
467 action_label = get_action_label (action);
468 g_object_get (G_OBJECT (action), "stock-id", &icon, NULL);
469 if (icon != NULL)
471 GtkWidget *dummy = gtk_label_new ("Dummy");
472 g_object_ref_sink(G_OBJECT(dummy));
473 pixbuf = gtk_widget_render_icon (dummy, icon,
474 GTK_ICON_SIZE_MENU, NULL);
476 gtk_tree_store_set (GTK_TREE_STORE (model), iter,
477 COLUMN_PIXBUF, pixbuf,
478 COLUMN_ACTION_LABEL, action_label,
479 COLUMN_VISIBLE, gtk_action_get_visible (action),
480 COLUMN_SHOW_VISIBLE, TRUE,
481 COLUMN_SENSITIVE, gtk_action_get_sensitive (action),
482 COLUMN_ACTION, action,
483 COLUMN_GROUP, group,
484 -1);
485 if (pixbuf != NULL) g_object_unref (G_OBJECT (pixbuf));
486 if (dummy != NULL) g_object_unref (dummy);
487 g_free (icon);
488 g_free (action_label);
491 /* Remove all actions in the action group group */
492 static void
493 remove_action_in_group (GtkTreeModel *model, GtkActionGroup *group)
495 GtkTreeIter parent;
496 gboolean valid;
498 valid = gtk_tree_model_get_iter_first (model, &parent);
499 while (valid)
501 /* Check each action, as a parent can contains actions from different
502 * groups */
503 GtkTreeIter child;
505 valid = gtk_tree_model_iter_children (model, &child, &parent);
506 while (valid)
508 gpointer child_group;
510 gtk_tree_model_get (model, &child, COLUMN_GROUP, &child_group, -1);
512 if (child_group == (gpointer)group)
514 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &child);
516 else
518 valid = gtk_tree_model_iter_next (model, &child);
522 /* if parent is now empty remove it */
523 if (!gtk_tree_model_iter_has_child (model, &parent))
525 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
527 else
529 valid = gtk_tree_model_iter_next (model, &parent);
534 #if 0
535 static void
536 sensitivity_toggled (GtkCellRendererToggle *cell,
537 const gchar *path_str, GtkTreeView *tree_view)
539 GtkTreeModel *model;
540 GtkTreeModel *other_model;
541 GtkTreePath *path;
542 GtkTreeIter iter;
543 GtkAction *action;
544 gboolean sensitive;
546 model = gtk_tree_view_get_model (tree_view);
547 path = gtk_tree_path_new_from_string (path_str);
548 gtk_tree_model_get_iter (model, &iter, path);
549 gtk_tree_path_free (path);
551 gtk_tree_model_get (model, &iter,
552 COLUMN_SENSITIVE, &sensitive,
553 COLUMN_ACTION, &action, -1);
554 g_object_set (G_OBJECT (action), "sensitive", !sensitive, NULL);
555 g_object_unref (action);
557 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
558 COLUMN_SENSITIVE, !sensitive, -1);
560 /* Update other model */
561 other_model = g_object_get_data (G_OBJECT (tree_view), "other_model");
562 if (find_action (other_model, &iter, action))
564 gtk_tree_store_set (GTK_TREE_STORE (other_model), &iter,
565 COLUMN_SENSITIVE, !sensitive, -1);
568 #endif
570 static void
571 visibility_toggled (GtkCellRendererToggle *cell,
572 const gchar *path_str, GtkTreeView *tree_view)
574 GtkTreeModel *model;
575 GtkTreeModel *other_model;
576 GtkTreePath *path;
577 GtkTreeIter iter;
578 GtkAction *action;
579 gboolean visible;
581 model = gtk_tree_view_get_model (tree_view);
582 path = gtk_tree_path_new_from_string (path_str);
583 gtk_tree_model_get_iter (model, &iter, path);
584 gtk_tree_path_free (path);
586 gtk_tree_model_get (model, &iter,
587 COLUMN_VISIBLE, &visible,
588 COLUMN_ACTION, &action, -1);
589 g_object_set (G_OBJECT (action), "visible", !visible, NULL);
590 g_object_unref (action);
591 gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
592 COLUMN_VISIBLE, !visible, -1);
594 /* Update other model */
595 other_model = g_object_get_data (G_OBJECT (tree_view), "other_model");
596 if (find_action (other_model, &iter, action))
598 gtk_tree_store_set (GTK_TREE_STORE (other_model), &iter,
599 COLUMN_VISIBLE, !visible, -1);
603 static void
604 accel_edited_callback (GtkCellRendererAccel *cell,
605 const char *path_string,
606 guint keyval,
607 GdkModifierType mask,
608 guint hardware_keycode,
609 GtkTreeView *tree_view)
611 GtkTreeModel *model;
612 GtkTreePath *path;
613 GtkTreeIter iter;
614 GtkAction *action;
615 const gchar *accel_path;
617 model = gtk_tree_view_get_model (tree_view);
618 path = gtk_tree_path_new_from_string (path_string);
619 gtk_tree_model_get_iter (model, &iter, path);
620 gtk_tree_path_free (path);
622 gtk_tree_model_get (model, &iter,
623 COLUMN_ACTION, &action, -1);
625 /* sanity check */
626 if (action == NULL)
627 return;
629 accel_path = gtk_action_get_accel_path (action);
630 g_object_unref (action);
631 if (accel_path) {
632 gtk_accel_map_change_entry (accel_path, keyval, mask, TRUE);
636 static void
637 accel_cleared_callback (GtkCellRendererAccel *cell,
638 const char *path_string,
639 GtkTreeView *tree_view)
641 GtkTreeModel *model;
642 GtkTreePath *path;
643 GtkTreeIter iter;
644 GtkAction *action;
645 const gchar *accel_path;
648 model = gtk_tree_view_get_model (tree_view);
649 path = gtk_tree_path_new_from_string (path_string);
650 gtk_tree_model_get_iter (model, &iter, path);
651 gtk_tree_path_free (path);
653 gtk_tree_model_get (model, &iter,
654 COLUMN_ACTION, &action, -1);
656 /* sanity check */
657 if (action == NULL)
658 return;
660 accel_path = gtk_action_get_accel_path (action);
661 g_object_unref (action);
662 if (accel_path) {
663 gtk_accel_map_change_entry (accel_path, 0, 0, TRUE);
667 /* Fill the model sorted by accelerator with data from default model sorted by
668 * name */
669 static void
670 fill_sort_by_accel_store (GtkTreeStore *store, GtkTreeModel *model)
672 gboolean valid;
673 GtkTreeIter group;
675 for (valid = gtk_tree_model_get_iter_first (model, &group);
676 valid;
677 valid = gtk_tree_model_iter_next (model, &group))
679 GtkTreeIter iter;
680 gchar *group_label;
682 gtk_tree_model_get (model, &group,
683 COLUMN_ACTION_LABEL, &group_label,
684 -1);
686 for (valid = gtk_tree_model_iter_children (model, &iter, &group);
687 valid;
688 valid = gtk_tree_model_iter_next (model, &iter))
690 GtkTreeIter child;
691 GdkPixbuf *pixbuf;
692 gchar *action_label;
693 gboolean visible;
694 gboolean sensitive;
695 GtkAction *action;
696 gpointer action_group;
698 gtk_tree_model_get (model, &iter,
699 COLUMN_PIXBUF, &pixbuf,
700 COLUMN_ACTION_LABEL, &action_label,
701 COLUMN_VISIBLE, &visible,
702 COLUMN_SENSITIVE, &sensitive,
703 COLUMN_ACTION, &action,
704 COLUMN_GROUP, &action_group,
705 -1);
707 if (action != NULL)
709 insert_sorted_by_accel (GTK_TREE_MODEL (store), &child, group_label, action);
711 gtk_tree_store_set (store, &child,
712 COLUMN_PIXBUF, pixbuf,
713 COLUMN_ACTION_LABEL, action_label,
714 COLUMN_VISIBLE, visible,
715 COLUMN_SHOW_VISIBLE, TRUE,
716 COLUMN_SENSITIVE, sensitive,
717 COLUMN_ACTION, action,
718 COLUMN_GROUP, action_group,
719 -1);
723 if (pixbuf != NULL) g_object_unref (pixbuf);
724 g_free (action_label);
725 if (action != NULL) g_object_unref (action);
727 g_free (group_label);
731 /* Switch to the model sorted by name if use_name is true or sorted by
732 * accelerator if use_name is false */
733 static void
734 change_tree_model (GtkTreeView *tree_view, gboolean use_name)
736 gboolean has_name;
738 has_name = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "name_model"));
739 if (has_name != use_name)
741 GtkTreeModel *model;
742 GtkTreeModel *other_model;
743 GtkTreeIter iter;
744 GtkTreePath *path;
745 GList *expanded = NULL;
746 GtkAction *selected_action = NULL;
747 gchar *selected_group = NULL;
748 GtkTreeSelection *selection;
749 GList *item;
751 /* Save selection */
752 model = gtk_tree_view_get_model (tree_view);
753 selection = gtk_tree_view_get_selection (tree_view);
754 if (gtk_tree_selection_get_selected (selection, NULL, &iter))
756 gtk_tree_model_get (model, &iter,
757 COLUMN_ACTION_LABEL, &selected_group,
758 COLUMN_ACTION, &selected_action,
759 -1);
762 /* Save expanded groups */
763 for (path = gtk_tree_path_new_first ();
764 gtk_tree_model_get_iter (model, &iter, path);
765 gtk_tree_path_next (path))
767 if (gtk_tree_view_row_expanded (tree_view, path))
769 gchar *label;
771 gtk_tree_model_get (model, &iter, COLUMN_ACTION_LABEL, &label, -1);
772 expanded = g_list_prepend (expanded, label);
773 g_message ("expanded %s", label);
776 gtk_tree_path_free (path);
778 /* Swap model */
779 other_model = g_object_get_data (G_OBJECT (tree_view), "other_model");
781 if (!gtk_tree_model_get_iter_first (other_model, &iter) && !use_name)
783 /* Accelerator model is empty fill it */
784 fill_sort_by_accel_store (GTK_TREE_STORE (other_model), model);
787 gtk_tree_view_set_model (tree_view, other_model);
788 g_object_set_data (G_OBJECT (tree_view), "other_model", model);
789 g_object_set_data (G_OBJECT (tree_view), "name_model", GINT_TO_POINTER (use_name));
791 /* Expand same group */
792 for (item = g_list_first (expanded); item != NULL; item = g_list_next (item))
794 gchar *label = (gchar *)item->data;
795 gboolean valid;
797 for (valid = find_group_after (other_model, &iter, NULL, label);
798 valid;
799 valid = find_group_after (other_model, &iter, &iter, label))
801 path = gtk_tree_model_get_path (other_model, &iter);
802 gtk_tree_view_expand_row (tree_view, path, FALSE);
803 gtk_tree_path_free (path);
805 g_free (label);
807 g_list_free (expanded);
809 /* Restore selection */
810 if (selected_action != NULL)
812 find_action (other_model, &iter, selected_action);
813 gtk_tree_selection_select_iter (selection, &iter);
814 g_object_unref (selected_action);
816 else if (selected_group != NULL)
818 find_group_after (other_model, &iter, NULL, selected_group);
819 gtk_tree_selection_select_iter (selection, &iter);
821 /* Display selected row */
822 if ((selected_action != NULL) || (selected_group != NULL))
824 GtkTreePath *path;
826 path = gtk_tree_model_get_path (other_model, &iter);
827 gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0);
828 gtk_tree_path_free (path);
830 g_free (selected_group);
834 static void
835 accel_sort_by_accel_callback (GtkTreeViewColumn *column,
836 gpointer data)
838 GtkTreeView *tree_view = (GtkTreeView *)data;
840 change_tree_model (tree_view, FALSE);
843 static void
844 accel_sort_by_name_callback (GtkTreeViewColumn *column,
845 gpointer data)
847 GtkTreeView *tree_view = (GtkTreeView *)data;
849 change_tree_model (tree_view, TRUE);
852 static void
853 accel_set_func (GtkTreeViewColumn *tree_column,
854 GtkCellRenderer *cell,
855 GtkTreeModel *model,
856 GtkTreeIter *iter,
857 gpointer data)
859 GtkAction *action;
860 const gchar *accel_path;
861 GtkAccelKey key;
863 gtk_tree_model_get (model, iter,
864 COLUMN_ACTION, &action, -1);
865 if (action == NULL)
866 g_object_set (G_OBJECT (cell), "visible", FALSE, NULL);
867 else
869 if ((accel_path = gtk_action_get_accel_path (action)))
871 if (gtk_accel_map_lookup_entry (accel_path, &key))
873 g_object_set (G_OBJECT (cell), "visible", TRUE,
874 "accel-key", key.accel_key,
875 "accel-mods", key.accel_mods, NULL);
877 else
878 g_object_set (G_OBJECT (cell), "visible", TRUE,
879 "accel-key", 0,
880 "accel-mods", 0, NULL);
882 g_object_unref (action);
886 G_DEFINE_TYPE(AnjutaUI, anjuta_ui, GTK_TYPE_UI_MANAGER)
888 static void
889 anjuta_ui_dispose (GObject *obj)
891 AnjutaUI *ui = ANJUTA_UI (obj);
893 if (ui->priv->name_model) {
894 /* This will also release the refs on actions.
895 * Clear is necessary because following unref() might not actually
896 * finalize the model. It basically ensures all refs on actions
897 * are released irrespective of whether the model is finalized
898 * or not.
900 gtk_tree_store_clear (GTK_TREE_STORE (ui->priv->name_model));
902 g_object_unref (G_OBJECT (ui->priv->name_model));
903 ui->priv->name_model = NULL;
905 if (ui->priv->accel_model) {
906 gtk_tree_store_clear (GTK_TREE_STORE (ui->priv->accel_model));
907 g_object_unref (G_OBJECT (ui->priv->accel_model));
908 ui->priv->accel_model = NULL;
910 if (ui->priv->customizable_actions_hash)
912 /* This will also release the refs on all action groups */
913 g_hash_table_destroy (ui->priv->customizable_actions_hash);
914 ui->priv->customizable_actions_hash = NULL;
916 if (ui->priv->uncustomizable_actions_hash)
918 /* This will also release the refs on all action groups */
919 g_hash_table_destroy (ui->priv->uncustomizable_actions_hash);
920 ui->priv->uncustomizable_actions_hash = NULL;
922 if (ui->priv->icon_factory) {
923 g_object_unref (G_OBJECT (ui->priv->icon_factory));
924 ui->priv->icon_factory = NULL;
926 G_OBJECT_CLASS (anjuta_ui_parent_class)->dispose (obj);
929 static void
930 anjuta_ui_finalize (GObject *obj)
932 AnjutaUI *ui = ANJUTA_UI (obj);
933 g_free (ui->priv);
934 G_OBJECT_CLASS (anjuta_ui_parent_class)->finalize (obj);
937 static void
938 anjuta_ui_class_init (AnjutaUIClass *class)
940 GObjectClass *object_class = G_OBJECT_CLASS (class);
942 object_class->dispose = anjuta_ui_dispose;
943 object_class->finalize = anjuta_ui_finalize;
946 static void
947 anjuta_ui_init (AnjutaUI *ui)
949 GtkTreeStore *store;
951 /* Initialize member data */
952 ui->priv = g_new0 (AnjutaUIPrivate, 1);
953 ui->priv->customizable_actions_hash =
954 g_hash_table_new_full (g_str_hash,
955 g_str_equal,
956 (GDestroyNotify) g_free,
957 NULL);
958 ui->priv->uncustomizable_actions_hash =
959 g_hash_table_new_full (g_str_hash,
960 g_str_equal,
961 (GDestroyNotify) g_free,
962 NULL);
963 /* Create Icon factory */
964 ui->priv->icon_factory = gtk_icon_factory_new ();
965 gtk_icon_factory_add_default (ui->priv->icon_factory);
967 /* Create Accel editor sorted by name model */
968 store = gtk_tree_store_new (N_COLUMNS,
969 GDK_TYPE_PIXBUF,
970 G_TYPE_STRING,
971 G_TYPE_BOOLEAN,
972 G_TYPE_BOOLEAN,
973 G_TYPE_BOOLEAN,
974 G_TYPE_OBJECT,
975 G_TYPE_POINTER);
977 /* unreferenced in dispose() method. */
978 ui->priv->name_model = GTK_TREE_MODEL (store);
980 /* Create Accel editor sorted by accelerator model */
981 store = gtk_tree_store_new (N_COLUMNS,
982 GDK_TYPE_PIXBUF,
983 G_TYPE_STRING,
984 G_TYPE_BOOLEAN,
985 G_TYPE_BOOLEAN,
986 G_TYPE_BOOLEAN,
987 G_TYPE_OBJECT,
988 G_TYPE_POINTER);
990 /* unreferenced in dispose() method. */
991 ui->priv->accel_model = GTK_TREE_MODEL (store);
995 * anjuta_ui_new:
997 * Creates a new instance of #AnjutaUI.
999 * Return value: A #AnjutaUI object
1001 AnjutaUI *
1002 anjuta_ui_new (void)
1004 return g_object_new (ANJUTA_TYPE_UI, NULL);
1008 * anjuta_ui_add_action_group_entries:
1009 * @ui: A #AnjutaUI object.
1010 * @action_group_name: Untranslated name of the action group.
1011 * @action_group_label: Translated label of the action group.
1012 * @entries: An array of action entries.
1013 * @num_entries: Number of elements in the action entries array.
1014 * @can_customize: If true the actions are customizable by user.
1015 * @translation_domain: The translation domain used to translated the entries.
1016 * It is usually the GETTEXT_PACKAGE macro in a project.
1017 * @user_data: User data to pass to action objects. This is the data that
1018 * will come as user_data in "activate" signal of the actions.
1020 * #GtkAction objects are created from the #GtkActionEntry structures and
1021 * added to the UI Manager. "activate" signal of #GtkAction is connected for
1022 * all the action objects using the callback in the entry structure and the
1023 * @user_data passed here.
1025 * This group of actions are registered with the name @action_group_name
1026 * in #AnjutaUI. A #GtkAction object from this action group can be later
1027 * retrieved by anjuta_ui_get_action() using @action_group_name and action name.
1028 * @action_group_label is used as the display name for the action group in
1029 * UI manager dialog where action shortcuts are configured.
1031 * Return value: A #GtkActionGroup object holding all the action objects.
1033 GtkActionGroup*
1034 anjuta_ui_add_action_group_entries (AnjutaUI *ui,
1035 const gchar *action_group_name,
1036 const gchar *action_group_label,
1037 GtkActionEntry *entries,
1038 gint num_entries,
1039 const gchar *translation_domain,
1040 gboolean can_customize,
1041 gpointer user_data)
1043 GtkActionGroup *action_group;
1045 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1046 g_return_val_if_fail (action_group_name != NULL, NULL);
1047 g_return_val_if_fail (action_group_name != NULL, NULL);
1049 action_group = gtk_action_group_new (action_group_name);
1051 gtk_action_group_set_translation_domain (action_group, translation_domain);
1052 gtk_action_group_add_actions (action_group, entries, num_entries,
1053 user_data);
1054 anjuta_ui_add_action_group (ui, action_group_name,
1055 action_group_label, action_group,
1056 can_customize);
1057 return action_group;
1061 * anjuta_ui_add_toggle_action_group_entries:
1062 * @ui: A #AnjutaUI object.
1063 * @action_group_name: Untranslated name of the action group.
1064 * @action_group_label: Translated label of the action group.
1065 * @entries: An array of action entries.
1066 * @num_entries: Number of elements in the action entries array.
1067 * @translation_domain: The translation domain used to translated the entries.
1068 * It is usually the GETTEXT_PACKAGE macro in a project.
1069 * @user_data: User data to pass to action objects. This is the data that
1070 * will come as user_data in "activate" signal of the actions.
1072 * This is similar to anjuta_ui_add_action_group_entries(), except that
1073 * it adds #GtkToggleAction objects after creating them from the @entries.
1075 * Return value: A #GtkActionGroup object holding all the action objects.
1077 GtkActionGroup*
1078 anjuta_ui_add_toggle_action_group_entries (AnjutaUI *ui,
1079 const gchar *action_group_name,
1080 const gchar *action_group_label,
1081 GtkToggleActionEntry *entries,
1082 gint num_entries,
1083 const gchar *translation_domain,
1084 gboolean can_customize,
1085 gpointer user_data)
1087 GtkActionGroup *action_group;
1089 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1090 g_return_val_if_fail (action_group_name != NULL, NULL);
1091 g_return_val_if_fail (action_group_name != NULL, NULL);
1093 action_group = gtk_action_group_new (action_group_name);
1094 gtk_action_group_set_translation_domain (action_group, translation_domain);
1095 gtk_action_group_add_toggle_actions (action_group, entries, num_entries,
1096 user_data);
1097 anjuta_ui_add_action_group (ui, action_group_name,
1098 action_group_label, action_group,
1099 can_customize);
1100 return action_group;
1104 * anjuta_ui_add_action_group:
1105 * @ui: A #AnjutaUI object.
1106 * @action_group_name: Untranslated name of the action group.
1107 * @action_group_label: Translated label of the action group.
1108 * @action_group: #GtkActionGroup object to add.
1110 * This is similar to anjuta_ui_add_action_group_entries(), except that
1111 * it adds #GtkActionGroup object @action_group directly. All actions in this
1112 * group are automatically registered in #AnjutaUI and can be retrieved
1113 * normally with anjuta_ui_get_action().
1115 void
1116 anjuta_ui_add_action_group (AnjutaUI *ui,
1117 const gchar *action_group_name,
1118 const gchar *action_group_label,
1119 GtkActionGroup *action_group,
1120 gboolean can_customize)
1122 GList *actions, *l;
1124 g_return_if_fail (ANJUTA_IS_UI (ui));
1125 g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1126 g_return_if_fail (action_group_name != NULL);
1127 g_return_if_fail (action_group_name != NULL);
1129 gtk_ui_manager_insert_action_group (GTK_UI_MANAGER (ui), action_group, 0);
1131 if (can_customize)
1133 g_hash_table_insert (ui->priv->customizable_actions_hash,
1134 g_strdup (action_group_name), action_group);
1136 else
1138 g_hash_table_insert (ui->priv->uncustomizable_actions_hash,
1139 g_strdup (action_group_name), action_group);
1142 actions = gtk_action_group_list_actions (action_group);
1143 for (l = actions; l; l = l->next)
1145 guint signal_id;
1146 gint n_handlers;
1147 GtkTreeIter iter;
1148 GtkAction *action = l->data;
1150 if (!action)
1151 continue;
1153 signal_id = g_signal_lookup ("activate", GTK_TYPE_ACTION);
1154 n_handlers = g_signal_has_handler_pending (action, signal_id,
1155 0, TRUE);
1156 if (n_handlers == 0)
1157 continue; /* The action element is not user configuration */
1159 insert_sorted_by_name (ui->priv->name_model, &iter, action_group_label, action);
1160 fill_action_data (ui->priv->name_model, &iter, action, action_group);
1162 if (gtk_tree_model_get_iter_first (ui->priv->accel_model, &iter))
1164 /* accel model is filled only if needed */
1165 insert_sorted_by_accel (ui->priv->accel_model, &iter, action_group_label, action);
1166 fill_action_data (ui->priv->accel_model, &iter, action, action_group);
1169 g_list_free(actions);
1172 static gboolean
1173 on_action_group_remove_hash (gpointer key, gpointer value, gpointer data)
1175 if (data == value)
1176 return TRUE;
1177 else
1178 return FALSE;
1182 * anjuta_ui_remove_action_group:
1183 * @ui: A #AnjutaUI object
1184 * @action_group: #GtkActionGroup object to remove.
1186 * Removes a previous added action group. All actions in this group are
1187 * also unregistered from UI manager.
1189 void
1190 anjuta_ui_remove_action_group (AnjutaUI *ui, GtkActionGroup *action_group)
1192 g_return_if_fail (ANJUTA_IS_UI (ui));
1194 remove_action_in_group (ui->priv->name_model, action_group);
1195 remove_action_in_group (ui->priv->accel_model, action_group);
1197 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (ui), action_group);
1199 g_hash_table_foreach_remove (ui->priv->customizable_actions_hash,
1200 on_action_group_remove_hash, action_group);
1201 g_hash_table_foreach_remove (ui->priv->uncustomizable_actions_hash,
1202 on_action_group_remove_hash, action_group);
1206 * anjuta_ui_get_action:
1207 * @ui: This #AnjutaUI object
1208 * @action_group_name: Group name.
1209 * @action_name: Action name.
1211 * Returns the action object with the name @action_name in @action_group_name.
1212 * Note that it will be only sucessully returned if the group has been added
1213 * using methods in #AnjutaUI.
1215 * Returns: A #GtkAction object
1217 GtkAction*
1218 anjuta_ui_get_action (AnjutaUI *ui, const gchar *action_group_name,
1219 const gchar *action_name)
1221 GtkActionGroup *action_group;
1222 GtkAction *action;
1224 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1226 action_group = g_hash_table_lookup (ui->priv->customizable_actions_hash,
1227 action_group_name);
1228 if (!action_group)
1230 action_group = g_hash_table_lookup (ui->priv->uncustomizable_actions_hash,
1231 action_group_name);
1233 if (GTK_IS_ACTION_GROUP (action_group) == FALSE)
1235 g_warning ("Unable to find action group \"%s\"", action_group_name);
1236 return NULL;
1238 action = gtk_action_group_get_action (action_group, action_name);
1239 if (GTK_IS_ACTION (action))
1240 return action;
1241 g_warning ("Unable to find action \"%s\" in group \"%s\"",
1242 action_name, action_group_name);
1243 return NULL;
1247 * anjuta_ui_activate_action_by_path:
1248 * @ui: This #AnjutaUI object
1249 * @action_path: Path of the action in the form "GroupName/ActionName"
1251 * Activates the action represented by @action_path. The path is in the form
1252 * "ActionGroupName/ActionName". Note that it will only work if the group has
1253 * been added using methods in #AnjutaUI.
1255 void
1256 anjuta_ui_activate_action_by_path (AnjutaUI *ui, const gchar *action_path)
1258 const gchar *action_group_name;
1259 const gchar *action_name;
1260 GtkAction *action;
1261 gchar **strv;
1263 g_return_if_fail (ANJUTA_IS_UI (ui));
1264 g_return_if_fail (action_path != NULL);
1266 strv = g_strsplit (action_path, "/", 2);
1267 action_group_name = strv[0];
1268 action_name = strv[1];
1270 g_return_if_fail (action_group_name != NULL && action_name != NULL);
1272 action = anjuta_ui_get_action (ui, action_group_name, action_name);
1273 if (action)
1274 gtk_action_activate (action);
1275 g_strfreev (strv);
1279 * anjuta_ui_activate_action_by_group:
1280 * @ui: This #AnjutaUI object
1281 * @action_group: Action group.
1282 * @action_name: Action name.
1284 * Activates the action @action_name in the #GtkActionGroup @action_group.
1285 * "ActionGroupName/ActionName". Note that it will only work if the group has
1286 * been added using methods in #AnjutaUI.
1288 void
1289 anjuta_ui_activate_action_by_group (AnjutaUI *ui, GtkActionGroup *action_group,
1290 const gchar *action_name)
1292 GtkAction *action;
1294 g_return_if_fail (ANJUTA_IS_UI (ui));
1295 g_return_if_fail (action_group != NULL && action_name != NULL);
1297 action = gtk_action_group_get_action (action_group, action_name);
1298 if (GTK_IS_ACTION (action))
1299 gtk_action_activate (action);
1303 * anjuta_ui_merge:
1304 * @ui: A #AnjutaUI object.
1305 * @ui_filename: UI file to merge into UI manager.
1307 * Merges XML UI definition in @ui_filename. UI elements defined in the xml
1308 * are merged with existing UI elements in UI manager. The format of the
1309 * file content is the standard XML UI definition tree. For more detail,
1310 * read the documentation for #GtkUIManager.
1312 * Return value: Integer merge ID
1314 gint
1315 anjuta_ui_merge (AnjutaUI *ui, const gchar *ui_filename)
1317 gint id;
1318 GError *err = NULL;
1320 g_return_val_if_fail (ANJUTA_IS_UI (ui), -1);
1321 g_return_val_if_fail (ui_filename != NULL, -1);
1322 id = gtk_ui_manager_add_ui_from_file(GTK_UI_MANAGER (ui),
1323 ui_filename, &err);
1324 #ifdef DEBUG
1326 gchar *basename = g_path_get_basename (ui_filename);
1327 DEBUG_PRINT ("merged [%d] %s", id, basename);
1328 g_free(basename);
1330 #endif
1331 if (err != NULL)
1332 g_warning ("Could not merge [%s]: %s", ui_filename, err->message);
1333 return id;
1337 * anjuta_ui_unmerge:
1338 * @ui: A #AnjutaUI object.
1339 * @id: Merge ID returned by anjuta_ui_merge().
1341 * Unmerges UI with the ID value @id (returned by anjuta_ui_merge() when
1342 * it was merged. For more detail, read the documentation for #GtkUIManager.
1344 void
1345 anjuta_ui_unmerge (AnjutaUI *ui, gint id)
1347 /* DEBUG_PRINT ("Menu unmerging %d", id); */
1348 g_return_if_fail (ANJUTA_IS_UI (ui));
1349 gtk_ui_manager_remove_ui(GTK_UI_MANAGER (ui), id);
1353 * anjuta_ui_get_accel_group:
1354 * @ui: A #AnjutaUI object.
1356 * Returns the #GtkAccelGroup object associated with this UI manager.
1358 * Returns: A #GtkAccelGroup object.
1360 GtkAccelGroup*
1361 anjuta_ui_get_accel_group (AnjutaUI *ui)
1363 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1364 return gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (ui));
1368 * anjuta_ui_get_accel_editor:
1369 * @ui: A #AnjutaUI object.
1371 * Creates an accel editor widget and returns it. It should be added to
1372 * container and displayed to users.
1374 * Returns: a #GtkWidget containing the editor.
1376 GtkWidget *
1377 anjuta_ui_get_accel_editor (AnjutaUI *ui)
1379 GtkWidget *tree_view, *sw;
1380 GtkTreeStore *store;
1381 GtkTreeViewColumn *column;
1382 GtkCellRenderer *renderer;
1384 store = GTK_TREE_STORE (ui->priv->name_model);
1386 tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
1387 g_object_set_data (G_OBJECT (tree_view), "other_model", ui->priv->accel_model);
1388 g_object_set_data (G_OBJECT (tree_view), "name_model", GINT_TO_POINTER (TRUE));
1389 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
1391 /* Columns */
1392 column = gtk_tree_view_column_new ();
1393 gtk_tree_view_column_set_title (column, dgettext (GETTEXT_PACKAGE, "Action"));
1395 renderer = gtk_cell_renderer_pixbuf_new ();
1396 gtk_tree_view_column_pack_start (column, renderer, FALSE);
1397 gtk_tree_view_column_add_attribute (column, renderer, "pixbuf",
1398 COLUMN_PIXBUF);
1400 renderer = gtk_cell_renderer_text_new ();
1401 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1402 gtk_tree_view_column_add_attribute (column, renderer, "text",
1403 COLUMN_ACTION_LABEL);
1404 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1405 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree_view), column);
1406 gtk_tree_view_column_set_clickable (column, TRUE);
1407 g_signal_connect (G_OBJECT (column), "clicked",
1408 G_CALLBACK (accel_sort_by_name_callback),
1409 tree_view);
1411 renderer = gtk_cell_renderer_toggle_new ();
1412 g_signal_connect (G_OBJECT (renderer), "toggled",
1413 G_CALLBACK (visibility_toggled), tree_view);
1414 column = gtk_tree_view_column_new_with_attributes (dgettext (GETTEXT_PACKAGE, "Visible"),
1415 renderer,
1416 "active",
1417 COLUMN_VISIBLE,
1418 "visible",
1419 COLUMN_SHOW_VISIBLE,
1420 NULL);
1421 gtk_tree_view_column_set_alignment (column, 0.5f);
1422 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1423 #if 0
1424 renderer = gtk_cell_renderer_toggle_new ();
1425 g_signal_connect (G_OBJECT (renderer), "toggled",
1426 G_CALLBACK (sensitivity_toggled), tree_view);
1427 column = gtk_tree_view_column_new_with_attributes (_("Sensitive"),
1428 renderer,
1429 "active",
1430 COLUMN_SENSITIVE,
1431 NULL);
1432 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1433 #endif
1434 column = gtk_tree_view_column_new ();
1435 gtk_tree_view_column_set_title (column, dgettext (GETTEXT_PACKAGE, "Shortcut"));
1436 renderer = g_object_new (GTK_TYPE_CELL_RENDERER_ACCEL,
1437 "editable", TRUE,
1438 NULL);
1439 g_signal_connect (G_OBJECT (renderer), "accel-edited",
1440 G_CALLBACK (accel_edited_callback),
1441 tree_view);
1442 g_signal_connect (G_OBJECT (renderer), "accel-cleared",
1443 G_CALLBACK (accel_cleared_callback),
1444 tree_view);
1445 g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
1446 gtk_tree_view_column_pack_start (column, renderer, TRUE);
1447 gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
1448 gtk_tree_view_column_set_clickable (column, TRUE);
1449 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
1450 g_signal_connect (G_OBJECT (column), "clicked",
1451 G_CALLBACK (accel_sort_by_accel_callback),
1452 tree_view);
1454 sw = gtk_scrolled_window_new (NULL, NULL);
1455 gtk_container_set_border_width (GTK_CONTAINER (sw), 6);
1456 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1457 GTK_POLICY_AUTOMATIC,
1458 GTK_POLICY_AUTOMATIC);
1459 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
1460 GTK_SHADOW_IN);
1461 gtk_container_add (GTK_CONTAINER (sw), tree_view);
1462 gtk_widget_show_all (sw);
1463 return sw;
1467 * anjuta_ui_get_icon_factory:
1468 * @ui: A #AnjutaUI object
1470 * This returns the IconFactory object. All icons should be registered using
1471 * this icon factory. Read the documentation for #GtkIconFactory on how to
1472 * use it.
1474 * Return value: The #GtkIconFactory object used by it
1476 GtkIconFactory*
1477 anjuta_ui_get_icon_factory (AnjutaUI *ui)
1479 g_return_val_if_fail (ANJUTA_IS_UI (ui), NULL);
1480 return ui->priv->icon_factory;
1484 * anjuta_ui_dump_tree:
1485 * @ui: A #AnjutaUI object.
1487 * Dumps the current UI XML tree in STDOUT. Useful for debugging.
1489 void
1490 anjuta_ui_dump_tree (AnjutaUI *ui)
1492 gchar *ui_str;
1494 g_return_if_fail (ANJUTA_IS_UI(ui));
1496 gtk_ui_manager_ensure_update (GTK_UI_MANAGER (ui));
1497 ui_str = gtk_ui_manager_get_ui (GTK_UI_MANAGER (ui));
1498 /* DEBUG_PRINT ("%s", ui_str); */
1499 g_free (ui_str);
1503 * Accels
1505 static gchar *
1506 anjuta_ui_get_accel_file (void)
1508 return anjuta_util_get_user_config_file_path ("anjuta-accels", NULL);
1511 void
1512 anjuta_ui_load_accels (const gchar *filename)
1514 if (filename)
1516 gtk_accel_map_load (filename);
1518 else
1520 gchar *def_filename = anjuta_ui_get_accel_file ();
1521 if (def_filename != NULL)
1523 gtk_accel_map_load (def_filename);
1524 g_free (def_filename);
1529 void
1530 anjuta_ui_save_accels (const gchar *filename)
1532 if (filename)
1534 gtk_accel_map_save (filename);
1536 else
1538 gchar * def_filename = anjuta_ui_get_accel_file ();
1540 if (def_filename != NULL)
1542 gtk_accel_map_save (def_filename);
1543 g_free (def_filename);
1548 static void anjuta_ui_remove_accel (AnjutaUI *ui,
1549 const gchar *accel_path, guint accel_key,
1550 GdkModifierType accel_mods, gboolean changed)
1552 gtk_accel_group_disconnect_key (anjuta_ui_get_accel_group(ui), accel_key, accel_mods);
1555 void
1556 anjuta_ui_unload_accels (AnjutaUI *ui)
1558 anjuta_ui_save_accels (NULL);
1559 gtk_accel_map_foreach_unfiltered (ui, (GtkAccelMapForeach) anjuta_ui_remove_accel);