Updated Spanish translation
[anjuta.git] / plugins / snippets-manager / snippets-editor.c
blob0d25770e91275ce90e02823c957bb2646a8485ad
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 snippets-editor.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-editor.h"
23 #include "snippet-variables-store.h"
24 #include <string.h>
25 #include <libanjuta/interfaces/ianjuta-language.h>
26 #include <libanjuta/interfaces/ianjuta-editor-language.h>
28 #define EDITOR_UI PACKAGE_DATA_DIR"/glade/snippets-editor.ui"
30 #define ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPETS_EDITOR, SnippetsEditorPrivate))
32 #define LOCAL_TYPE_STR "Snippet"
33 #define GLOBAL_TYPE_STR "Anjuta"
35 #define UNDEFINED_BG_COLOR "#ffbaba"
37 #define NAME_COL_TITLE _("Name")
38 #define TYPE_COL_TITLE _("Type")
39 #define DEFAULT_COL_TITLE _("Default value")
40 #define INSTANT_COL_TITLE _("Instant value")
42 #define MIN_NAME_COL_WIDTH 120
44 #define NEW_VAR_NAME "new_variable"
46 #define GROUPS_COL_NAME 0
48 #define ERROR_LANG_NULL _("<b>Error:</b> You must choose at least one language for the snippet!")
49 #define ERROR_LANG_CONFLICT _("<b>Error:</b> The trigger key is already in use for one of the languages!")
50 #define ERROR_TRIGGER_NOT_VALID _("<b>Error:</b> The trigger key can only contain alphanumeric characters and \"_\"!")
51 #define ERROR_TRIGGER_NULL _("<b>Error:</b> You haven't entered a trigger key for the snippet!")
53 #define SNIPPET_VAR_START "${"
54 #define SNIPPET_VAR_END "}"
55 #define IS_SNIPPET_VAR_START(text, index) (text[index] == '$' && text[index + 1] == '{')
56 #define IS_SNIPPET_VAR_END(text, index) (text[index] == '}')
58 struct _SnippetsEditorPrivate
60 SnippetsDB *snippets_db;
61 AnjutaSnippet *snippet;
62 AnjutaSnippet *backup_snippet;
63 GtkListStore *group_store;
64 GtkListStore *lang_store;
66 /* A tree model with 2 entries: LOCAL_TYPE_STR and GLOBAL_TYPE_STR to be used
67 by the variables view on the type column */
68 GtkListStore *type_model;
70 /* Snippet Content editor widgets */
71 GtkTextView *content_text_view; /* TODO - this should be changed later with GtkSourceView */
72 GtkToggleButton *preview_button;
74 /* Snippet properties widgets */
75 GtkEntry *name_entry;
76 GtkEntry *trigger_entry;
77 GtkEntry *keywords_entry;
78 GtkComboBox *languages_combo_box;
79 GtkComboBox *snippets_group_combo_box;
80 GtkImage *languages_notify;
81 GtkImage *group_notify;
82 GtkImage *trigger_notify;
83 GtkImage *name_notify;
85 /* If one of the following variables is TRUE, then we have an error and the Save Button
86 will be insensitive */
87 gboolean languages_error;
88 gboolean group_error;
89 gboolean trigger_error;
91 /* Variables widgets */
92 GtkTreeView *variables_view;
93 GtkButton *variable_add_button;
94 GtkButton *variable_remove_button;
95 GtkButton *variable_insert_button;
97 /* Variables tree model */
98 SnippetVarsStore *vars_store;
99 GtkTreeModel *vars_store_sorted;
101 /* Variables view cell renderers */
102 GtkCellRenderer *name_combo_cell;
103 GtkCellRenderer *type_combo_cell;
104 GtkCellRenderer *type_pixbuf_cell;
105 GtkCellRenderer *default_text_cell;
106 GtkCellRenderer *instant_text_cell;
108 /* Editor widgets */
109 GtkButton *save_button;
110 GtkButton *close_button;
111 GtkAlignment *editor_alignment;
113 /* So it will guard deleting the priv->snippet by calling snippets_editor_set_snippet
114 with snippet == NULL after deleting the backup_snippet in the saving handler. */
115 gboolean saving_snippet;
119 enum
121 VARS_VIEW_COL_NAME = 0,
122 VARS_VIEW_COL_TYPE,
123 VARS_VIEW_COL_DEFAULT,
124 VARS_VIEW_COL_INSTANT
127 enum
129 LANG_MODEL_COL_IN_SNIPPET = 0,
130 LANG_MODEL_COL_NAME,
131 LANG_MODEL_COL_N
134 /* Handlers */
135 static void on_preview_button_toggled (GtkToggleButton *preview_button,
136 gpointer user_data);
137 static void on_save_button_clicked (GtkButton *save_button,
138 gpointer user_data);
139 static void on_close_button_clicked (GtkButton *close_button,
140 gpointer user_data);
141 static void on_name_combo_cell_edited (GtkCellRendererText *cell,
142 gchar *path_string,
143 gchar *new_string,
144 gpointer user_data);
145 static void on_type_combo_cell_changed (GtkCellRendererCombo *cell,
146 gchar *path_string,
147 gchar *new_string,
148 gpointer user_data);
149 static void on_default_text_cell_edited (GtkCellRendererText *cell,
150 gchar *path_string,
151 gchar *new_string,
152 gpointer user_data);
153 static void on_variables_view_row_activated (GtkTreeView *tree_view,
154 GtkTreePath *path,
155 GtkTreeViewColumn *col,
156 gpointer user_data);
157 static void on_variable_add_button_clicked (GtkButton *variable_add_button,
158 gpointer user_data);
159 static void on_variable_remove_button_clicked (GtkButton *variable_remove_button,
160 gpointer user_data);
161 static void on_variable_insert_button_clicked (GtkButton *variable_insert_button,
162 gpointer user_data);
163 static void on_variables_view_selection_changed (GtkTreeSelection *selection,
164 gpointer user_data);
165 static void on_snippets_group_combo_box_changed (GtkComboBox *combo_box,
166 gpointer user_data);
167 static void on_languages_combo_box_changed (GtkComboBox *combo_box,
168 gpointer user_data);
169 static void on_trigger_entry_text_changed (GObject *entry_obj,
170 GParamSpec *param_spec,
171 gpointer user_data);
172 static void on_name_entry_text_changed (GObject *entry_obj,
173 GParamSpec *param_spec,
174 gpointer user_data);
176 G_DEFINE_TYPE (SnippetsEditor, snippets_editor, GTK_TYPE_BOX);
179 static void
180 snippets_editor_dispose (GObject *object)
182 SnippetsEditorPrivate *priv = NULL;
184 /* Assertions */
185 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (object));
186 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (object);
188 if (ANJUTA_IS_SNIPPET (priv->snippet))
189 g_object_unref (priv->snippet);
191 G_OBJECT_CLASS (snippets_editor_parent_class)->dispose (G_OBJECT (object));
194 static void
195 snippets_editor_class_init (SnippetsEditorClass* klass)
197 GObjectClass *g_object_class = NULL;
199 /* Assertions */
200 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR_CLASS (klass));
202 g_object_class = G_OBJECT_CLASS (klass);
203 g_object_class->dispose = snippets_editor_dispose;
205 /* The SnippetsEditor saved the snippet. Basically, the SnippetsBrowser should
206 focus on the row where the snippet was saved. This is needed because when the
207 snippet is saved, the old one is deleted and the new one is inserted. The given
208 object is the newly inserted snippet. */
209 g_signal_new ("snippet-saved",
210 ANJUTA_TYPE_SNIPPETS_EDITOR,
211 G_SIGNAL_RUN_LAST,
212 G_STRUCT_OFFSET (SnippetsEditorClass, snippet_saved),
213 NULL, NULL,
214 g_cclosure_marshal_VOID__OBJECT,
215 G_TYPE_NONE,
217 G_TYPE_OBJECT,
218 NULL);
220 g_signal_new ("close-request",
221 ANJUTA_TYPE_SNIPPETS_EDITOR,
222 G_SIGNAL_RUN_LAST,
223 G_STRUCT_OFFSET (SnippetsEditorClass, close_request),
224 NULL, NULL,
225 g_cclosure_marshal_VOID__VOID,
226 G_TYPE_NONE,
228 NULL);
230 g_type_class_add_private (klass, sizeof (SnippetsEditorPrivate));
233 static void
234 snippets_editor_init (SnippetsEditor* snippets_editor)
236 SnippetsEditorPrivate* priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
238 snippets_editor->priv = priv;
240 /* Initialize the private field */
241 priv->snippets_db = NULL;
242 priv->snippet = NULL;
243 priv->backup_snippet = NULL;
244 priv->group_store = NULL;
245 priv->lang_store = NULL;
247 priv->type_model = NULL;
249 priv->content_text_view = NULL;
250 priv->preview_button = NULL;
252 priv->name_entry = NULL;
253 priv->trigger_entry = NULL;
254 priv->languages_combo_box = NULL;
255 priv->snippets_group_combo_box = NULL;
256 priv->keywords_entry = NULL;
257 priv->languages_notify = NULL;
258 priv->group_notify = NULL;
259 priv->trigger_notify = NULL;
261 priv->variables_view = NULL;
262 priv->variable_add_button = NULL;
263 priv->variable_remove_button = NULL;
264 priv->variable_insert_button = NULL;
266 priv->vars_store = NULL;
267 priv->vars_store_sorted = NULL;
269 priv->name_combo_cell = NULL;
270 priv->type_combo_cell = NULL;
271 priv->type_pixbuf_cell = NULL;
272 priv->default_text_cell = NULL;
273 priv->instant_text_cell = NULL;
275 priv->save_button = NULL;
276 priv->close_button = NULL;
277 priv->editor_alignment = NULL;
279 priv->saving_snippet = FALSE;
282 static void
283 load_snippets_editor_ui (SnippetsEditor *snippets_editor)
285 GtkBuilder *bxml = NULL;
286 SnippetsEditorPrivate *priv = NULL;
287 GError *error = NULL;
289 /* Assertions */
290 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
291 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
293 /* Load the UI file */
294 bxml = gtk_builder_new ();
295 if (!gtk_builder_add_from_file (bxml, EDITOR_UI, &error))
297 g_warning ("Couldn't load editor ui file: %s", error->message);
298 g_error_free (error);
301 /* Edit content widgets */
302 priv->content_text_view = GTK_TEXT_VIEW (gtk_builder_get_object (bxml, "content_text_view"));
303 priv->preview_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (bxml, "preview_button"));
304 g_return_if_fail (GTK_IS_TEXT_VIEW (priv->content_text_view));
305 g_return_if_fail (GTK_IS_TOGGLE_BUTTON (priv->preview_button));
307 /* Edit properties widgets */
308 priv->name_entry = GTK_ENTRY (gtk_builder_get_object (bxml, "name_entry"));
309 priv->trigger_entry = GTK_ENTRY (gtk_builder_get_object (bxml, "trigger_entry"));
310 priv->languages_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (bxml, "languages_combo_box"));
311 priv->snippets_group_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (bxml, "snippets_group_combo_box"));
312 priv->languages_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "languages_notify"));
313 priv->group_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "group_notify"));
314 priv->trigger_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "trigger_notify"));
315 priv->name_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "name_notify"));
316 priv->keywords_entry = GTK_ENTRY (gtk_builder_get_object (bxml, "keywords_entry"));
317 g_return_if_fail (GTK_IS_ENTRY (priv->name_entry));
318 g_return_if_fail (GTK_IS_ENTRY (priv->trigger_entry));
319 g_return_if_fail (GTK_IS_COMBO_BOX (priv->languages_combo_box));
320 g_return_if_fail (GTK_IS_COMBO_BOX (priv->snippets_group_combo_box));
321 g_return_if_fail (GTK_IS_IMAGE (priv->languages_notify));
322 g_return_if_fail (GTK_IS_IMAGE (priv->group_notify));
323 g_return_if_fail (GTK_IS_ENTRY (priv->keywords_entry));
325 /* Edit variables widgets */
326 priv->variables_view = GTK_TREE_VIEW (gtk_builder_get_object (bxml, "variables_view"));
327 priv->variable_add_button = GTK_BUTTON (gtk_builder_get_object (bxml, "variable_add_button"));
328 priv->variable_remove_button = GTK_BUTTON (gtk_builder_get_object (bxml, "variable_remove_button"));
329 priv->variable_insert_button = GTK_BUTTON (gtk_builder_get_object (bxml, "variable_insert_button"));
330 g_return_if_fail (GTK_IS_TREE_VIEW (priv->variables_view));
331 g_return_if_fail (GTK_IS_BUTTON (priv->variable_add_button));
332 g_return_if_fail (GTK_IS_BUTTON (priv->variable_remove_button));
333 g_return_if_fail (GTK_IS_BUTTON (priv->variable_insert_button));
335 /* General widgets */
336 priv->save_button = GTK_BUTTON (gtk_builder_get_object (bxml, "save_button"));
337 priv->close_button = GTK_BUTTON (gtk_builder_get_object (bxml, "close_button"));
338 priv->editor_alignment = GTK_ALIGNMENT (gtk_builder_get_object (bxml, "editor_alignment"));
339 g_return_if_fail (GTK_IS_BUTTON (priv->save_button));
340 g_return_if_fail (GTK_IS_BUTTON (priv->close_button));
341 g_return_if_fail (GTK_IS_ALIGNMENT (priv->editor_alignment));
343 /* Add the gtk_alignment as the child of the snippets editor */
344 gtk_box_pack_start (GTK_BOX (snippets_editor),
345 GTK_WIDGET (priv->editor_alignment),
346 TRUE,
347 TRUE,
350 g_object_unref (bxml);
353 /* Variables View cell data functions and the sort function */
355 static gint
356 compare_var_in_snippet (gboolean in_snippet1, gboolean in_snippet2)
358 /* Those that are in snippet go before those that aren't */
359 if ((in_snippet1 && in_snippet2) || (!in_snippet1 && !in_snippet2))
360 return 0;
361 if (in_snippet1)
362 return -1;
363 return 1;
366 static gint
367 vars_store_sort_func (GtkTreeModel *vars_store,
368 GtkTreeIter *iter1,
369 GtkTreeIter *iter2,
370 gpointer user_data)
372 gboolean in_snippet1 = FALSE, in_snippet2 = FALSE;
373 gchar *name1 = NULL, *name2 = NULL;
374 gint compare_value = 0;
376 /* Get the values from the model */
377 gtk_tree_model_get (vars_store, iter1,
378 VARS_STORE_COL_NAME, &name1,
379 VARS_STORE_COL_IN_SNIPPET, &in_snippet1,
380 -1);
381 gtk_tree_model_get (vars_store, iter2,
382 VARS_STORE_COL_NAME, &name2,
383 VARS_STORE_COL_IN_SNIPPET, &in_snippet2,
384 -1);
386 /* We first check if both variables are in the snippet */
387 compare_value = compare_var_in_snippet (in_snippet1, in_snippet2);
389 /* If we didn't got a compare_value until this point, we compare by name */
390 if (!compare_value)
391 compare_value = g_strcmp0 (name1, name2);
393 g_free (name1);
394 g_free (name2);
396 return compare_value;
399 static void
400 set_cell_colors (GtkCellRenderer *cell,
401 SnippetVariableType type,
402 gboolean undefined)
404 if (undefined && type == SNIPPET_VAR_TYPE_GLOBAL)
405 g_object_set (cell, "cell-background", UNDEFINED_BG_COLOR, NULL);
406 else
407 g_object_set (cell, "cell-background-set", FALSE, NULL);
410 static void
411 focus_on_in_snippet_variable (GtkTreeView *vars_view,
412 GtkTreeModel *vars_model,
413 const gchar *var_name,
414 GtkTreeViewColumn *col,
415 gboolean start_editing)
417 GtkTreeIter iter;
418 gchar *name = NULL;
419 gboolean in_snippet = FALSE;
421 /* Assertions */
422 g_return_if_fail (GTK_IS_TREE_VIEW (vars_view));
423 g_return_if_fail (GTK_IS_TREE_MODEL (vars_model));
425 if (!gtk_tree_model_get_iter_first (vars_model, &iter))
426 return;
428 /* We search for a variable which is in the snippet with the given name. If we find
429 it, we focus the cursor on it. */
432 gtk_tree_model_get (vars_model, &iter,
433 VARS_STORE_COL_NAME, &name,
434 VARS_STORE_COL_IN_SNIPPET, &in_snippet,
435 -1);
437 if (!g_strcmp0 (var_name, name) && in_snippet)
439 GtkTreePath *path = gtk_tree_model_get_path (vars_model, &iter);
441 gtk_tree_view_set_cursor (vars_view, path, col, start_editing);
443 gtk_tree_path_free (path);
445 g_free (name);
446 return;
449 g_free (name);
451 } while (gtk_tree_model_iter_next (vars_model, &iter));
454 static void
455 change_snippet_variable_name_in_content (SnippetsEditor *snippets_editor,
456 const gchar *old_var_name,
457 const gchar *new_var_name)
459 SnippetsEditorPrivate *priv = NULL;
460 gchar *old_content = NULL;
461 GString *updated_content = NULL, *cur_var_name = NULL;
462 gint i = 0, j = 0, old_content_len = 0;
463 GtkTextBuffer *buffer = NULL;
465 /* Assertions */
466 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
467 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
469 buffer = gtk_text_view_get_buffer (priv->content_text_view);
471 /* We should have a snippet loaded if we got in this function */
472 if (!ANJUTA_IS_SNIPPET (priv->snippet))
473 g_return_if_reached ();
475 /* Get the content depending on what is shown in the content editor right now */
476 if (gtk_toggle_button_get_active (priv->preview_button))
478 old_content = g_strdup (snippet_get_content (priv->snippet));
480 else
482 GtkTextIter start_iter, end_iter;
484 gtk_text_buffer_get_start_iter (buffer, &start_iter);
485 gtk_text_buffer_get_end_iter (buffer, &end_iter);
486 old_content = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
489 old_content_len = strlen (old_content);
490 updated_content = g_string_new ("");
492 for (i = 0; i < old_content_len; i ++)
494 if (IS_SNIPPET_VAR_START (old_content, i))
496 /* We add the snippet var start -- "${" and continue with the variable name */
497 //j = i;
498 i += strlen (SNIPPET_VAR_START) - 1;
499 j = i + 1;
500 g_string_append (updated_content, SNIPPET_VAR_START);
501 cur_var_name = g_string_new ("");
503 /* We add all the chars until we got to the mark of the variable end or
504 to the end of the text */
505 while (!IS_SNIPPET_VAR_END (old_content, j) && j < old_content_len)
506 g_string_append_c (cur_var_name, old_content[j ++]);
508 /* If we found a valid variable and it's the variable we want to replace */
509 if (IS_SNIPPET_VAR_END (old_content, j) &&
510 !g_strcmp0 (cur_var_name->str, old_var_name))
512 g_string_append (updated_content, new_var_name);
513 g_string_append (updated_content, SNIPPET_VAR_END);
514 i = j;
517 g_string_free (cur_var_name, TRUE);
520 else
522 g_string_append_c (updated_content, old_content[i]);
526 /* We update the content */
527 snippet_set_content (priv->snippet, updated_content->str);
529 /* And update the content text view if neccesary */
530 if (!gtk_toggle_button_get_active (priv->preview_button))
532 GtkTextBuffer *buffer = gtk_text_view_get_buffer (priv->content_text_view);
533 gtk_text_buffer_set_text (buffer, updated_content->str, -1);
536 g_string_free (updated_content, TRUE);
537 g_free (old_content);
540 static void
541 variables_view_name_combo_data_func (GtkTreeViewColumn *column,
542 GtkCellRenderer *cell,
543 GtkTreeModel *tree_model,
544 GtkTreeIter *iter,
545 gpointer user_data)
547 gboolean in_snippet = FALSE, undefined = FALSE;
548 gchar *name = NULL, *name_with_markup = NULL;
549 SnippetVariableType type;
551 gtk_tree_model_get (tree_model, iter,
552 VARS_STORE_COL_NAME, &name,
553 VARS_STORE_COL_IN_SNIPPET, &in_snippet,
554 VARS_STORE_COL_UNDEFINED, &undefined,
555 VARS_STORE_COL_TYPE, &type,
556 -1);
558 if (in_snippet)
559 name_with_markup = g_strconcat ("<b>", name, "</b>", NULL);
560 else
561 name_with_markup = g_strdup (name);
563 g_object_set (cell, "editable", in_snippet, NULL);
564 g_object_set (cell, "markup", name_with_markup, NULL);
566 set_cell_colors (cell, type, undefined);
568 g_free (name);
569 g_free (name_with_markup);
572 static void
573 variables_view_type_combo_data_func (GtkTreeViewColumn *column,
574 GtkCellRenderer *cell,
575 GtkTreeModel *tree_model,
576 GtkTreeIter *iter,
577 gpointer user_data)
579 SnippetVariableType type;
580 gboolean in_snippet = FALSE;
581 gboolean undefined = FALSE;
583 gtk_tree_model_get (tree_model, iter,
584 VARS_STORE_COL_TYPE, &type,
585 VARS_STORE_COL_IN_SNIPPET, &in_snippet,
586 VARS_STORE_COL_UNDEFINED, &undefined,
587 -1);
589 if (type == SNIPPET_VAR_TYPE_LOCAL)
590 g_object_set (cell, "text", LOCAL_TYPE_STR, NULL);
591 else
592 if (type == SNIPPET_VAR_TYPE_GLOBAL)
593 g_object_set (cell, "text", GLOBAL_TYPE_STR, NULL);
594 else
595 g_return_if_reached ();
597 set_cell_colors (cell, type, undefined);
599 g_object_set (cell, "sensitive", in_snippet, NULL);
600 g_object_set (cell, "editable", in_snippet, NULL);
603 static void
604 variables_view_type_pixbuf_data_func (GtkTreeViewColumn *column,
605 GtkCellRenderer *cell,
606 GtkTreeModel *tree_model,
607 GtkTreeIter *iter,
608 gpointer user_data)
610 SnippetVariableType type;
611 gboolean undefined = FALSE;
613 gtk_tree_model_get (tree_model, iter,
614 VARS_STORE_COL_TYPE, &type,
615 VARS_STORE_COL_UNDEFINED, &undefined,
616 -1);
618 if (type == SNIPPET_VAR_TYPE_GLOBAL && undefined)
619 g_object_set (cell, "visible", TRUE, NULL);
620 else
621 g_object_set (cell, "visible", FALSE, NULL);
623 set_cell_colors (cell, type, undefined);
626 static void
627 variables_view_default_text_data_func (GtkTreeViewColumn *column,
628 GtkCellRenderer *cell,
629 GtkTreeModel *tree_model,
630 GtkTreeIter *iter,
631 gpointer user_data)
633 gchar *default_value = NULL;
634 gboolean in_snippet = FALSE, undefined = FALSE;
635 SnippetVariableType type;
637 gtk_tree_model_get (tree_model, iter,
638 VARS_STORE_COL_DEFAULT_VALUE, &default_value,
639 VARS_STORE_COL_IN_SNIPPET, &in_snippet,
640 VARS_STORE_COL_UNDEFINED, &undefined,
641 VARS_STORE_COL_TYPE, &type,
642 -1);
644 g_object_set (cell, "text", default_value, NULL);
645 g_object_set (cell, "editable", in_snippet, NULL);
647 set_cell_colors (cell, type, undefined);
649 g_free (default_value);
652 static void
653 variables_view_instant_text_data_func (GtkTreeViewColumn *column,
654 GtkCellRenderer *cell,
655 GtkTreeModel *tree_model,
656 GtkTreeIter *iter,
657 gpointer user_data)
659 gboolean undefined = FALSE;
660 SnippetVariableType type;
662 gtk_tree_model_get (tree_model, iter,
663 VARS_STORE_COL_UNDEFINED, &undefined,
664 VARS_STORE_COL_TYPE, &type,
665 -1);
667 set_cell_colors (cell, type, undefined);
671 static void
672 init_variables_view (SnippetsEditor *snippets_editor)
674 SnippetsEditorPrivate *priv = NULL;
675 GtkTreeViewColumn *col = NULL;
676 GtkTreeIter iter;
678 /* Assertions */
679 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
680 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
682 /* Initialize the type model */
683 priv->type_model = gtk_list_store_new (1, G_TYPE_STRING);
684 gtk_list_store_append (priv->type_model, &iter);
685 gtk_list_store_set (priv->type_model, &iter,
686 0, LOCAL_TYPE_STR,
687 -1);
688 gtk_list_store_append (priv->type_model, &iter);
689 gtk_list_store_set (priv->type_model, &iter,
690 0, GLOBAL_TYPE_STR,
691 -1);
694 /* Initialize the sorted model */
695 priv->vars_store_sorted = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (priv->vars_store));
696 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (priv->vars_store_sorted),
697 vars_store_sort_func,
698 NULL, NULL);
699 gtk_tree_view_set_model (priv->variables_view, GTK_TREE_MODEL (priv->vars_store_sorted));
701 /* Column 1 - Name */
702 col = gtk_tree_view_column_new ();
703 priv->name_combo_cell = gtk_cell_renderer_combo_new ();
704 gtk_tree_view_column_set_title (col, NAME_COL_TITLE);
705 gtk_tree_view_column_pack_start (col, priv->name_combo_cell, FALSE);
706 gtk_tree_view_column_set_cell_data_func (col, priv->name_combo_cell,
707 variables_view_name_combo_data_func,
708 snippets_editor, NULL);
709 g_object_set (col, "resizable", TRUE, NULL);
710 g_object_set (col, "min-width", MIN_NAME_COL_WIDTH, NULL);
711 g_object_set (priv->name_combo_cell, "has-entry", TRUE, NULL);
712 g_object_set (priv->name_combo_cell, "model",
713 snippets_db_get_global_vars_model (priv->snippets_db), NULL);
714 g_object_set (priv->name_combo_cell, "text-column",
715 GLOBAL_VARS_MODEL_COL_NAME, NULL);
716 gtk_tree_view_insert_column (priv->variables_view, col, -1);
718 /* Column 2 - Type */
719 col = gtk_tree_view_column_new ();
720 priv->type_combo_cell = gtk_cell_renderer_combo_new ();
721 priv->type_pixbuf_cell = gtk_cell_renderer_pixbuf_new ();
722 gtk_tree_view_column_set_title (col, TYPE_COL_TITLE);
723 gtk_tree_view_column_pack_start (col, priv->type_combo_cell, FALSE);
724 gtk_tree_view_column_pack_end (col, priv->type_pixbuf_cell, FALSE);
725 g_object_set (priv->type_combo_cell, "model", priv->type_model, NULL);
726 g_object_set (priv->type_combo_cell, "text-column", 0, NULL);
727 g_object_set (priv->type_combo_cell, "has-entry", FALSE, NULL);
728 gtk_tree_view_column_set_cell_data_func (col, priv->type_combo_cell,
729 variables_view_type_combo_data_func,
730 snippets_editor, NULL);
731 g_object_set (priv->type_pixbuf_cell, "stock-id", GTK_STOCK_DIALOG_WARNING, NULL);
732 gtk_tree_view_column_set_cell_data_func (col, priv->type_pixbuf_cell,
733 variables_view_type_pixbuf_data_func,
734 snippets_editor, NULL);
735 gtk_tree_view_insert_column (priv->variables_view, col, -1);
737 /* Column 3 - Default Value (just for those variables that are in the snippet) */
738 col = gtk_tree_view_column_new ();
739 priv->default_text_cell = gtk_cell_renderer_text_new ();
740 gtk_tree_view_column_set_title (col, DEFAULT_COL_TITLE);
741 gtk_tree_view_column_pack_start (col, priv->default_text_cell, FALSE);
742 gtk_tree_view_column_set_cell_data_func (col, priv->default_text_cell,
743 variables_view_default_text_data_func,
744 snippets_editor, NULL);
745 g_object_set (col, "resizable", TRUE, NULL);
746 gtk_tree_view_insert_column (priv->variables_view, col, -1);
748 /* Column 4 - Instant value */
749 priv->instant_text_cell = gtk_cell_renderer_text_new ();
750 col = gtk_tree_view_column_new_with_attributes (INSTANT_COL_TITLE,
751 priv->instant_text_cell,
752 "text", VARS_STORE_COL_INSTANT_VALUE,
753 NULL);
754 gtk_tree_view_column_set_cell_data_func (col, priv->instant_text_cell,
755 variables_view_instant_text_data_func,
756 snippets_editor, NULL);
757 g_object_set (col, "resizable", TRUE, NULL);
758 g_object_set (G_OBJECT (priv->instant_text_cell), "editable", FALSE, NULL);
759 gtk_tree_view_insert_column (priv->variables_view, col, -1);
761 /* Initialize the buttons as insensitive */
762 g_object_set (priv->variable_add_button, "sensitive", FALSE, NULL);
763 g_object_set (priv->variable_remove_button, "sensitive", FALSE, NULL);
764 g_object_set (priv->variable_insert_button, "sensitive", FALSE, NULL);
768 static void
769 focus_snippets_group_combo_box (SnippetsEditor *snippets_editor)
771 SnippetsEditorPrivate *priv = NULL;
772 AnjutaSnippetsGroup *parent_snippets_group = NULL;
773 const gchar *parent_snippets_group_name = NULL;
774 gchar *cur_group_name = NULL;
775 GtkTreeIter iter;
777 /* Assertions */
778 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
779 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
781 /* We initialize it */
782 g_object_set (priv->snippets_group_combo_box, "active", -1, NULL);
784 /* If we have a snippet and it has a snippets group. */
785 if (ANJUTA_IS_SNIPPET (priv->snippet) &&
786 ANJUTA_IS_SNIPPETS_GROUP (priv->snippet->parent_snippets_group))
788 parent_snippets_group = ANJUTA_SNIPPETS_GROUP (priv->snippet->parent_snippets_group);
789 parent_snippets_group_name = snippets_group_get_name (parent_snippets_group);
791 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->group_store), &iter))
792 return;
796 gtk_tree_model_get (GTK_TREE_MODEL (priv->group_store), &iter,
797 GROUPS_COL_NAME, &cur_group_name,
798 -1);
800 if (!g_strcmp0 (cur_group_name, parent_snippets_group_name))
802 gtk_combo_box_set_active_iter (priv->snippets_group_combo_box, &iter);
804 g_free (cur_group_name);
805 return;
808 g_free (cur_group_name);
810 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->group_store), &iter));
815 static void
816 init_snippets_group_combo_box (SnippetsEditor *snippets_editor)
818 SnippetsEditorPrivate *priv = NULL;
819 GtkCellRenderer *cell = NULL;
821 /* Assertions */
822 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
823 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
825 /* Init the tree model */
826 priv->group_store = gtk_list_store_new (1, G_TYPE_STRING);
828 /* Set the tree model to the combo-box */
829 gtk_combo_box_set_model (priv->snippets_group_combo_box,
830 GTK_TREE_MODEL (priv->group_store));
831 g_object_unref (priv->group_store);
833 /* Add the cell renderer */
834 cell = gtk_cell_renderer_text_new ();
835 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->snippets_group_combo_box),
836 cell, TRUE);
837 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->snippets_group_combo_box),
838 cell, "text", GROUPS_COL_NAME, NULL);
842 static void
843 reload_snippets_group_combo_box (SnippetsEditor *snippets_editor)
845 SnippetsEditorPrivate *priv = NULL;
846 GtkTreeIter iter;
847 gchar *cur_group_name = NULL, *parent_group_name = NULL;
848 gint i = 0;
850 /* Assertions */
851 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
852 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
854 /* Unref the old model if there is one */
855 gtk_list_store_clear (priv->group_store);
857 /* If we have a snippet loaded, we should re-check it in the combo-box */
858 if (ANJUTA_IS_SNIPPET (priv->snippet) &&
859 ANJUTA_IS_SNIPPETS_GROUP (priv->snippet->parent_snippets_group))
861 AnjutaSnippetsGroup *group = ANJUTA_SNIPPETS_GROUP (priv->snippet->parent_snippets_group);
863 parent_group_name = g_strdup (snippets_group_get_name (group));
866 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->snippets_db), &iter))
867 return;
869 /* Add the groups in the database to the list store */
872 /* Get the current group name from the database ... */
873 gtk_tree_model_get (GTK_TREE_MODEL (priv->snippets_db), &iter,
874 SNIPPETS_DB_MODEL_COL_NAME, &cur_group_name,
875 -1);
877 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->snippets_group_combo_box), cur_group_name);
879 /* If we have a snippet loaded, we search for the row. */
880 if (parent_group_name != NULL)
882 if (!g_strcmp0 (parent_group_name, cur_group_name))
883 g_object_set (priv->snippets_group_combo_box, "active", i, NULL);
885 i ++;
888 g_free (cur_group_name);
890 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->snippets_db), &iter));
894 static void
895 init_languages_combo_box (SnippetsEditor *snippets_editor)
897 SnippetsEditorPrivate *priv = NULL;
898 GtkCellRenderer *cell = NULL;
899 GtkTreeIter tree_iter;
900 GList *lang_ids = NULL, *iter = NULL;
901 gint cur_lang_id = 0;
902 const gchar *cur_lang = NULL;
903 IAnjutaLanguage *language = NULL;
905 /* Assertions */
906 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
907 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
909 /* Initialize the model which will be used for the combo-box */
910 priv->lang_store = gtk_list_store_new (LANG_MODEL_COL_N, G_TYPE_BOOLEAN, G_TYPE_STRING);
912 /* Add the items */
913 language = anjuta_shell_get_interface (priv->snippets_db->anjuta_shell,
914 IAnjutaLanguage, NULL);
915 lang_ids = ianjuta_language_get_languages (language, NULL);
916 for (iter = g_list_first (lang_ids); iter != NULL; iter = g_list_next (iter))
918 cur_lang_id = GPOINTER_TO_INT (iter->data);
919 cur_lang = ianjuta_language_get_name (language, cur_lang_id, NULL);
920 gtk_list_store_append (priv->lang_store, &tree_iter);
921 gtk_list_store_set (priv->lang_store, &tree_iter,
922 LANG_MODEL_COL_IN_SNIPPET, FALSE,
923 LANG_MODEL_COL_NAME, cur_lang,
924 -1);
926 g_list_free (lang_ids);
928 /* Set it as the model of the combo-box */
929 gtk_combo_box_set_model (priv->languages_combo_box,
930 GTK_TREE_MODEL (priv->lang_store));
931 g_object_unref (priv->lang_store);
933 /* Add the cell renderers */
934 cell = gtk_cell_renderer_toggle_new ();
935 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->languages_combo_box),
936 cell, FALSE);
937 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->languages_combo_box),
938 cell, "active", LANG_MODEL_COL_IN_SNIPPET);
940 cell = gtk_cell_renderer_text_new ();
941 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->languages_combo_box),
942 cell, FALSE);
943 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->languages_combo_box),
944 cell, "text", LANG_MODEL_COL_NAME);
947 static void
948 load_languages_combo_box (SnippetsEditor *snippets_editor)
950 SnippetsEditorPrivate *priv = NULL;
951 GtkTreeIter iter;
952 gchar *cur_lang = NULL;
953 gboolean has_language = FALSE;
955 /* Assertions */
956 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
957 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
959 /* Add the new selection or clear it */
960 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->lang_store), &iter))
961 g_return_if_reached ();
965 /* Clear it */
966 gtk_list_store_set (priv->lang_store, &iter,
967 LANG_MODEL_COL_IN_SNIPPET, FALSE,
968 -1);
970 /* If we have a snippet loaded, we also populate the checklist */
971 if (ANJUTA_IS_SNIPPET (priv->snippet))
973 gtk_tree_model_get (GTK_TREE_MODEL (priv->lang_store), &iter,
974 LANG_MODEL_COL_NAME, &cur_lang,
975 -1);
977 has_language = snippet_has_language (priv->snippet, cur_lang);
978 gtk_list_store_set (priv->lang_store, &iter,
979 LANG_MODEL_COL_IN_SNIPPET, has_language,
980 -1);
982 g_free (cur_lang);
985 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->lang_store), &iter));
987 /* The combo box should be sensitive only if there is a snippet loaded */
988 g_object_set (priv->languages_combo_box, "sensitive",
989 ANJUTA_IS_SNIPPET (priv->snippet), NULL);
992 static void
993 load_keywords_entry (SnippetsEditor *snippets_editor)
995 SnippetsEditorPrivate *priv = NULL;
996 GList *keywords = NULL, *iter = NULL;
997 const gchar *cur_keyword = NULL;
998 GString *keywords_string = NULL;
1000 /* Assertions */
1001 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1002 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1004 /* Clear the text entry */
1005 gtk_entry_set_text (priv->keywords_entry, "");
1007 /* If there is a snippet loaded, add the keywords */
1008 if (ANJUTA_IS_SNIPPET (priv->snippet))
1010 keywords = snippet_get_keywords_list (priv->snippet);
1011 keywords_string = g_string_new ("");
1013 for (iter = g_list_first (keywords); iter != NULL; iter = g_list_next (iter))
1015 cur_keyword = (const gchar *)iter->data;
1016 g_string_append (keywords_string, cur_keyword);
1017 g_string_append (keywords_string, " ");
1020 gtk_entry_set_text (priv->keywords_entry, keywords_string->str);
1022 g_string_free (keywords_string, TRUE);
1023 g_list_free (keywords);
1027 static void
1028 save_keywords_entry (SnippetsEditor *snippets_editor)
1030 SnippetsEditorPrivate *priv = NULL;
1031 GList *keywords = NULL;
1032 gchar **keywords_array = NULL;
1033 gint i = 0;
1035 /* Assertions */
1036 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1037 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1039 keywords_array = g_strsplit (gtk_entry_get_text (priv->keywords_entry), " ", -1);
1041 /* Add each item of the array to the list */
1042 while (keywords_array[i])
1044 /* In case the user entered more than one space between keywords */
1045 if (g_strcmp0 (keywords_array[i], ""))
1046 keywords = g_list_append (keywords, keywords_array[i]);
1048 i ++;
1051 snippet_set_keywords_list (priv->snippet, keywords);
1052 g_strfreev (keywords_array);
1053 g_list_free (keywords);
1057 static gboolean
1058 check_trigger_entry (SnippetsEditor *snippets_editor)
1060 SnippetsEditorPrivate *priv = NULL;
1061 gboolean valid = TRUE;
1062 guint16 i = 0, text_length = 0;
1063 const gchar *text = NULL;
1065 /* Assertions */
1066 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor), FALSE);
1067 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1069 /* Check the text is valid only if there is a snippet loaded */
1070 if (ANJUTA_IS_SNIPPET (priv->snippet))
1072 text = gtk_entry_get_text (priv->trigger_entry);
1073 text_length = gtk_entry_get_text_length (priv->trigger_entry);
1075 for (i = 0; i < text_length; i ++)
1076 if (!g_ascii_isalnum (text[i]) && text[i] != '_')
1078 /* Set as invalid and set the according error message */
1079 g_object_set (priv->trigger_notify, "tooltip-markup", ERROR_TRIGGER_NOT_VALID, NULL);
1080 valid = FALSE;
1081 break;
1084 /* If there isn't a trigger-key entered, we also show an error message, but a
1085 different one */
1086 if (text_length == 0)
1088 g_object_set (priv->trigger_notify, "tooltip-markup", ERROR_TRIGGER_NULL, NULL);
1089 valid = FALSE;
1094 /* Show or hide */
1095 g_object_set (priv->trigger_notify, "visible", !valid, NULL);
1097 return valid;
1100 static gboolean
1101 check_languages_combo_box (SnippetsEditor *snippets_editor)
1103 SnippetsEditorPrivate *priv = NULL;
1104 GtkTreeIter iter;
1105 gchar *lang_name = NULL;
1106 const gchar *trigger = NULL;
1107 gboolean no_lang_selected = TRUE;
1108 AnjutaSnippet *conflicting_snippet = NULL;
1110 /* Assertions */
1111 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor), FALSE);
1112 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1114 trigger = gtk_entry_get_text (priv->trigger_entry);
1116 /* We should always have this tree model filled */
1117 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->lang_store), &iter))
1118 g_return_val_if_reached (FALSE);
1120 /* We initialize the error image by hiding it */
1121 g_object_set (priv->languages_notify, "visible", FALSE, NULL);
1123 if (!ANJUTA_IS_SNIPPET (priv->snippet))
1124 return TRUE;
1126 /* We check each language to see if it doesen't cause a conflict */
1129 gtk_tree_model_get (GTK_TREE_MODEL (priv->lang_store), &iter,
1130 LANG_MODEL_COL_NAME, &lang_name,
1131 -1);
1133 if (snippet_has_language (priv->snippet, lang_name))
1135 conflicting_snippet = snippets_db_get_snippet (priv->snippets_db, trigger, lang_name);
1137 no_lang_selected = FALSE;
1139 /* If there is a conflicting snippet and it isn't the one we had backed-up,
1140 we make visible the error icon. */
1141 if (ANJUTA_IS_SNIPPET (conflicting_snippet) &&
1142 priv->backup_snippet != conflicting_snippet)
1144 g_object_set (priv->languages_notify, "tooltip-markup", ERROR_LANG_CONFLICT, NULL);
1145 g_object_set (priv->languages_notify, "visible", TRUE, NULL);
1147 g_free (lang_name);
1148 return FALSE;
1153 g_free (lang_name);
1155 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->lang_store), &iter));
1157 /* If the user doesn't have any language selected, we show a warning. */
1158 if (no_lang_selected)
1160 g_object_set (priv->languages_notify, "tooltip-markup", ERROR_LANG_NULL, NULL);
1161 g_object_set (priv->languages_notify, "visible", TRUE, NULL);
1163 return FALSE;
1166 return TRUE;
1169 static gboolean
1170 check_group_combo_box (SnippetsEditor *snippets_editor)
1172 SnippetsEditorPrivate *priv = NULL;
1173 gboolean has_selection = FALSE;
1175 /* Assertions */
1176 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor), FALSE);
1177 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1179 has_selection = (gtk_combo_box_get_active (priv->snippets_group_combo_box) >= 0);
1180 g_object_set (priv->group_notify, "visible",
1181 !has_selection && ANJUTA_IS_SNIPPET (priv->snippet),
1182 NULL);
1184 return has_selection;
1187 static void
1188 check_all_inputs (SnippetsEditor *snippets_editor)
1190 SnippetsEditorPrivate *priv = NULL;
1191 gboolean no_errors = FALSE;
1193 /* Assertions */
1194 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1195 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1197 /* We check we don't have any errors */
1198 no_errors = (!priv->languages_error && !priv->group_error && !priv->trigger_error);
1200 g_object_set (priv->save_button, "sensitive", no_errors, NULL);
1203 static void
1204 check_name_entry (SnippetsEditor *snippets_editor)
1206 SnippetsEditorPrivate *priv = NULL;
1207 guint16 text_length = 0;
1209 /* Assertions */
1210 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1211 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1213 /* Initialize the warning icon */
1214 g_object_set (priv->name_notify, "visible", FALSE, NULL);
1216 if (ANJUTA_IS_SNIPPET (priv->snippet))
1218 text_length = gtk_entry_get_text_length (priv->name_entry);
1219 g_object_set (priv->name_notify, "visible", text_length == 0, NULL);
1224 static void
1225 init_input_errors (SnippetsEditor *snippets_editor)
1227 SnippetsEditorPrivate *priv = NULL;
1229 /* Assertions */
1230 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1231 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1233 g_object_set (priv->group_notify, "visible", FALSE, NULL);
1234 g_object_set (priv->languages_notify, "visible", FALSE, NULL);
1235 g_object_set (priv->trigger_notify, "visible", FALSE, NULL);
1237 priv->group_error = !check_languages_combo_box (snippets_editor);
1238 priv->languages_error = !check_group_combo_box (snippets_editor);
1239 priv->trigger_error = !check_trigger_entry (snippets_editor);
1240 check_name_entry (snippets_editor);
1242 check_all_inputs (snippets_editor);
1245 static void
1246 init_sensitivity (SnippetsEditor *snippets_editor)
1248 SnippetsEditorPrivate *priv = NULL;
1249 gboolean has_snippet = FALSE;
1251 /* Assertions */
1252 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1253 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1255 has_snippet = ANJUTA_IS_SNIPPET (priv->snippet);
1256 g_object_set (priv->save_button, "sensitive", has_snippet, NULL);
1257 g_object_set (priv->variable_add_button, "sensitive", has_snippet, NULL);
1258 g_object_set (priv->languages_combo_box, "sensitive", has_snippet, NULL);
1259 g_object_set (priv->snippets_group_combo_box, "sensitive", has_snippet, NULL);
1260 g_object_set (priv->name_entry, "sensitive", has_snippet, NULL);
1261 g_object_set (priv->trigger_entry, "sensitive", has_snippet, NULL);
1262 g_object_set (priv->keywords_entry, "sensitive", has_snippet, NULL);
1263 g_object_set (priv->content_text_view, "sensitive", has_snippet, NULL);
1267 static void
1268 init_editor_handlers (SnippetsEditor *snippets_editor)
1270 SnippetsEditorPrivate *priv = NULL;
1272 /* Assertions */
1273 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1274 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1276 g_signal_connect (G_OBJECT (priv->preview_button),
1277 "toggled",
1278 G_CALLBACK (on_preview_button_toggled),
1279 snippets_editor);
1280 g_signal_connect (G_OBJECT (priv->save_button),
1281 "clicked",
1282 G_CALLBACK (on_save_button_clicked),
1283 snippets_editor);
1284 g_signal_connect (G_OBJECT (priv->close_button),
1285 "clicked",
1286 G_CALLBACK (on_close_button_clicked),
1287 snippets_editor);
1288 g_signal_connect (G_OBJECT (priv->name_combo_cell),
1289 "edited",
1290 G_CALLBACK (on_name_combo_cell_edited),
1291 snippets_editor);
1292 g_signal_connect (G_OBJECT (priv->type_combo_cell),
1293 "changed",
1294 G_CALLBACK (on_type_combo_cell_changed),
1295 snippets_editor);
1296 g_signal_connect (G_OBJECT (priv->default_text_cell),
1297 "edited",
1298 G_CALLBACK (on_default_text_cell_edited),
1299 snippets_editor);
1300 g_signal_connect (G_OBJECT (priv->variables_view),
1301 "row-activated",
1302 G_CALLBACK (on_variables_view_row_activated),
1303 snippets_editor);
1304 g_signal_connect (G_OBJECT (priv->variable_add_button),
1305 "clicked",
1306 G_CALLBACK (on_variable_add_button_clicked),
1307 snippets_editor);
1308 g_signal_connect (G_OBJECT (priv->variable_remove_button),
1309 "clicked",
1310 G_CALLBACK (on_variable_remove_button_clicked),
1311 snippets_editor);
1312 g_signal_connect (G_OBJECT (priv->variable_insert_button),
1313 "clicked",
1314 G_CALLBACK (on_variable_insert_button_clicked),
1315 snippets_editor);
1316 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (priv->variables_view)),
1317 "changed",
1318 G_CALLBACK (on_variables_view_selection_changed),
1319 snippets_editor);
1320 g_signal_connect (G_OBJECT (priv->snippets_group_combo_box),
1321 "changed",
1322 G_CALLBACK (on_snippets_group_combo_box_changed),
1323 snippets_editor);
1324 g_signal_connect (G_OBJECT (priv->languages_combo_box),
1325 "changed",
1326 G_CALLBACK (on_languages_combo_box_changed),
1327 snippets_editor);
1328 g_signal_connect (G_OBJECT (priv->trigger_entry),
1329 "notify::text",
1330 G_CALLBACK (on_trigger_entry_text_changed),
1331 snippets_editor);
1332 g_signal_connect (G_OBJECT (priv->name_entry),
1333 "notify::text",
1334 G_CALLBACK (on_name_entry_text_changed),
1335 snippets_editor);
1338 SnippetsEditor *
1339 snippets_editor_new (SnippetsDB *snippets_db)
1341 SnippetsEditor *snippets_editor =
1342 ANJUTA_SNIPPETS_EDITOR (g_object_new (snippets_editor_get_type (), NULL));
1343 SnippetsEditorPrivate *priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1345 /* Assertions */
1346 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), snippets_editor);
1348 priv->snippets_db = snippets_db;
1350 /* Load the variables tree model */
1351 priv->vars_store = snippet_vars_store_new ();
1353 /* Load the UI for snippets-editor.ui */
1354 load_snippets_editor_ui (snippets_editor);
1356 /* Initialize the variables tree view */
1357 init_variables_view (snippets_editor);
1359 /* Initialize the snippets-group combo box */
1360 init_snippets_group_combo_box (snippets_editor);
1361 reload_snippets_group_combo_box (snippets_editor);
1363 /* Initialize the languages combo box */
1364 init_languages_combo_box (snippets_editor);
1366 /* Connect the handlers */
1367 init_editor_handlers (snippets_editor);
1369 /* Initialize the buttons as insensitive */
1370 g_object_set (priv->save_button, "sensitive", FALSE, NULL);
1371 g_object_set (priv->languages_combo_box, "sensitive", FALSE, NULL);
1372 g_object_set (priv->snippets_group_combo_box, "sensitive", FALSE, NULL);
1374 return snippets_editor;
1377 static void
1378 load_content_to_editor (SnippetsEditor *snippets_editor)
1380 SnippetsEditorPrivate *priv = NULL;
1381 gchar *text = NULL;
1382 GtkTextBuffer *content_buffer = NULL;
1384 /* Assertions */
1385 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1386 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1388 /* If we don't have a snippet loaded we don't do anything */
1389 if (!ANJUTA_IS_SNIPPET (priv->snippet))
1391 text = g_strdup ("");
1393 else
1394 if (gtk_toggle_button_get_active (priv->preview_button))
1396 text = snippet_get_default_content (priv->snippet,
1397 G_OBJECT (priv->snippets_db),
1398 "");
1400 else
1402 text = g_strdup (snippet_get_content (priv->snippet));
1405 content_buffer = gtk_text_view_get_buffer (priv->content_text_view);
1406 gtk_text_buffer_set_text (content_buffer, text, -1);
1407 g_free (text);
1410 /* Warning: this will take the text as it is. It won't check if it's a preview. */
1411 static void
1412 save_content_from_editor (SnippetsEditor *snippets_editor)
1414 SnippetsEditorPrivate *priv = NULL;
1415 GtkTextIter start_iter, end_iter;
1416 gchar *text = NULL;
1417 GtkTextBuffer *content_buffer = NULL;
1419 /* Assertions */
1420 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1421 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1423 /* If we don't have a snippet loaded, don't do anything */
1424 if (!ANJUTA_IS_SNIPPET (priv->snippet))
1425 return;
1427 /* Get the text in the GtkTextBuffer */
1428 content_buffer = gtk_text_view_get_buffer (priv->content_text_view);
1429 gtk_text_buffer_get_start_iter (content_buffer, &start_iter);
1430 gtk_text_buffer_get_end_iter (content_buffer, &end_iter);
1431 text = gtk_text_buffer_get_text (content_buffer, &start_iter, &end_iter, FALSE);
1433 /* Save it to the snippet */
1434 snippet_set_content (priv->snippet, text);
1436 g_free (text);
1439 void
1440 snippets_editor_set_snippet (SnippetsEditor *snippets_editor,
1441 AnjutaSnippet *snippet)
1443 SnippetsEditorPrivate *priv = NULL;
1445 /* Assertions */
1446 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1447 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1449 /* If we are saving the snippet, we need to guard entering this method because
1450 it will be called by the selection changed handler in the browser */
1451 if (priv->saving_snippet)
1452 return;
1454 /* Delete the old snippet */
1455 if (ANJUTA_IS_SNIPPET (priv->snippet))
1456 g_object_unref (priv->snippet);
1458 /* Set the current snippet */
1459 priv->backup_snippet = snippet;
1460 if (ANJUTA_IS_SNIPPET (snippet))
1461 priv->snippet = snippet_copy (snippet);
1462 else
1463 priv->snippet = NULL;
1465 /* Set the sensitive property of the widgets */
1466 init_sensitivity (snippets_editor);
1468 /* Initialize the snippet content editor */
1469 load_content_to_editor (snippets_editor);
1471 /* Initialize the name property */
1472 if (ANJUTA_IS_SNIPPET (snippet))
1473 gtk_entry_set_text (priv->name_entry, snippet_get_name (snippet));
1474 else
1475 gtk_entry_set_text (priv->name_entry, "");
1477 /* Initialize the trigger-key property */
1478 if (ANJUTA_IS_SNIPPET (snippet))
1479 gtk_entry_set_text (priv->trigger_entry, snippet_get_trigger_key (snippet));
1480 else
1481 gtk_entry_set_text (priv->trigger_entry, "");
1483 /* Initialize the snippets group combo-box property */
1484 reload_snippets_group_combo_box (snippets_editor);
1485 focus_snippets_group_combo_box (snippets_editor);
1487 /* Initialize the language combo-box property */
1488 load_languages_combo_box (snippets_editor);
1490 /* Initialize the keywords text-view property */
1491 load_keywords_entry (snippets_editor);
1493 /* Initialize the variables tree-view - load the variables tree model with the variables
1494 from the current snippet*/
1495 snippet_vars_store_unload (priv->vars_store);
1496 if (ANJUTA_IS_SNIPPET (priv->snippet))
1497 snippet_vars_store_load (priv->vars_store, priv->snippets_db, priv->snippet);
1499 /* We initialize the errors/warnings */
1500 init_input_errors (snippets_editor);
1504 void
1505 snippets_editor_set_snippet_new (SnippetsEditor *snippets_editor)
1507 SnippetsEditorPrivate *priv = NULL;
1509 /* Assertions */
1510 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
1511 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1513 /* Delete the old snippet */
1514 if (ANJUTA_IS_SNIPPET (priv->snippet))
1515 g_object_unref (priv->snippet);
1516 priv->backup_snippet = NULL;
1518 /* Initialize a new empty snippet */
1519 priv->snippet = snippet_new ("", NULL, "", "", NULL, NULL, NULL, NULL);
1521 init_sensitivity (snippets_editor);
1523 /* Initialize the entries and content */
1524 gtk_entry_set_text (priv->name_entry, "");
1525 gtk_entry_set_text (priv->trigger_entry, "");
1526 gtk_entry_set_text (priv->keywords_entry, "");
1527 load_content_to_editor (snippets_editor);
1530 reload_snippets_group_combo_box (snippets_editor);
1531 focus_snippets_group_combo_box (snippets_editor);
1533 load_languages_combo_box (snippets_editor);
1535 snippet_vars_store_unload (priv->vars_store);
1536 if (ANJUTA_IS_SNIPPET (priv->snippet))
1537 snippet_vars_store_load (priv->vars_store, priv->snippets_db, priv->snippet);
1539 init_input_errors (snippets_editor);
1543 static void
1544 on_preview_button_toggled (GtkToggleButton *preview_button,
1545 gpointer user_data)
1547 SnippetsEditor *snippets_editor = NULL;
1548 SnippetsEditorPrivate *priv = NULL;
1549 gboolean preview_mode = FALSE;
1551 /* Assertions */
1552 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1553 snippets_editor = ANJUTA_SNIPPETS_EDITOR (user_data);
1554 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1556 /* If we go in the preview mode, we should save the content and disallow removing
1557 and inserting variables */
1558 preview_mode = gtk_toggle_button_get_active (preview_button);
1559 if (preview_mode)
1560 save_content_from_editor (snippets_editor);
1562 g_object_set (priv->variable_insert_button, "sensitive", !preview_mode, NULL);
1563 g_object_set (priv->content_text_view, "editable", !preview_mode, NULL);
1565 load_content_to_editor (snippets_editor);
1568 static void
1569 on_save_button_clicked (GtkButton *save_button,
1570 gpointer user_data)
1572 SnippetsEditorPrivate *priv = NULL;
1573 SnippetsEditor *snippets_editor = NULL;
1574 AnjutaSnippetsGroup *parent_snippets_group = NULL;
1576 /* Assertions */
1577 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1578 snippets_editor = ANJUTA_SNIPPETS_EDITOR (user_data);
1579 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
1580 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
1582 /* If there isn't a snippet editing */
1583 if (!ANJUTA_IS_SNIPPET (priv->snippet))
1584 return;
1586 /* The user should have a snippets group selected */
1587 if (!ANJUTA_IS_SNIPPETS_GROUP (priv->snippet->parent_snippets_group))
1588 return;
1590 /* Copy over the name, trigger and keywords */
1591 snippet_set_name (priv->snippet, gtk_entry_get_text (priv->name_entry));
1592 snippet_set_trigger_key (priv->snippet, gtk_entry_get_text (priv->trigger_entry));
1593 save_keywords_entry (snippets_editor);
1595 /* Save the content */
1596 if (!gtk_toggle_button_get_active (priv->preview_button))
1597 save_content_from_editor (snippets_editor);
1599 /* Delete the back-up snippet if there is one (we don't have one if it's a new snippet)*/
1600 priv->saving_snippet = TRUE;
1601 if (ANJUTA_IS_SNIPPET (priv->backup_snippet))
1602 snippets_db_remove_snippet (priv->snippets_db,
1603 snippet_get_trigger_key (priv->backup_snippet),
1604 snippet_get_any_language (priv->backup_snippet),
1605 TRUE);
1606 /* Add the new snippet */
1607 parent_snippets_group = ANJUTA_SNIPPETS_GROUP (priv->snippet->parent_snippets_group);
1608 snippets_db_add_snippet (priv->snippets_db,
1609 priv->snippet,
1610 snippets_group_get_name (parent_snippets_group));
1612 /* Move the new snippet as the back-up one */
1613 priv->backup_snippet = priv->snippet;
1614 priv->snippet = snippet_copy (priv->backup_snippet);
1616 /* Emit the signal that the snippet was saved */
1617 g_signal_emit_by_name (snippets_editor, "snippet-saved", priv->backup_snippet);
1619 priv->saving_snippet = FALSE;
1622 static void
1623 on_close_button_clicked (GtkButton *close_button,
1624 gpointer user_data)
1626 /* Assertions */
1627 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1629 g_signal_emit_by_name (ANJUTA_SNIPPETS_EDITOR (user_data), "close-request");
1632 static void
1633 on_name_combo_cell_edited (GtkCellRendererText *cell,
1634 gchar *path_string,
1635 gchar *new_string,
1636 gpointer user_data)
1638 SnippetsEditorPrivate *priv = NULL;
1639 GtkTreePath *path = NULL;
1640 gchar *old_name = NULL;
1641 GtkTreeIter iter;
1643 /* Assertions */
1644 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1645 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1647 /* We don't accept empty strings as variables names */
1648 if (!g_strcmp0 (new_string, ""))
1649 return;
1651 /* Get the old name at the given path */
1652 path = gtk_tree_path_new_from_string (path_string);
1653 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->vars_store_sorted), &iter, path);
1654 gtk_tree_path_free (path);
1655 gtk_tree_model_get (GTK_TREE_MODEL (priv->vars_store_sorted), &iter,
1656 VARS_STORE_COL_NAME, &old_name,
1657 -1);
1659 /* If the name wasn't changed we don't do anything */
1660 if (!g_strcmp0 (old_name, new_string))
1662 g_free (old_name);
1663 return;
1666 /* Set the new name */
1667 snippet_vars_store_set_variable_name (priv->vars_store, old_name, new_string);
1669 /* If there is a global variable with the given name, treat it as global */
1670 if (snippets_db_has_global_variable (priv->snippets_db, new_string))
1671 snippet_vars_store_set_variable_type (priv->vars_store,
1672 new_string,
1673 SNIPPET_VAR_TYPE_GLOBAL);
1675 focus_on_in_snippet_variable (priv->variables_view,
1676 GTK_TREE_MODEL (priv->vars_store_sorted),
1677 new_string,
1678 NULL, FALSE);
1680 change_snippet_variable_name_in_content (ANJUTA_SNIPPETS_EDITOR (user_data),
1681 old_name, new_string);
1683 g_free (old_name);
1687 static void
1688 on_type_combo_cell_changed (GtkCellRendererCombo *cell,
1689 gchar *path_string,
1690 gchar *new_string,
1691 gpointer user_data)
1693 SnippetsEditorPrivate *priv = NULL;
1694 GtkTreePath *path = NULL;
1695 gchar *name = NULL;
1696 GtkTreeIter iter;
1697 SnippetVariableType type;
1699 /* Assertions */
1700 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1701 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1703 /* Get the name at the given path */
1704 path = gtk_tree_path_new_from_string (path_string);
1705 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->vars_store_sorted), &iter, path);
1706 gtk_tree_path_free (path);
1707 gtk_tree_model_get (GTK_TREE_MODEL (priv->vars_store_sorted), &iter,
1708 VARS_STORE_COL_NAME, &name,
1709 VARS_STORE_COL_TYPE, &type,
1710 -1);
1712 if (type == SNIPPET_VAR_TYPE_LOCAL)
1713 snippet_vars_store_set_variable_type (priv->vars_store, name, SNIPPET_VAR_TYPE_GLOBAL);
1714 else
1715 snippet_vars_store_set_variable_type (priv->vars_store, name, SNIPPET_VAR_TYPE_LOCAL);
1717 focus_on_in_snippet_variable (priv->variables_view,
1718 GTK_TREE_MODEL (priv->vars_store_sorted),
1719 name,
1720 NULL, FALSE);
1722 g_free (name);
1725 static void
1726 on_default_text_cell_edited (GtkCellRendererText *cell,
1727 gchar *path_string,
1728 gchar *new_string,
1729 gpointer user_data)
1731 SnippetsEditorPrivate *priv = NULL;
1732 GtkTreePath *path = NULL;
1733 gchar *name = NULL;
1734 GtkTreeIter iter;
1736 /* Assertions */
1737 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1738 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1740 /* Get the name at the given path */
1741 path = gtk_tree_path_new_from_string (path_string);
1742 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->vars_store_sorted), &iter, path);
1743 gtk_tree_path_free (path);
1744 gtk_tree_model_get (GTK_TREE_MODEL (priv->vars_store_sorted), &iter,
1745 VARS_STORE_COL_NAME, &name,
1746 -1);
1748 snippet_vars_store_set_variable_default (priv->vars_store, name, new_string);
1750 g_free (name);
1755 static void
1756 on_variables_view_row_activated (GtkTreeView *tree_view,
1757 GtkTreePath *path,
1758 GtkTreeViewColumn *col,
1759 gpointer user_data)
1761 /* Assertions */
1762 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1764 /* TODO -- still to be decided :) */
1768 static void
1769 on_variable_add_button_clicked (GtkButton *variable_add_button,
1770 gpointer user_data)
1772 SnippetsEditorPrivate *priv = NULL;
1773 GtkTreeViewColumn *col = NULL;
1775 /* Assertions */
1776 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1777 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1779 /* Add the variable to the vars_store */
1780 snippet_vars_store_add_variable_to_snippet (priv->vars_store,
1781 NEW_VAR_NAME, FALSE);
1783 /* Focus on it */
1784 col = gtk_tree_view_get_column (priv->variables_view, VARS_VIEW_COL_NAME);
1785 focus_on_in_snippet_variable (priv->variables_view,
1786 GTK_TREE_MODEL (priv->vars_store_sorted),
1787 NEW_VAR_NAME,
1788 col, TRUE);
1791 static void
1792 on_variable_remove_button_clicked (GtkButton *variable_remove_button,
1793 gpointer user_data)
1795 SnippetsEditorPrivate *priv = NULL;
1796 GtkTreeIter iter;
1797 gboolean has_selection = FALSE;
1798 GtkTreeSelection *selection = NULL;
1799 GtkTreeModel *model = NULL;
1800 gchar *name = NULL;
1802 /* Assertions */
1803 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1804 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1806 /* Get the selected variable */
1807 selection = gtk_tree_view_get_selection (priv->variables_view);
1808 model = GTK_TREE_MODEL (priv->vars_store_sorted);
1809 has_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
1811 /* We should always have a selection if the remove button is sensitive */
1812 g_return_if_fail (has_selection);
1814 /* Remove the variable from the vars_store */
1815 gtk_tree_model_get (model, &iter,
1816 VARS_STORE_COL_NAME, &name,
1817 -1);
1818 snippet_vars_store_remove_variable_from_snippet (priv->vars_store, name);
1820 g_free (name);
1823 static void
1824 on_variable_insert_button_clicked (GtkButton *variable_insert_button,
1825 gpointer user_data)
1827 SnippetsEditorPrivate *priv = NULL;
1828 GtkTextBuffer *content_buffer = NULL;
1829 gchar *var_name = NULL, *var_name_formated = NULL;
1830 GtkTreeSelection *selection = NULL;
1831 GtkTreeIter iter;
1832 gboolean in_snippet = FALSE;
1834 /* Assertions */
1835 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1836 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1838 /* Get the name of the selected variable */
1839 selection = gtk_tree_view_get_selection (priv->variables_view);
1840 if (!gtk_tree_selection_get_selected (selection, &priv->vars_store_sorted, &iter))
1841 g_return_if_reached ();
1843 gtk_tree_model_get (priv->vars_store_sorted, &iter,
1844 VARS_STORE_COL_NAME, &var_name,
1845 VARS_STORE_COL_IN_SNIPPET, &in_snippet,
1846 -1);
1848 /* We insert the variable in the content text buffer and add it to the snippet
1849 if necessary */
1850 var_name_formated = g_strconcat (SNIPPET_VAR_START, var_name, SNIPPET_VAR_END, NULL);
1851 content_buffer = gtk_text_view_get_buffer (priv->content_text_view);
1852 gtk_text_buffer_insert_at_cursor (content_buffer, var_name_formated, -1);
1854 if (!in_snippet)
1856 snippet_vars_store_add_variable_to_snippet (priv->vars_store, var_name, TRUE);
1857 g_object_set (priv->variable_remove_button, "sensitive", TRUE, NULL);
1860 g_free (var_name_formated);
1861 g_free (var_name);
1865 static void
1866 on_variables_view_selection_changed (GtkTreeSelection *selection,
1867 gpointer user_data)
1869 SnippetsEditorPrivate *priv = NULL;
1870 GtkTreeIter iter;
1871 GtkTreeModel *vars_store_sorted_model = NULL;
1872 gboolean in_snippet = FALSE, has_selection = FALSE;
1874 /* Assertions */
1875 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1876 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1878 vars_store_sorted_model = GTK_TREE_MODEL (priv->vars_store_sorted);
1879 has_selection = gtk_tree_selection_get_selected (selection,
1880 &vars_store_sorted_model,
1881 &iter);
1883 /* If there isn't a selection, the remove and insert button won't be sensitive */
1884 g_object_set (priv->variable_remove_button, "sensitive", has_selection, NULL);
1885 g_object_set (priv->variable_insert_button, "sensitive", has_selection, NULL);
1887 if (!has_selection)
1888 return;
1890 /* Check if the selected variable is in the snippet. If not, the remove button
1891 won't be sensitive. */
1892 gtk_tree_model_get (vars_store_sorted_model, &iter,
1893 VARS_STORE_COL_IN_SNIPPET, &in_snippet,
1894 -1);
1895 g_object_set (priv->variable_remove_button, "sensitive", in_snippet, NULL);
1899 static void
1900 on_snippets_group_combo_box_changed (GtkComboBox *combo_box,
1901 gpointer user_data)
1903 SnippetsEditorPrivate *priv = NULL;
1904 GtkTreeIter iter;
1905 gchar *group_name = NULL;
1906 AnjutaSnippetsGroup *snippets_group = NULL;
1908 /* Assertions */
1909 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1910 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1912 /* If we have a snippet loaded, we change his parent */
1913 if (ANJUTA_IS_SNIPPET (priv->snippet))
1915 if (!gtk_combo_box_get_active_iter (priv->snippets_group_combo_box, &iter))
1917 priv->group_error = !check_group_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
1918 check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
1919 return;
1922 gtk_tree_model_get (GTK_TREE_MODEL (priv->group_store), &iter,
1923 GROUPS_COL_NAME, &group_name,
1924 -1);
1926 snippets_group = snippets_db_get_snippets_group (priv->snippets_db, group_name);
1927 g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group));
1929 priv->snippet->parent_snippets_group = G_OBJECT (snippets_group);
1931 g_free (group_name);
1934 priv->group_error = !check_group_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
1935 check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
1939 static void
1940 on_languages_combo_box_changed (GtkComboBox *combo_box,
1941 gpointer user_data)
1943 SnippetsEditorPrivate *priv = NULL;
1944 GtkTreeIter iter;
1945 gboolean in_snippet = FALSE;
1946 gchar *lang_name = NULL;
1948 /* Assertions */
1949 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1950 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1952 /* This will happen because we set at the end of this function -1 as active */
1953 if (gtk_combo_box_get_active (combo_box) < 0)
1954 return;
1956 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
1957 g_return_if_reached ();
1959 /* We reverse the setting */
1960 gtk_tree_model_get (GTK_TREE_MODEL (priv->lang_store), &iter,
1961 LANG_MODEL_COL_IN_SNIPPET, &in_snippet,
1962 LANG_MODEL_COL_NAME, &lang_name,
1963 -1);
1964 gtk_list_store_set (priv->lang_store, &iter,
1965 LANG_MODEL_COL_IN_SNIPPET, !in_snippet,
1966 -1);
1968 if (!in_snippet)
1969 snippet_add_language (priv->snippet, lang_name);
1970 else
1971 snippet_remove_language (priv->snippet, lang_name);
1973 g_free (lang_name);
1975 /* We don't want anything to show when there isn't a popup */
1976 gtk_combo_box_set_active (combo_box, -1);
1978 priv->languages_error = !check_languages_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
1980 check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
1983 static void
1984 on_trigger_entry_text_changed (GObject *entry_obj,
1985 GParamSpec *param_spec,
1986 gpointer user_data)
1988 SnippetsEditorPrivate *priv = NULL;
1990 /* Assertions */
1991 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
1992 priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
1994 priv->trigger_error = !check_trigger_entry (ANJUTA_SNIPPETS_EDITOR (user_data));
1995 priv->languages_error = !check_languages_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
1997 check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
2000 static void
2001 on_name_entry_text_changed (GObject *entry_obj,
2002 GParamSpec *param_spec,
2003 gpointer user_data)
2005 /* Assertions */
2006 g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
2008 check_name_entry (ANJUTA_SNIPPETS_EDITOR (user_data));