bgo #708248 - inconsistency in strings: libtool, whitespace use
[anjuta.git] / plugins / snippets-manager / snippets-browser.c
blobd70b0b4f9f25d09378203bc3d03acf755f952a8e
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 snippets-browser.c
4 Copyright (C) Dragos Dena 2010
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,
19 Boston, MA 02110-1301 USA
22 #include "snippets-browser.h"
23 #include "snippets-group.h"
24 #include "snippets-editor.h"
25 #include <libanjuta/interfaces/ianjuta-document-manager.h>
26 #include <libanjuta/interfaces/ianjuta-document.h>
27 #include <libanjuta/interfaces/ianjuta-editor.h>
28 #include <libanjuta/interfaces/ianjuta-editor-language.h>
29 #include <libanjuta/interfaces/ianjuta-language.h>
31 #define BROWSER_UI PACKAGE_DATA_DIR"/glade/snippets-browser.ui"
32 #define TOOLTIP_SIZE 200
33 #define NEW_SNIPPETS_GROUP_NAME "New Snippets Group"
35 #define ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPETS_BROWSER, SnippetsBrowserPrivate))
37 struct _SnippetsBrowserPrivate
39 SnippetsEditor *snippets_editor;
40 GtkTreeView *snippets_view;
42 SnippetsDB *snippets_db;
44 GtkButton *add_button;
45 GtkButton *delete_button;
46 GtkButton *insert_button;
47 GtkToggleButton *edit_button;
49 GtkWidget *grip;
51 GtkBox *snippets_view_vbox;
52 GtkScrolledWindow *snippets_view_cont;
54 GtkWidget *browser_hpaned;
56 GtkTreeModel *filter;
58 gboolean maximized;
60 SnippetsInteraction *snippets_interaction;
64 enum
66 SNIPPETS_VIEW_COL_NAME = 0,
67 SNIPPETS_VIEW_COL_TRIGGER,
68 SNIPPETS_VIEW_COL_LANGUAGES
72 G_DEFINE_TYPE (SnippetsBrowser, snippets_browser, GTK_TYPE_BOX);
74 static void
75 snippets_browser_class_init (SnippetsBrowserClass* klass)
78 /* Assertions */
79 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER_CLASS (klass));
81 /* The SnippetsBrowser asks for a maximize. If a maximize is possible,
82 the snippets_browser_show_editor should be called. */
83 g_signal_new ("maximize-request",
84 ANJUTA_TYPE_SNIPPETS_BROWSER,
85 G_SIGNAL_RUN_LAST,
86 G_STRUCT_OFFSET (SnippetsBrowserClass, maximize_request),
87 NULL, NULL,
88 g_cclosure_marshal_VOID__VOID,
89 G_TYPE_NONE,
91 NULL);
93 /* Like above, the SnippetsBrowser asks for a unmaximize. */
94 g_signal_new ("unmaximize-request",
95 ANJUTA_TYPE_SNIPPETS_BROWSER,
96 G_SIGNAL_RUN_LAST,
97 G_STRUCT_OFFSET (SnippetsBrowserClass, unmaximize_request),
98 NULL, NULL,
99 g_cclosure_marshal_VOID__VOID,
100 G_TYPE_NONE,
102 NULL);
104 g_type_class_add_private (klass, sizeof (SnippetsBrowserPrivate));
107 static void
108 snippets_browser_init (SnippetsBrowser* snippets_browser)
110 SnippetsBrowserPrivate* priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
112 snippets_browser->priv = priv;
113 snippets_browser->show_only_document_language_snippets = TRUE;
114 snippets_browser->anjuta_shell = NULL;
116 /* Initialize the private field */
117 priv->snippets_view = NULL;
118 priv->snippets_db = NULL;
119 priv->add_button = NULL;
120 priv->delete_button = NULL;
121 priv->insert_button = NULL;
122 priv->edit_button = NULL;
123 priv->snippets_view_cont = NULL;
124 priv->snippets_view_vbox = NULL;
125 priv->browser_hpaned = NULL;
126 priv->filter = NULL;
127 priv->maximized = FALSE;
128 priv->snippets_interaction = NULL;
132 /* Handlers */
134 static void on_add_button_clicked (GtkButton *add_button,
135 gpointer user_data);
136 static void on_delete_button_clicked (GtkButton *delete_button,
137 gpointer user_data);
138 static void on_insert_button_clicked (GtkButton *insert_button,
139 gpointer user_data);
140 static void on_edit_button_toggled (GtkToggleButton *edit_button,
141 gpointer user_data);
142 static void on_snippets_view_row_activated (GtkTreeView *snippets_view,
143 GtkTreePath *path,
144 GtkTreeViewColumn *col,
145 gpointer user_data);
146 static gboolean on_snippets_view_query_tooltip (GtkWidget *snippets_view,
147 gint x,
148 gint y,
149 gboolean keyboard_mode,
150 GtkTooltip *tooltip,
151 gpointer user_data);
152 static void on_name_changed (GtkCellRendererText *renderer,
153 gchar *path_string,
154 gchar *new_text,
155 gpointer user_data);
156 static void on_add_snippet_menu_item_activated (GtkMenuItem *menu_item,
157 gpointer user_data);
158 static void on_add_snippets_group_menu_item_activated (GtkMenuItem *menu_item,
159 gpointer user_data);
160 static void on_snippets_view_selection_changed (GtkTreeSelection *tree_selection,
161 gpointer user_data);
162 static void on_snippets_editor_snippet_saved (SnippetsEditor *snippets_editor,
163 GObject *snippet,
164 gpointer user_data);
165 static void on_snippets_editor_close_request (SnippetsEditor *snippets_editor,
166 gpointer user_data);
168 /* Private methods */
170 static void
171 init_browser_layout (SnippetsBrowser *snippets_browser)
173 GError *error = NULL;
174 SnippetsBrowserPrivate *priv = NULL;
175 GtkBuilder *bxml = NULL;
176 GObject *window = NULL;
178 /* Assertions */
179 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
180 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
182 /* Load the UI file */
183 bxml = gtk_builder_new ();
184 if (!gtk_builder_add_from_file (bxml, BROWSER_UI, &error))
186 g_warning ("Couldn't load browser ui file: %s", error->message);
187 g_error_free (error);
190 /* Get the Gtk objects */
191 priv->add_button = GTK_BUTTON(gtk_button_new());
192 gtk_widget_set_tooltip_text (GTK_WIDGET (priv->add_button),
193 _("Add snippet"));
194 gtk_container_add (GTK_CONTAINER (priv->add_button),
195 gtk_image_new_from_stock (GTK_STOCK_ADD,
196 GTK_ICON_SIZE_MENU));
197 priv->delete_button = GTK_BUTTON(gtk_button_new());
198 gtk_widget_set_tooltip_text (GTK_WIDGET (priv->delete_button),
199 _("Remove selected snippet"));
200 gtk_container_add (GTK_CONTAINER (priv->delete_button),
201 gtk_image_new_from_stock (GTK_STOCK_REMOVE,
202 GTK_ICON_SIZE_MENU));
203 priv->insert_button = GTK_BUTTON(gtk_button_new());
204 gtk_widget_set_tooltip_text (GTK_WIDGET (priv->insert_button),
205 _("Insert snippet into editor at current cursor position"));
206 gtk_container_add (GTK_CONTAINER (priv->insert_button),
207 gtk_image_new_from_stock (GTK_STOCK_PASTE,
208 GTK_ICON_SIZE_MENU));
209 priv->grip = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
210 priv->edit_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (bxml, "edit_button"));
211 priv->snippets_view_cont = GTK_SCROLLED_WINDOW (gtk_builder_get_object (bxml, "snippets_view_cont"));
212 priv->snippets_view_vbox = GTK_BOX (gtk_builder_get_object (bxml, "snippets_view_vbox"));
214 gtk_box_pack_start (GTK_BOX (priv->grip), gtk_label_new (_("Snippets")), FALSE, FALSE, 5);
215 gtk_box_pack_end (GTK_BOX (priv->grip), GTK_WIDGET(priv->insert_button), FALSE, FALSE, 1);
216 gtk_box_pack_end (GTK_BOX (priv->grip), GTK_WIDGET(priv->delete_button), FALSE, FALSE, 1);
217 gtk_box_pack_end (GTK_BOX (priv->grip), GTK_WIDGET(priv->add_button), FALSE, FALSE, 1);
219 gtk_widget_show_all (priv->grip);
221 /* Assert the objects */
222 g_return_if_fail (GTK_IS_TOGGLE_BUTTON (priv->edit_button));
223 g_return_if_fail (GTK_IS_SCROLLED_WINDOW (priv->snippets_view_cont));
224 g_return_if_fail (GTK_IS_BOX (priv->snippets_view_vbox));
226 /* Add the Snippets View to the scrolled window */
227 gtk_container_add (GTK_CONTAINER (priv->snippets_view_cont),
228 GTK_WIDGET (priv->snippets_view));
230 /* Add the hbox as the child of the snippets browser */
231 window = gtk_builder_get_object (bxml, "builder_window");
232 g_object_ref (priv->snippets_view_vbox);
233 gtk_container_remove (GTK_CONTAINER (window), GTK_WIDGET (priv->snippets_view_vbox));
234 gtk_box_pack_start (GTK_BOX (snippets_browser),
235 GTK_WIDGET (priv->snippets_view_vbox),
236 TRUE,
237 TRUE,
239 g_object_unref (priv->snippets_view_vbox);
241 /* Initialize the snippets editor */
242 priv->snippets_editor = snippets_editor_new (priv->snippets_db);
243 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (priv->snippets_editor));
245 /* Add the editor to the HPaned */
246 priv->browser_hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
247 gtk_paned_pack2 (GTK_PANED (priv->browser_hpaned),
248 GTK_WIDGET (priv->snippets_editor),
249 TRUE, FALSE);
250 g_object_ref_sink (priv->browser_hpaned);
252 g_object_unref (bxml);
255 static void
256 init_browser_handlers (SnippetsBrowser *snippets_browser)
258 SnippetsBrowserPrivate *priv = NULL;
260 /* Assertions */
261 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
262 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
264 g_signal_connect (priv->snippets_view,
265 "row-activated",
266 G_CALLBACK (on_snippets_view_row_activated),
267 snippets_browser);
268 g_signal_connect (priv->snippets_view,
269 "query-tooltip",
270 G_CALLBACK (on_snippets_view_query_tooltip),
271 snippets_browser);
272 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (priv->snippets_view)),
273 "changed",
274 G_CALLBACK (on_snippets_view_selection_changed),
275 snippets_browser);
276 g_signal_connect (priv->add_button,
277 "clicked",
278 G_CALLBACK (on_add_button_clicked),
279 snippets_browser);
280 g_signal_connect (priv->delete_button,
281 "clicked",
282 G_CALLBACK (on_delete_button_clicked),
283 snippets_browser);
284 g_signal_connect (priv->insert_button,
285 "clicked",
286 G_CALLBACK (on_insert_button_clicked),
287 snippets_browser);
288 g_signal_connect (priv->edit_button,
289 "toggled",
290 G_CALLBACK (on_edit_button_toggled),
291 snippets_browser);
292 g_signal_connect (priv->snippets_editor,
293 "snippet-saved",
294 G_CALLBACK (on_snippets_editor_snippet_saved),
295 snippets_browser);
296 g_signal_connect (priv->snippets_editor,
297 "close-request",
298 G_CALLBACK (on_snippets_editor_close_request),
299 snippets_browser);
301 /* Set the has-tooltip property for the query-tooltip signal */
302 g_object_set (priv->snippets_view, "has-tooltip", TRUE, NULL);
305 static void
306 snippets_view_name_text_data_func (GtkTreeViewColumn *column,
307 GtkCellRenderer *renderer,
308 GtkTreeModel *tree_model,
309 GtkTreeIter *iter,
310 gpointer user_data)
312 gchar *name = NULL;
313 GObject *cur_object = NULL;
315 /* Assertions */
316 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
317 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
319 /* Get the name */
320 gtk_tree_model_get (tree_model, iter,
321 SNIPPETS_DB_MODEL_COL_NAME, &name,
322 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
323 -1);
325 g_object_set (renderer, "text", name, NULL);
326 g_free (name);
328 if (ANJUTA_IS_SNIPPETS_GROUP (cur_object))
330 g_object_set (renderer, "editable", TRUE, NULL);
332 else
334 g_return_if_fail (ANJUTA_IS_SNIPPET (cur_object));
335 g_object_set (renderer, "editable", FALSE, NULL);
338 g_object_unref (cur_object);
342 static void
343 snippets_view_name_pixbuf_data_func (GtkTreeViewColumn *column,
344 GtkCellRenderer *renderer,
345 GtkTreeModel *tree_model,
346 GtkTreeIter *iter,
347 gpointer user_data)
349 GObject *cur_object = NULL;
350 gchar *stock_id = NULL;
352 /* Assertions */
353 g_return_if_fail (GTK_IS_CELL_RENDERER_PIXBUF (renderer));
354 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
356 gtk_tree_model_get (tree_model, iter,
357 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
358 -1);
360 if (ANJUTA_IS_SNIPPET (cur_object))
362 stock_id = GTK_STOCK_FILE;
364 else
366 g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (cur_object));
367 stock_id = GTK_STOCK_DIRECTORY;
370 g_object_unref (cur_object);
371 g_object_set (renderer, "stock-id", stock_id, NULL);
374 static void
375 snippets_view_trigger_data_func (GtkTreeViewColumn *column,
376 GtkCellRenderer *renderer,
377 GtkTreeModel *tree_model,
378 GtkTreeIter *iter,
379 gpointer user_data)
381 gchar *trigger = NULL, *trigger_markup = NULL;
383 /* Assertions */
384 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
385 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
387 gtk_tree_model_get (tree_model, iter,
388 SNIPPETS_DB_MODEL_COL_TRIGGER, &trigger,
389 -1);
390 trigger_markup = g_strconcat ("<b>", trigger, "</b>", NULL);
391 g_object_set (renderer, "markup", trigger_markup, NULL);
393 g_free (trigger);
394 g_free (trigger_markup);
397 static void
398 snippets_view_languages_data_func (GtkTreeViewColumn *column,
399 GtkCellRenderer *renderer,
400 GtkTreeModel *tree_model,
401 GtkTreeIter *iter,
402 gpointer user_data)
404 gchar *languages = NULL;
406 /* Assertions */
407 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
408 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
410 gtk_tree_model_get (tree_model, iter,
411 SNIPPETS_DB_MODEL_COL_LANGUAGES, &languages,
412 -1);
414 g_object_set (renderer, "text", languages, NULL);
416 g_free (languages);
419 static gboolean
420 snippets_db_language_filter_func (GtkTreeModel *tree_model,
421 GtkTreeIter *iter,
422 gpointer user_data)
424 SnippetsBrowser *snippets_browser = NULL;
425 IAnjutaDocumentManager *docman = NULL;
426 IAnjutaDocument *doc = NULL;
427 IAnjutaLanguage *ilanguage = NULL;
428 const gchar *language = NULL;
429 GObject *cur_object = NULL;
430 SnippetsBrowserPrivate *priv = NULL;
431 gboolean has_language = FALSE;
433 /* Assertions */
434 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
435 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data), FALSE);
436 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
437 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
439 /* If we have the setting to show all snippets or if we are editing,
440 we just return TRUE */
441 if (!snippets_browser->show_only_document_language_snippets ||
442 priv->maximized)
444 return TRUE;
447 /* Get the current object */
448 gtk_tree_model_get (tree_model, iter,
449 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
450 -1);
452 /* If it's a SnippetsGroup we render it */
453 if (ANJUTA_IS_SNIPPETS_GROUP (cur_object))
455 g_object_unref (cur_object);
456 return TRUE;
458 else
459 if (!ANJUTA_IS_SNIPPET (cur_object))
461 g_return_val_if_reached (FALSE);
464 /* Get the current document manager. If it doesn't exist we show all snippets */
465 docman = anjuta_shell_get_interface (snippets_browser->anjuta_shell,
466 IAnjutaDocumentManager,
467 NULL);
468 if (!IANJUTA_IS_DOCUMENT_MANAGER (docman))
470 g_object_unref (cur_object);
471 return TRUE;
474 ilanguage = anjuta_shell_get_interface (snippets_browser->anjuta_shell,
475 IAnjutaLanguage,
476 NULL);
477 if (!IANJUTA_IS_LANGUAGE (ilanguage))
479 g_object_unref (cur_object);
480 return TRUE;
483 /* Get the current doc and if it isn't an editor show all snippets */
484 doc = ianjuta_document_manager_get_current_document (docman, NULL);
485 if (!IANJUTA_IS_EDITOR (doc))
487 g_object_unref (cur_object);
488 return TRUE;
491 /* Get the language */
492 language = ianjuta_language_get_name_from_editor (ilanguage,
493 IANJUTA_EDITOR_LANGUAGE (doc),
494 NULL);
495 if (language == NULL)
497 g_object_unref (cur_object);
498 return TRUE;
501 has_language = snippet_has_language (ANJUTA_SNIPPET (cur_object), language);
503 g_object_unref (cur_object);
504 return has_language;
507 static void
508 init_snippets_view (SnippetsBrowser *snippets_browser)
510 SnippetsBrowserPrivate *priv = NULL;
511 GtkCellRenderer *text_renderer = NULL, *pixbuf_renderer = NULL;
512 GtkTreeViewColumn *column = NULL;
514 /* Assertions */
515 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
516 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
517 g_return_if_fail (GTK_IS_TREE_VIEW (priv->snippets_view));
518 g_return_if_fail (GTK_IS_TREE_MODEL (priv->snippets_db));
520 /* Set up the filter */
521 priv->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->snippets_db), NULL);
522 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter),
523 snippets_db_language_filter_func,
524 snippets_browser,
525 NULL);
526 gtk_tree_view_set_model (priv->snippets_view, priv->filter);
529 /* Column 1 - Name */
530 column = gtk_tree_view_column_new ();
531 text_renderer = gtk_cell_renderer_text_new ();
532 pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
533 gtk_tree_view_column_set_title (column, _("Name"));
534 gtk_tree_view_column_pack_start (column, pixbuf_renderer, FALSE);
535 gtk_tree_view_column_pack_end (column, text_renderer, FALSE);
536 gtk_tree_view_column_set_cell_data_func (column, pixbuf_renderer,
537 snippets_view_name_pixbuf_data_func,
538 snippets_browser, NULL);
539 gtk_tree_view_column_set_cell_data_func (column, text_renderer,
540 snippets_view_name_text_data_func,
541 snippets_browser, NULL);
542 g_signal_connect (text_renderer,
543 "edited",
544 G_CALLBACK (on_name_changed),
545 snippets_browser);
546 g_object_set (G_OBJECT (column), "resizable", TRUE, NULL);
547 gtk_tree_view_insert_column (priv->snippets_view, column, -1);
549 /* Column 2 - Trigger */
550 column = gtk_tree_view_column_new ();
551 text_renderer = gtk_cell_renderer_text_new ();
552 gtk_tree_view_column_set_title (column, _("Trigger"));
553 gtk_tree_view_column_pack_start (column, text_renderer, FALSE);
554 gtk_tree_view_column_set_cell_data_func (column, text_renderer,
555 snippets_view_trigger_data_func,
556 snippets_browser, NULL);
557 g_object_set (G_OBJECT (column), "resizable", TRUE, NULL);
558 gtk_tree_view_insert_column (priv->snippets_view, column, -1);
560 /* Column 3- Languages */
561 column = gtk_tree_view_column_new ();
562 text_renderer = gtk_cell_renderer_text_new ();
563 gtk_tree_view_column_set_title (column, _("Languages"));
564 gtk_tree_view_column_pack_start (column, text_renderer, FALSE);
565 gtk_tree_view_column_set_cell_data_func (column, text_renderer,
566 snippets_view_languages_data_func,
567 snippets_browser, NULL);
568 g_object_set (G_OBJECT (column), "resizable", TRUE, NULL);
569 g_object_set (G_OBJECT (column), "visible", FALSE, NULL);
570 gtk_tree_view_insert_column (priv->snippets_view, column, -1);
575 /* Public methods */
578 * snippets_browser_new:
580 * Returns: A new #SnippetsBrowser object.
582 SnippetsBrowser*
583 snippets_browser_new (void)
585 return ANJUTA_SNIPPETS_BROWSER (g_object_new (snippets_browser_get_type (), NULL));
589 * snippets_browser_load:
590 * @snippets_browser: A #SnippetsBrowser object.
591 * @snippets_db: A #SnippetsDB object from which the browser should be loaded.
592 * @snippets_interaction: A #SnippetsInteraction object which is used for interacting with the editor.
594 * Loads the #SnippetsBrowser with snippets that are found in the given database.
596 void
597 snippets_browser_load (SnippetsBrowser *snippets_browser,
598 SnippetsDB *snippets_db,
599 SnippetsInteraction *snippets_interaction)
601 SnippetsBrowserPrivate *priv = NULL;
603 /* Assertions */
604 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
605 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
606 g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
607 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
609 priv->snippets_db = snippets_db;
610 priv->snippets_interaction = snippets_interaction;
611 g_object_ref (priv->snippets_db);
612 g_object_ref (priv->snippets_interaction);
614 /* Set up the Snippets View */
615 priv->snippets_view = GTK_TREE_VIEW (gtk_tree_view_new ());
616 init_snippets_view (snippets_browser);
618 /* Set up the layout */
619 init_browser_layout (snippets_browser);
621 /* Initialize the snippet handlers */
622 init_browser_handlers (snippets_browser);
624 priv->maximized = FALSE;
628 * snippets_browser_unload:
629 * @snippets_browser: A #SnippetsBrowser object.
631 * Unloads the current #SnippetsBrowser object.
633 void
634 snippets_browser_unload (SnippetsBrowser *snippets_browser)
636 SnippetsBrowserPrivate *priv = NULL;
638 /* Assertions */
639 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
640 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
642 g_object_unref (priv->snippets_db);
643 g_object_unref (priv->snippets_interaction);
644 priv->snippets_db = NULL;
645 priv->snippets_interaction = NULL;
647 if (priv->maximized)
649 gtk_container_remove (GTK_CONTAINER (snippets_browser),
650 GTK_WIDGET (priv->browser_hpaned));
652 else
654 gtk_container_remove (GTK_CONTAINER (snippets_browser),
655 GTK_WIDGET (priv->snippets_view_vbox));
656 g_object_unref (priv->browser_hpaned);
659 g_object_unref (priv->filter);
663 * snippets_browser_show_editor:
664 * @snippets_browser: A #SnippetsBrowser object.
666 * Shows the editor attached to the browser. Warning: This will take up considerably
667 * more space than just having the browser shown.
669 void
670 snippets_browser_show_editor (SnippetsBrowser *snippets_browser)
672 SnippetsBrowserPrivate *priv = NULL;
673 GtkTreeSelection *selection = NULL;
674 GtkTreeViewColumn *col = NULL;
676 /* Assertions */
677 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
678 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
680 if (priv->maximized)
681 return;
683 /* Unparent the SnippetsView from the SnippetsBrowser */
684 g_object_ref (priv->snippets_view_vbox);
685 gtk_container_remove (GTK_CONTAINER (snippets_browser),
686 GTK_WIDGET (priv->snippets_view_vbox));
688 /* Add the SnippetsView to the HPaned */
689 gtk_paned_pack1 (GTK_PANED (priv->browser_hpaned),
690 GTK_WIDGET (priv->snippets_view_vbox),
691 TRUE, FALSE);
692 g_object_unref (priv->snippets_view_vbox);
694 /* Add the HPaned in the SnippetsBrowser */
695 gtk_box_pack_start (GTK_BOX (snippets_browser),
696 priv->browser_hpaned,
697 TRUE,
698 TRUE,
701 /* Show the editor widgets */
702 gtk_widget_show (priv->browser_hpaned);
703 gtk_widget_show (GTK_WIDGET (priv->snippets_editor));
705 priv->maximized = TRUE;
707 snippets_browser_refilter_snippets_view (snippets_browser);
709 gtk_widget_set_sensitive (GTK_WIDGET (priv->insert_button), FALSE);
711 /* Set the current snippet for the editor */
712 selection = gtk_tree_view_get_selection (priv->snippets_view);
713 on_snippets_view_selection_changed (selection, snippets_browser);
715 col = gtk_tree_view_get_column (priv->snippets_view, SNIPPETS_VIEW_COL_LANGUAGES);
716 g_object_set (col, "visible", TRUE, NULL);
721 * snippets_browser_hide_editor:
722 * @snippets_browser: A #SnippetsBrowser object.
724 * Hides the editor attached to the browser.
726 void
727 snippets_browser_hide_editor (SnippetsBrowser *snippets_browser)
729 SnippetsBrowserPrivate *priv = NULL;
730 GtkTreeViewColumn *col = NULL;
732 /* Assertions */
733 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
734 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
736 if (!priv->maximized)
737 return;
739 /* Hide the editor widgets */
740 gtk_widget_hide (GTK_WIDGET (priv->snippets_editor));
741 gtk_widget_hide (priv->browser_hpaned);
743 /* Remove the SnippetsView from the HPaned */
744 g_object_ref (priv->snippets_view_vbox);
745 gtk_container_remove (GTK_CONTAINER (priv->browser_hpaned),
746 GTK_WIDGET (priv->snippets_view_vbox));
748 /* Remove the HPaned from the SnippetsBrowser */
749 g_object_ref (priv->browser_hpaned);
750 gtk_container_remove (GTK_CONTAINER (snippets_browser),
751 GTK_WIDGET (priv->browser_hpaned));
752 g_object_unref (priv->browser_hpaned);
754 /* Add the SnippetsView to the SnippetsBrowser */
755 gtk_box_pack_start (GTK_BOX (snippets_browser),
756 GTK_WIDGET (priv->snippets_view_vbox),
757 TRUE,
758 TRUE,
760 g_object_unref (priv->snippets_view_vbox);
762 priv->maximized = FALSE;
764 snippets_browser_refilter_snippets_view (snippets_browser);
766 gtk_widget_set_sensitive (GTK_WIDGET (priv->insert_button), TRUE);
768 col = gtk_tree_view_get_column (priv->snippets_view, SNIPPETS_VIEW_COL_LANGUAGES);
769 g_object_set (col, "visible", FALSE, NULL);
773 * snippets_browser_refilter_snippets_view:
774 * @snippets_browser: A #SnippetsBrowser object.
776 * Refilters the Snippets View (if snippets_browser->show_only_document_language_snippets
777 * is TRUE), showing just the snippets of the current document. If the Snippets Browser
778 * has the editor shown, it will show all the snippets, regardless of the option.
780 void
781 snippets_browser_refilter_snippets_view (SnippetsBrowser *snippets_browser)
783 SnippetsBrowserPrivate *priv = NULL;
785 /* Assertions */
786 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
787 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
789 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
792 /* Handlers definitions */
794 static void
795 on_add_button_clicked (GtkButton *add_button,
796 gpointer user_data)
798 GtkWidget *menu = NULL, *add_snippet_menu_item = NULL,
799 *add_snippets_group_menu_item = NULL;
800 SnippetsBrowser *snippets_browser = NULL;
802 /* Assertions */
803 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
804 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
806 menu = gtk_menu_new ();
808 /* Insert the Add Snippet menu item */
809 add_snippet_menu_item = gtk_menu_item_new_with_label (_("Add Snippet…"));
810 g_signal_connect (add_snippet_menu_item,
811 "activate",
812 G_CALLBACK (on_add_snippet_menu_item_activated),
813 snippets_browser);
814 gtk_menu_shell_append (GTK_MENU_SHELL (menu),
815 GTK_WIDGET (add_snippet_menu_item));
816 gtk_widget_show (GTK_WIDGET (add_snippet_menu_item));
818 /* Insert the Add Snippets Group menu item */
819 add_snippets_group_menu_item = gtk_menu_item_new_with_label (_("Add Snippets Group…"));
820 g_signal_connect (add_snippets_group_menu_item,
821 "activate",
822 G_CALLBACK (on_add_snippets_group_menu_item_activated),
823 snippets_browser);
824 gtk_menu_shell_append (GTK_MENU_SHELL (menu),
825 GTK_WIDGET (add_snippets_group_menu_item));
826 gtk_widget_show (GTK_WIDGET (add_snippets_group_menu_item));
828 gtk_menu_popup (GTK_MENU (menu),
829 NULL, NULL, NULL, NULL, 0,
830 gtk_get_current_event_time ());
834 static void
835 on_delete_button_clicked (GtkButton *delete_button,
836 gpointer user_data)
838 GtkTreeIter iter;
839 SnippetsBrowser *snippets_browser = NULL;
840 SnippetsBrowserPrivate *priv = NULL;
841 gboolean has_selection = FALSE;
842 GObject *cur_object = NULL;
843 GtkTreeSelection *selection = NULL;
845 /* Assertions */
846 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
847 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
848 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
849 g_return_if_fail (GTK_IS_TREE_MODEL (priv->filter));
851 selection = gtk_tree_view_get_selection (priv->snippets_view);
852 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
853 has_selection = gtk_tree_selection_get_selected (selection,
854 &priv->filter,
855 &iter);
856 if (has_selection)
858 gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
859 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
860 -1);
862 if (ANJUTA_IS_SNIPPET (cur_object))
864 const gchar *trigger_key = NULL, *language = NULL;
866 trigger_key = snippet_get_trigger_key (ANJUTA_SNIPPET (cur_object));
867 language = snippet_get_any_language (ANJUTA_SNIPPET (cur_object));
868 g_return_if_fail (trigger_key != NULL);
870 snippets_db_remove_snippet (priv->snippets_db, trigger_key, language, TRUE);
872 else
874 /* It's a SnippetsGroup object */
875 const gchar *name = NULL;
877 name = snippets_group_get_name (ANJUTA_SNIPPETS_GROUP (cur_object));
878 g_return_if_fail (name != NULL);
879 snippets_db_remove_snippets_group (priv->snippets_db, name);
882 g_object_unref (cur_object);
885 snippets_db_save_snippets (priv->snippets_db);
889 static void
890 on_insert_button_clicked (GtkButton *insert_button,
891 gpointer user_data)
893 SnippetsBrowser *snippets_browser = NULL;
894 SnippetsBrowserPrivate *priv = NULL;
895 GtkTreeSelection *selection = NULL;
896 GObject *cur_object = NULL;
897 GtkTreeIter iter;
898 gboolean has_selection = FALSE;
900 /* Assertions */
901 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
902 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
903 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
904 g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (priv->snippets_interaction));
906 selection = gtk_tree_view_get_selection (priv->snippets_view);
907 has_selection = gtk_tree_selection_get_selected (selection,
908 &priv->filter,
909 &iter);
910 if (has_selection)
912 gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
913 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
914 -1);
916 if (!ANJUTA_IS_SNIPPET (cur_object))
917 return;
919 snippets_interaction_insert_snippet (priv->snippets_interaction,
920 priv->snippets_db,
921 ANJUTA_SNIPPET (cur_object),
922 TRUE);
927 static void
928 on_edit_button_toggled (GtkToggleButton *edit_button,
929 gpointer user_data)
931 SnippetsBrowser *snippets_browser = NULL;
932 SnippetsBrowserPrivate *priv = NULL;
934 /* Assertions */
935 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
936 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
937 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
939 /* Request a maximize/unmaximize (which should be caught by the plugin) */
940 if (!priv->maximized)
941 g_signal_emit_by_name (G_OBJECT (snippets_browser),
942 "maximize-request");
943 else
944 g_signal_emit_by_name (G_OBJECT (snippets_browser),
945 "unmaximize-request");
948 static void
949 on_snippets_view_row_activated (GtkTreeView *snippets_view,
950 GtkTreePath *path,
951 GtkTreeViewColumn *col,
952 gpointer user_data)
954 GtkTreeIter iter;
955 SnippetsBrowser *snippets_browser = NULL;
956 SnippetsBrowserPrivate *priv = NULL;
957 GObject *cur_object = NULL;
959 /* Assertions */
960 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
961 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
962 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
963 g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (priv->snippets_interaction));
964 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
966 gtk_tree_model_get_iter (priv->filter, &iter, path);
967 gtk_tree_model_get (priv->filter, &iter,
968 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
969 -1);
971 if (ANJUTA_IS_SNIPPET (cur_object))
972 snippets_interaction_insert_snippet (priv->snippets_interaction,
973 priv->snippets_db,
974 ANJUTA_SNIPPET (cur_object),
975 TRUE);
977 g_object_unref (cur_object);
981 static gboolean
982 on_snippets_view_query_tooltip (GtkWidget *snippets_view,
983 gint x,
984 gint y,
985 gboolean keyboard_mode,
986 GtkTooltip *tooltip,
987 gpointer user_data)
989 SnippetsBrowserPrivate *priv = NULL;
990 GtkTreeIter iter;
991 GObject *cur_object = NULL;
993 /* Assertions */
994 g_return_val_if_fail (GTK_IS_TREE_VIEW (snippets_view), FALSE);
995 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data), FALSE);
996 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
997 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db), FALSE);
998 g_return_val_if_fail (GTK_IS_TREE_MODEL (priv->filter), FALSE);
1000 /* Get the object at the current row */
1001 if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (snippets_view),
1002 &x, &y, keyboard_mode,
1003 NULL, NULL,
1004 &iter))
1005 return FALSE;
1006 gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
1007 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
1008 -1);
1010 if (ANJUTA_IS_SNIPPET (cur_object))
1012 gchar *default_content = NULL, *default_content_preview = NULL, *tooltip_text = NULL;
1014 default_content = snippet_get_default_content (ANJUTA_SNIPPET (cur_object),
1015 G_OBJECT (priv->snippets_db),
1016 "");
1018 default_content_preview = g_strndup (default_content, TOOLTIP_SIZE);
1019 tooltip_text = g_strconcat (default_content_preview, " …", NULL);
1020 gtk_tooltip_set_text (tooltip, tooltip_text);
1022 g_free (default_content);
1023 g_free (default_content_preview);
1024 g_free (tooltip_text);
1025 g_object_unref (cur_object);
1027 return TRUE;
1030 g_object_unref (cur_object);
1031 return FALSE;
1035 static void
1036 on_name_changed (GtkCellRendererText *renderer,
1037 gchar *path_string,
1038 gchar *new_text,
1039 gpointer user_data)
1041 SnippetsBrowser *snippets_browser = NULL;
1042 SnippetsBrowserPrivate *priv = NULL;
1043 GtkTreePath *path = NULL;
1044 GtkTreeIter iter;
1045 gchar *old_name = NULL;
1047 /* Assertions */
1048 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
1049 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
1050 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
1052 path = gtk_tree_path_new_from_string (path_string);
1053 gtk_tree_model_get_iter (priv->filter, &iter, path);
1054 gtk_tree_model_get (priv->filter, &iter,
1055 SNIPPETS_DB_MODEL_COL_NAME, &old_name,
1056 -1);
1058 snippets_db_set_snippets_group_name (priv->snippets_db, old_name, new_text);
1059 snippets_browser_refilter_snippets_view (snippets_browser);
1061 snippets_db_save_snippets (priv->snippets_db);
1063 gtk_tree_path_free (path);
1064 g_free (old_name);
1068 static void
1069 on_add_snippet_menu_item_activated (GtkMenuItem *menu_item,
1070 gpointer user_data)
1072 SnippetsBrowserPrivate *priv = NULL;
1074 /* Assertions */
1075 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
1076 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
1078 /* Request a maximize/unmaximize (which should be caught by the plugin) */
1079 if (!priv->maximized)
1080 g_signal_emit_by_name (G_OBJECT (user_data),
1081 "maximize-request");
1083 snippets_editor_set_snippet_new (priv->snippets_editor);
1086 static void
1087 on_add_snippets_group_menu_item_activated (GtkMenuItem *menu_item,
1088 gpointer user_data)
1090 SnippetsBrowser *snippets_browser = NULL;
1091 SnippetsBrowserPrivate *priv = NULL;
1092 GtkTreeIter iter;
1093 AnjutaSnippetsGroup *snippets_group = NULL;
1095 /* Assertions */
1096 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
1097 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
1098 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
1099 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
1101 snippets_group = snippets_group_new (NEW_SNIPPETS_GROUP_NAME);
1102 snippets_db_add_snippets_group (priv->snippets_db, snippets_group, FALSE);
1104 /* The snippets database shouldn't be empty here */
1105 if (!gtk_tree_model_get_iter_first (priv->filter, &iter))
1106 g_return_if_reached ();
1110 gchar *name = NULL;
1112 gtk_tree_model_get (priv->filter, &iter,
1113 SNIPPETS_DB_MODEL_COL_NAME, &name,
1114 -1);
1115 if (!g_strcmp0 (name, NEW_SNIPPETS_GROUP_NAME))
1117 GtkTreePath *path = gtk_tree_model_get_path (priv->filter, &iter);
1118 GtkTreeViewColumn *col = gtk_tree_view_get_column (priv->snippets_view,
1119 SNIPPETS_VIEW_COL_NAME);
1120 gtk_tree_view_set_cursor (priv->snippets_view, path, col, TRUE);
1122 /* We save the database after the cursor was set. */
1123 snippets_db_save_snippets (priv->snippets_db);
1125 gtk_tree_path_free (path);
1126 g_free (name);
1127 return;
1130 g_free (name);
1132 } while (gtk_tree_model_iter_next (priv->filter, &iter));
1134 /* We should have found the newly added group */
1135 g_return_if_reached ();
1139 static void
1140 on_snippets_view_selection_changed (GtkTreeSelection *tree_selection,
1141 gpointer user_data)
1143 SnippetsBrowser *snippets_browser = NULL;
1144 SnippetsBrowserPrivate *priv = NULL;
1145 GtkTreeIter iter;
1146 GObject *cur_object = NULL;
1148 /* Assertions */
1149 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
1150 snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
1151 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
1152 g_return_if_fail (GTK_IS_TREE_MODEL (priv->filter));
1154 if (!gtk_tree_selection_get_selected (tree_selection, &priv->filter, &iter))
1156 snippets_editor_set_snippet (priv->snippets_editor, NULL);
1157 return;
1160 gtk_tree_model_get (priv->filter, &iter,
1161 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
1162 -1);
1164 /* We only change the snippet of the editor if the browser has the editor shown */
1165 if (ANJUTA_IS_SNIPPET (cur_object) && priv->maximized)
1166 snippets_editor_set_snippet (priv->snippets_editor,
1167 ANJUTA_SNIPPET (cur_object));
1168 else if (priv->maximized)
1169 snippets_editor_set_snippet (priv->snippets_editor, NULL);
1171 g_object_unref (cur_object);
1175 static void
1176 on_snippets_editor_snippet_saved (SnippetsEditor *snippets_editor,
1177 GObject *snippet,
1178 gpointer user_data)
1180 SnippetsBrowserPrivate *priv = NULL;
1181 GtkTreePath *path = NULL;
1183 /* Assertions */
1184 g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
1185 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
1186 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
1188 /* Focus on the newly inserted snippet (the path is valid because when the editor
1189 is shown, all snippets are visibile.)*/
1190 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
1191 path = snippets_db_get_path_at_object (priv->snippets_db, snippet);
1192 gtk_tree_view_set_cursor (priv->snippets_view, path, NULL, FALSE);
1194 /* We save the database after we set the cursor */
1195 snippets_db_save_snippets (priv->snippets_db);
1199 static void
1200 on_snippets_editor_close_request (SnippetsEditor *snippets_editor,
1201 gpointer user_data)
1203 SnippetsBrowserPrivate *priv = NULL;
1205 /* Assertions */
1206 g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
1207 priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
1209 gtk_toggle_button_set_active (priv->edit_button, FALSE);
1212 GtkWidget*
1213 snippets_browser_get_grip (SnippetsBrowser *snippets_browser)
1215 return snippets_browser->priv->grip;