Updated Spanish translation
[anjuta-git-plugin.git] / plugins / tools / editor.c
blob9bcdbfc6c6e8838de70ee3c0c984306b2358a8d6
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 editor.c
4 Copyright (C) 2003 Biswapesh Chattopadhyay
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Tool editor dialog
23 * This is used to set all tool informations.
25 *---------------------------------------------------------------------------*/
27 #include <config.h>
29 #include "editor.h"
31 #include "dialog.h"
32 #include "tool.h"
33 #include "variable.h"
35 #include <libanjuta/anjuta-utils.h>
36 #include <libanjuta/interfaces/ianjuta-document-manager.h>
37 #include <libanjuta/interfaces/ianjuta-editor.h>
38 #include <libanjuta/interfaces/ianjuta-file-loader.h>
40 #include <libgnomeui/libgnomeui.h>
42 #include <gtk/gtk.h>
44 #include <string.h>
46 /*---------------------------------------------------------------------------*/
48 /* Variable dialog */
50 typedef enum {
51 ATP_VARIABLE_DEFAULT = 0,
52 ATP_VARIABLE_REPLACE = 1 << 1
53 } ATPVariableType;
55 typedef struct _ATPVariableDialog
57 GtkDialog* dialog;
58 GtkTreeView* view;
59 ATPToolEditor* editor;
60 GtkEditable* entry;
61 ATPVariableType type;
62 } ATPVariableDialog;
64 enum {
65 ATP_VARIABLE_NAME_COLUMN,
66 ATP_VARIABLE_MEAN_COLUMN,
67 ATP_VARIABLE_VALUE_COLUMN,
68 ATP_N_VARIABLE_COLUMNS,
71 /* Structure containing the required properties of the tool editor GUI */
72 struct _ATPToolEditor
74 GtkWidget *dialog;
75 GtkEditable *name_en;
76 GtkEditable *command_en;
77 GtkEditable *param_en;
78 ATPVariableDialog param_var;
79 GtkEditable *dir_en;
80 ATPVariableDialog dir_var;
81 GtkToggleButton *enabled_tb;
82 GtkToggleButton *terminal_tb;
83 GtkToggleButton *autosave_tb;
84 GtkToggleButton *script_tb;
85 GtkComboBox *output_com;
86 GtkComboBox *error_com;
87 GtkComboBox *input_com;
88 GtkEditable *input_en;
89 GtkButton *input_var_bt;
90 ATPVariableDialog input_file_var;
91 ATPVariableDialog input_string_var;
92 GtkToggleButton *shortcut_bt;
93 GnomeIconEntry *icon_en;
94 gchar* shortcut;
95 ATPUserTool *tool;
96 ATPToolDialog* parent;
97 ATPToolEditorList* owner;
98 ATPToolEditor* next;
101 /*---------------------------------------------------------------------------*/
103 /* Widget and signal name found in glade file
104 *---------------------------------------------------------------------------*/
106 #define TOOL_EDITOR "editor_dialog"
107 #define TOOL_NAME "name_entry"
108 #define TOOL_COMMAND "command_entry"
109 #define TOOL_PARAM "parameter_entry"
110 #define TOOL_WORKING_DIR "directory_entry"
111 #define TOOL_ENABLED "enable_checkbox"
112 #define TOOL_AUTOSAVE "save_checkbox"
113 #define TOOL_TERMINAL "terminal_checkbox"
114 #define TOOL_SCRIPT "script_checkbox"
115 #define TOOL_OUTPUT "output_combo"
116 #define TOOL_ERROR "error_combo"
117 #define TOOL_INPUT "input_combo"
118 #define TOOL_INPUT_VALUE "input_entry"
119 #define TOOL_INPUT_VARIABLE "input_button"
120 #define TOOL_SHORTCUT "shortcut_bt"
121 #define TOOL_ICON "icon_entry"
123 #define EDITOR_RESPONSE_SIGNAL "on_editor_dialog_response"
124 #define EDITOR_PARAM_VARIABLE_SIGNAL "on_variable_parameter"
125 #define EDITOR_DIR_VARIABLE_SIGNAL "on_variable_directory"
126 #define EDITOR_INPUT_VARIABLE_SIGNAL "on_variable_input"
127 #define EDITOR_INPUT_CHANGED_SIGNAL "on_input_changed"
128 #define EDITOR_TOGGLE_TERMINAL_SIGNAL "on_toggle_terminal"
129 #define EDITOR_TOGGLE_SHORCUT_SIGNAL "on_toggle_shorcut"
130 #define EDITOR_TOGGLE_SCRIPT_SIGNAL "on_toggle_script"
132 #define TOOL_VARIABLE "variable_dialog"
133 #define VARIABLE_TREEVIEW "variable_treeview"
134 #define VARIABLE_RESPONSE_SIGNAL "on_variable_dialog_response"
135 #define VARIABLE_ACTIVATE_SIGNAL "on_variable_activate_row"
137 /* Add helper function
138 *---------------------------------------------------------------------------*/
140 static gboolean
141 make_directory (gchar* path)
143 gchar c;
144 gchar* ptr;
146 for (ptr = path; *ptr;)
148 /* Get next directory */
149 for (c = '\0'; *ptr; ++ptr)
151 if (*ptr == G_DIR_SEPARATOR)
153 /* Strip leading directory separator */
156 ++ptr;
157 } while (*ptr == G_DIR_SEPARATOR);
158 c = *ptr;
159 *ptr = '\0';
160 break;
164 /* Create it */
165 if (mkdir (path, 0755) < 0)
167 /* Error creating directory */
168 *ptr = c;
169 if (errno != EEXIST)
171 /* An already existing directory is not an error */
172 return FALSE;
175 else
177 /* New directory created */
178 *ptr = c;
182 return TRUE;
185 static void
186 set_combo_box_enum_model (GtkComboBox* combo_box, const ATPEnumType* list)
188 GtkTreeModel *model;
190 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
192 for (; list->id != -1;++list)
194 GtkTreeIter iter;
196 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
197 gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, _(list->name), 1, list->id, -1);
199 gtk_combo_box_set_model (combo_box, model);
202 static gint
203 get_combo_box_value (GtkComboBox* combo_box)
205 GtkTreeIter iter;
206 GtkTreeModel *model;
207 gint value = -1;
209 if (gtk_combo_box_get_active_iter (combo_box, &iter))
211 model = gtk_combo_box_get_model (combo_box);
212 gtk_tree_model_get (model, &iter, 1, &value, -1);
215 return value;
218 static gboolean
219 set_combo_box_value (GtkComboBox* combo_box, gint value)
221 GtkTreeIter iter;
222 GtkTreeModel *model;
223 gint current;
225 if (value != -1)
227 model = gtk_combo_box_get_model (combo_box);
228 if (gtk_tree_model_get_iter_first (model, &iter))
232 gtk_tree_model_get (model, &iter, 1, &current, -1);
233 if (value == current)
235 gtk_combo_box_set_active_iter (combo_box, &iter);
237 return TRUE;
240 while (gtk_tree_model_iter_next (model, &iter));
244 gtk_combo_box_set_active (combo_box, 0);
246 return FALSE;
249 /* Tool variable dialog
250 * Display a list of variables useable as command line parameters or working
251 * directory with their values. Clicking on a variable add it in the current
252 * entry widget.
253 *---------------------------------------------------------------------------*/
255 static ATPVariableDialog*
256 atp_variable_dialog_construct (ATPVariableDialog* this, ATPToolEditor* editor, ATPVariableType type)
258 this->dialog = NULL;
259 this->editor = editor;
260 this->type = type;
262 return this;
265 static void
266 atp_variable_dialog_destroy (ATPVariableDialog* this)
268 if (this->dialog)
270 gtk_widget_destroy (GTK_WIDGET (this->dialog));
271 this->dialog = NULL;
275 static void
276 atp_variable_dialog_set_entry (ATPVariableDialog *this, GtkEditable* entry)
278 this->entry = entry;
281 static void
282 atp_variable_dialog_populate (ATPVariableDialog* this, ATPFlags flag)
284 GtkTreeModel *model;
285 ATPVariable* variable;
286 guint i;
288 variable = atp_tool_dialog_get_variable (this->editor->parent);
289 model = gtk_tree_view_get_model (this->view);
290 gtk_list_store_clear (GTK_LIST_STORE(model));
292 for (i = atp_variable_get_count(variable); i > 0;)
294 GtkTreeIter iter;
295 gchar* value;
296 const gchar* value_col;
298 --i;
299 if ((flag == ATP_DEFAULT_VARIABLE) || (flag & atp_variable_get_flag (variable, i)))
301 if (atp_variable_get_flag (variable, i) & ATP_INTERACTIVE_VARIABLE)
303 value = NULL;
304 value_col = _("ask at runtime");
306 else
308 value = atp_variable_get_value_from_id (variable, i);
309 value_col = (value == NULL) ? _("undefined") : value;
311 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
312 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
313 ATP_VARIABLE_NAME_COLUMN,
314 atp_variable_get_name(variable, i),
315 ATP_VARIABLE_MEAN_COLUMN,
316 _(atp_variable_get_help(variable, i)),
317 ATP_VARIABLE_VALUE_COLUMN,
318 value_col,
319 -1);
320 if (value) g_free (value);
325 static void
326 atp_variable_dialog_add_variable(ATPVariableDialog *this, const gchar* text)
328 gint pos;
330 g_return_if_fail (this->entry);
332 if (text != NULL)
334 gchar* next;
336 if (this->type == ATP_VARIABLE_REPLACE)
338 gtk_editable_delete_text (this->entry, 0, -1);
341 pos = gtk_editable_get_position(this->entry);
342 /* Add space before if useful */
343 if (pos != 0)
345 next = gtk_editable_get_chars (this->entry, pos - 1, pos);
347 if (!g_ascii_isspace (*next))
349 gtk_editable_insert_text (this->entry, " ", 1, &pos);
351 g_free (next);
353 gtk_editable_insert_text (this->entry, "$(", 2, &pos);
354 gtk_editable_insert_text (this->entry, text, strlen(text), &pos);
355 gtk_editable_insert_text (this->entry, ")", 1, &pos);
356 /* Add space after if useful */
357 next = gtk_editable_get_chars (this->entry, pos, pos + 1);
358 if (next != NULL)
360 if ((*next != '\0') && (!g_ascii_isspace (*next)))
362 gtk_editable_insert_text (this->entry, " ",1, &pos);
364 g_free (next);
369 static gchar*
370 get_current_name (GtkTreeView *view)
372 GtkTreeModel *model;
373 GtkTreeSelection *sel;
374 GtkTreeIter iter;
375 gchar* name;
377 model = gtk_tree_view_get_model (view);
378 sel = gtk_tree_view_get_selection (view);
379 if (gtk_tree_selection_get_selected (sel, &model, &iter))
381 gtk_tree_model_get (model, &iter, ATP_VARIABLE_NAME_COLUMN, &name, -1);
383 return name;
386 return NULL;
389 static void
390 on_variable_activate (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
392 ATPVariableDialog *this = (ATPVariableDialog*)user_data;
393 GtkTreeIter iter;
394 GtkTreeModel *model;
395 gchar* name;
397 /* Get Selected variable name */
398 model = gtk_tree_view_get_model (treeview);
399 gtk_tree_model_get_iter (model, &iter, path);
400 gtk_tree_model_get (model, &iter, ATP_VARIABLE_NAME_COLUMN, &name, -1);
402 atp_variable_dialog_add_variable (this, name);
404 gtk_widget_hide (GTK_WIDGET (this->dialog));
407 static void
408 on_variable_response (GtkDialog *dialog, gint response, gpointer user_data)
410 ATPVariableDialog *this = (ATPVariableDialog *)user_data;
411 gchar* name;
413 switch (response)
415 case GTK_RESPONSE_OK:
416 name = get_current_name (this->view);
417 atp_variable_dialog_add_variable (this, name);
418 break;
419 default:
420 break;
423 gtk_widget_hide (GTK_WIDGET (this->dialog));
426 static gboolean
427 atp_variable_dialog_show (ATPVariableDialog* this, ATPFlags flag)
429 GladeXML *xml;
430 GtkTreeModel *model;
431 GtkCellRenderer *renderer;
432 GtkTreeViewColumn *column;
434 if (this->dialog != NULL)
436 /* Display dialog box */
437 if (this->dialog) gtk_window_present (GTK_WINDOW (this->dialog));
438 return TRUE;
441 if (NULL == (xml = glade_xml_new(GLADE_FILE, TOOL_VARIABLE, NULL)))
443 anjuta_util_dialog_error (GTK_WINDOW (this->editor->dialog), _("Unable to build user interface for tool variable"));
444 return FALSE;
446 this->dialog = GTK_DIALOG (glade_xml_get_widget(xml, TOOL_VARIABLE));
447 gtk_widget_show (GTK_WIDGET (this->dialog));
448 gtk_window_set_transient_for (GTK_WINDOW (this->dialog), GTK_WINDOW (this->editor->dialog));
450 /* Create variable list */
451 this->view = GTK_TREE_VIEW (glade_xml_get_widget(xml, VARIABLE_TREEVIEW));
452 model = GTK_TREE_MODEL (gtk_list_store_new (ATP_N_VARIABLE_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
453 gtk_tree_view_set_model (this->view, model);
455 renderer = gtk_cell_renderer_text_new ();
456 column = gtk_tree_view_column_new_with_attributes (_("Variable"), renderer, "text", ATP_VARIABLE_NAME_COLUMN, NULL);
457 gtk_tree_view_append_column (this->view, column);
458 renderer = gtk_cell_renderer_text_new ();
459 column = gtk_tree_view_column_new_with_attributes (_("Meaning"), renderer, "text", ATP_VARIABLE_MEAN_COLUMN, NULL);
460 gtk_tree_view_append_column (this->view, column);
461 renderer = gtk_cell_renderer_text_new ();
462 column = gtk_tree_view_column_new_with_attributes (_("Value"), renderer, "text", ATP_VARIABLE_VALUE_COLUMN, NULL);
463 gtk_tree_view_append_column (this->view, column);
464 g_object_unref (model);
465 atp_variable_dialog_populate (this, flag);
467 /* Connect all signals */
468 glade_xml_signal_connect_data (xml, VARIABLE_RESPONSE_SIGNAL, GTK_SIGNAL_FUNC (on_variable_response), this);
469 glade_xml_signal_connect_data (xml, VARIABLE_ACTIVATE_SIGNAL, GTK_SIGNAL_FUNC (on_variable_activate), this);
470 g_signal_connect (G_OBJECT (this->dialog), "delete_event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
472 g_object_unref (xml);
474 return TRUE;
477 /* Tool editor dialog
478 *---------------------------------------------------------------------------*/
480 static void
481 atp_clear_tool_editor(ATPToolEditor* this)
483 g_return_if_fail (this != NULL);
485 gtk_editable_delete_text(this->name_en, 0, -1);
486 gtk_editable_delete_text(this->command_en, 0, -1);
487 gtk_editable_delete_text(this->param_en, 0, -1);
488 gtk_editable_delete_text(this->dir_en, 0, -1);
491 static void
492 atp_update_sensitivity(ATPToolEditor *this)
494 gboolean en;
496 /* Deactivate output and input setting if a terminal is used */
497 en = gtk_toggle_button_get_active (this->terminal_tb);
498 gtk_widget_set_sensitive(GTK_WIDGET (this->output_com), !en);
499 gtk_widget_set_sensitive(GTK_WIDGET (this->error_com), !en);
500 gtk_widget_set_sensitive(GTK_WIDGET (this->input_com), !en);
502 /* input value is available for a few input type only */
503 if (!en)
505 switch (get_combo_box_value (this->input_com))
507 case ATP_TIN_FILE:
508 case ATP_TIN_STRING:
509 en = TRUE;
510 break;
511 default:
512 en = FALSE;
513 break;
515 gtk_widget_set_sensitive(GTK_WIDGET (this->input_en), en);
516 gtk_widget_set_sensitive(GTK_WIDGET (this->input_var_bt), en);
518 else
520 gtk_widget_set_sensitive(GTK_WIDGET (this->input_en), FALSE);
521 gtk_widget_set_sensitive(GTK_WIDGET (this->input_var_bt), FALSE);
525 static void
526 atp_editor_update_shortcut (ATPToolEditor* this)
528 if (this->shortcut != NULL)
530 gtk_button_set_label (GTK_BUTTON (this->shortcut_bt), this->shortcut);
532 else
534 gtk_button_set_label (GTK_BUTTON (this->shortcut_bt), _("Disabled"));
538 static void
539 atp_populate_tool_editor(ATPToolEditor* this)
541 gint pos;
542 const gchar* value;
543 guint accel_key;
544 GdkModifierType accel_mods;
546 g_return_if_fail (this != NULL);
548 /* Nothing to fill */
549 if (this->tool == NULL) return;
551 value = atp_user_tool_get_name (this->tool);
552 if (value)
554 gtk_editable_insert_text(this->name_en, value
555 , strlen(value), &pos);
557 value = atp_user_tool_get_command (this->tool);
558 if (value)
560 gtk_editable_insert_text(this->command_en, value
561 , strlen(value), &pos);
563 value = atp_user_tool_get_param (this->tool);
564 if (value)
566 gtk_editable_insert_text(this->param_en, value
567 , strlen(value), &pos);
569 value = atp_user_tool_get_working_dir (this->tool);
570 if (value)
572 gtk_editable_insert_text(this->dir_en, value
573 , strlen(value), &pos);
575 gtk_toggle_button_set_active (this->enabled_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_ENABLE));
576 gtk_toggle_button_set_active (this->autosave_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_AUTOSAVE));
577 gtk_toggle_button_set_active (this->terminal_tb, atp_user_tool_get_flag (this->tool, ATP_TOOL_TERMINAL));
579 set_combo_box_value (this->output_com, atp_user_tool_get_output (this->tool));
580 set_combo_box_value (this->error_com, atp_user_tool_get_error (this->tool));
581 set_combo_box_value (this->input_com, atp_user_tool_get_input (this->tool));
582 switch (atp_user_tool_get_input (this->tool))
584 case ATP_TIN_FILE:
585 case ATP_TIN_STRING:
586 value = atp_user_tool_get_input_string (this->tool);
587 if (value)
589 gtk_editable_insert_text(this->input_en, value, strlen(value), &pos);
591 break;
592 default:
593 break;
595 atp_update_sensitivity (this);
597 if (this->shortcut != NULL) g_free (this->shortcut);
598 if (atp_user_tool_get_accelerator (this->tool, &accel_key, &accel_mods))
600 this->shortcut = gtk_accelerator_name (accel_key, accel_mods);
602 else
604 this->shortcut = NULL;
606 atp_editor_update_shortcut (this);
608 gnome_icon_entry_set_filename (this->icon_en, atp_user_tool_get_icon (this->tool));
611 static void
612 on_editor_terminal_toggle (GtkToggleButton *tb, gpointer user_data)
614 ATPToolEditor *this = (ATPToolEditor *)user_data;
616 atp_update_sensitivity (this);
619 static void
620 on_editor_script_toggle (GtkToggleButton *tb, gpointer user_data)
622 ATPToolEditor *this = (ATPToolEditor *)user_data;
623 gchar* command;
625 if (gtk_toggle_button_get_active(tb))
627 /* Get current command */
628 command = gtk_editable_get_chars(this->command_en, 0, -1);
630 if ((command == NULL) || (*command == '\0'))
632 gchar* name;
633 gint pos;
635 if (command) g_free (command);
636 /* Generate a new script file name */
637 command = gtk_editable_get_chars(this->name_en, 0, -1);
638 if ((command == NULL) || (*command == '\0'))
640 command = g_strdup("script");
642 name = atp_remove_mnemonic (command);
643 g_free (command);
644 command = g_build_filename (g_get_home_dir(),
645 LOCAL_ANJUTA_SCRIPT_DIRECTORY,
646 name, NULL);
647 g_free (name);
649 /* Find a new file name */
650 name = command;
651 pos = 0;
652 while (g_file_test (command, G_FILE_TEST_EXISTS))
654 if (command != name) g_free (command);
655 command = g_strdup_printf("%s%d", name, pos);
656 pos++;
658 if (command != name) g_free (name);
660 /* Fill command line */
661 gtk_editable_delete_text(this->command_en, 0, -1);
662 gtk_editable_insert_text(this->command_en, command,
663 strlen(command), &pos);
665 if (command) g_free (command);
669 static void
670 on_editor_input_changed (GtkComboBox *combo, gpointer user_data)
672 ATPToolEditor *this = (ATPToolEditor *)user_data;
674 atp_update_sensitivity (this);
677 static void
678 on_editor_response (GtkDialog *dialog, gint response, gpointer user_data)
680 ATPToolEditor* this = (ATPToolEditor*)user_data;
681 gchar* name;
682 gchar* data;
683 ATPInputType in_type;
684 gchar* value;
685 guint accel_key;
686 GdkModifierType accel_mods;
687 GtkAccelGroup* group;
688 AnjutaUI* ui;
690 if (response == GTK_RESPONSE_OK)
692 /* Check for all mandatory fields */
693 name = gtk_editable_get_chars(this->name_en, 0, -1);
694 if (!name || '\0' == name[0])
696 if (name) g_free (name);
697 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("You must provide a tool name!"));
698 return;
700 data = gtk_editable_get_chars(this->command_en, 0, -1);
701 if (!data || '\0' == data[0])
703 if (name) g_free (name);
704 if (data) g_free (data);
705 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("You must provide a tool command!"));
706 return;
709 if (!atp_user_tool_set_name (this->tool, name))
711 if (name) g_free (name);
712 if (data) g_free (data);
713 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("A tool with the same name already exists!"));
714 return;
716 g_free (name);
718 if (this->shortcut == NULL)
720 accel_key = 0;
721 accel_mods = 0;
723 else
725 gtk_accelerator_parse (this->shortcut, &accel_key, &accel_mods);
726 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(this->parent->plugin)->shell, NULL);
727 group = anjuta_ui_get_accel_group(ui);
728 if (gtk_accel_group_query (group, accel_key, accel_mods, NULL) != NULL)
730 if (!anjuta_util_dialog_boolean_question (GTK_WINDOW (this->dialog), _("The shortcut is already used by another component in Anjuta. Do you want to keep it anyway ?")))
732 return;
737 /* Set new tool data */
738 atp_user_tool_set_command (this->tool, data);
739 g_free (data);
741 data = gtk_editable_get_chars(this->param_en, 0, -1);
742 atp_user_tool_set_param (this->tool, data);
743 g_free (data);
745 data = gtk_editable_get_chars(this->dir_en, 0, -1);
746 atp_user_tool_set_working_dir (this->tool, data);
747 g_free (data);
749 atp_user_tool_set_flag (this->tool, ATP_TOOL_ENABLE | (gtk_toggle_button_get_active(this->enabled_tb) ? ATP_SET : ATP_CLEAR));
751 atp_user_tool_set_flag (this->tool, ATP_TOOL_AUTOSAVE | (gtk_toggle_button_get_active(this->autosave_tb) ? ATP_SET : ATP_CLEAR));
753 atp_user_tool_set_flag (this->tool, ATP_TOOL_TERMINAL | (gtk_toggle_button_get_active(this->terminal_tb) ? ATP_SET : ATP_CLEAR));
756 atp_user_tool_set_output (this->tool, get_combo_box_value (this->output_com));
757 atp_user_tool_set_error (this->tool, get_combo_box_value (this->error_com));
758 in_type = get_combo_box_value (this->input_com);
759 switch (in_type)
761 case ATP_TIN_FILE:
762 case ATP_TIN_STRING:
763 data = gtk_editable_get_chars(this->input_en, 0, -1);
764 atp_user_tool_set_input (this->tool, in_type, data);
765 g_free (data);
766 break;
767 default:
768 atp_user_tool_set_input (this->tool, in_type, NULL);
769 break;
772 atp_user_tool_set_accelerator (this->tool, accel_key, accel_mods);
774 value = gnome_icon_entry_get_filename (this->icon_en);
775 atp_user_tool_set_icon (this->tool, value);
776 g_free (value);
778 /* Open script in editor if requested */
779 if (gtk_toggle_button_get_active (this->script_tb))
781 IAnjutaDocumentManager *docman;
782 IAnjutaEditor *editor;
784 /* Check that default script directory exist */
785 data = g_build_filename (g_get_home_dir(), LOCAL_ANJUTA_SCRIPT_DIRECTORY, NULL);
786 make_directory (data);
787 g_free (data);
789 data = gtk_editable_get_chars(this->command_en, 0, -1);
791 if (!g_file_test (data, G_FILE_TEST_EXISTS))
793 FILE* sh;
795 /* Create default script */
796 sh = fopen (data, "wt");
797 if (sh != NULL)
799 gint previous;
801 fprintf(sh, "#!\n#\tScript template generated by Anjuta.\n#\tYou can pass argument using command line parameters\n#\n\n");
802 fclose (sh);
804 /* Make this file executable */
805 previous = umask (0666);
806 chmod (data, 0777 & ~previous);
807 umask (previous);
811 /* Load the script in an editor window */
812 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (this->parent->plugin)->shell, IAnjutaDocumentManager, NULL);
813 if (docman == NULL)
815 anjuta_util_dialog_error(GTK_WINDOW (this->dialog), _("Unable to edit script"));
816 return;
819 editor = ianjuta_document_manager_find_editor_with_path (docman, data, NULL);
820 if (editor == NULL)
822 IAnjutaFileLoader* loader;
823 gchar *uri;
825 /* Not found, load file */
826 loader = IANJUTA_FILE_LOADER (anjuta_shell_get_interface (ANJUTA_PLUGIN (this->parent->plugin)->shell, IAnjutaFileLoader, NULL));
827 uri = g_strdup_printf("file:///%s", data);
828 ianjuta_file_loader_load (loader, uri, FALSE, NULL);
829 g_free (uri);
831 else
833 /* Set as current */
834 ianjuta_document_manager_set_current_editor (docman, editor, NULL);
836 g_free (data);
840 atp_tool_dialog_refresh (this->parent, atp_user_tool_get_name (this->tool));
842 atp_tool_editor_free (this);
845 static void
846 on_editor_param_variable_show (GtkButton *button, gpointer user_data)
848 ATPToolEditor* this = (ATPToolEditor*)user_data;
850 atp_variable_dialog_show (&this->param_var, ATP_DEFAULT_VARIABLE);
853 static void
854 on_editor_dir_variable_show (GtkButton *button, gpointer user_data)
856 ATPToolEditor* this = (ATPToolEditor*)user_data;
858 atp_variable_dialog_show (&this->dir_var, ATP_DIRECTORY_VARIABLE);
861 static void
862 on_editor_input_variable_show (GtkButton *button, gpointer user_data)
864 ATPToolEditor* this = (ATPToolEditor*)user_data;
866 switch (get_combo_box_value (this->input_com))
868 case ATP_TIN_FILE:
869 atp_variable_dialog_show (&this->input_file_var, ATP_FILE_VARIABLE);
870 break;
871 case ATP_TIN_STRING:
872 atp_variable_dialog_show (&this->input_string_var, ATP_DEFAULT_VARIABLE);
873 break;
877 static gboolean
878 on_editor_get_keys(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
880 ATPToolEditor *this = (ATPToolEditor*)user_data;
881 GdkDisplay *display;
882 guint accel_key = 0;
883 GdkModifierType accel_mods = 0;
884 GdkModifierType consumed_mods = 0;
885 gboolean delete = FALSE;
886 gboolean edited = FALSE;
888 switch (event->keyval)
890 case GDK_Shift_L:
891 case GDK_Shift_R:
892 case GDK_Control_L:
893 case GDK_Control_R:
894 case GDK_Alt_L:
895 case GDK_Alt_R:
896 return TRUE;
897 case GDK_Escape:
898 break;
899 case GDK_Delete:
900 case GDK_KP_Delete:
901 case GDK_BackSpace:
902 delete = TRUE;
903 break;
904 default:
905 display = gtk_widget_get_display (widget);
906 gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
907 event->hardware_keycode,
908 event->state,
909 event->group,
910 NULL, NULL, NULL, &consumed_mods);
912 accel_key = gdk_keyval_to_lower (event->keyval);
913 accel_mods = (event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_mods);
915 /* If lowercasing affects the keysym, then we need to include SHIFT
916 * in the modifiers, We re-upper case when we match against the
917 * keyval, but display and save in caseless form.
919 if (accel_key != event->keyval)
920 accel_mods |= GDK_SHIFT_MASK;
922 edited = gtk_accelerator_valid (accel_key, accel_mods);
923 break;
926 if (delete || edited)
928 /* Remove previous shortcut */
929 if (this->shortcut != NULL) g_free (this->shortcut);
931 /* Set new one */
932 this->shortcut = delete ? NULL : gtk_accelerator_name (accel_key, accel_mods);
935 gtk_toggle_button_set_active (this->shortcut_bt, FALSE);
937 return TRUE;
940 static void
941 on_editor_shortcut_toggle (GtkToggleButton *tb, gpointer user_data)
943 ATPToolEditor *this = (ATPToolEditor *)user_data;
945 if (gtk_toggle_button_get_active (tb))
947 gtk_grab_add(GTK_WIDGET(tb));
949 g_signal_connect (G_OBJECT (tb), "key_press_event", G_CALLBACK (on_editor_get_keys), this);
950 gtk_button_set_label (GTK_BUTTON (tb), _("New accelerator..."));
952 else
954 g_signal_handlers_disconnect_by_func (G_OBJECT (this->shortcut_bt), G_CALLBACK (on_editor_get_keys), this);
955 gtk_grab_remove (GTK_WIDGET(this->shortcut_bt));
957 atp_editor_update_shortcut (this);
961 gboolean
962 atp_tool_editor_show (ATPToolEditor* this)
964 GladeXML *xml;
966 if (this->dialog != NULL)
968 /* dialog is already displayed */
969 gtk_window_present (GTK_WINDOW (this->dialog));
970 return TRUE;
973 if (NULL == (xml = glade_xml_new(GLADE_FILE, TOOL_EDITOR, NULL)))
975 anjuta_util_dialog_error (atp_tool_dialog_get_window (this->parent), _("Unable to build user interface for tool editor"));
976 g_free(this);
978 return FALSE;
980 this->dialog = glade_xml_get_widget(xml, TOOL_EDITOR);
981 gtk_widget_show (this->dialog);
982 gtk_window_set_transient_for (GTK_WINDOW (this->dialog), atp_plugin_get_app_window (this->parent->plugin));
984 this->name_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_NAME));
985 this->command_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_COMMAND));
986 this->param_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_PARAM));
987 atp_variable_dialog_set_entry (&this->param_var, this->param_en);
988 this->dir_en = GTK_EDITABLE (glade_xml_get_widget (xml, TOOL_WORKING_DIR));
989 atp_variable_dialog_set_entry (&this->dir_var, this->dir_en);
990 this->enabled_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, TOOL_ENABLED));
991 this->terminal_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_TERMINAL));
992 this->autosave_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_AUTOSAVE));
993 this->script_tb = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_SCRIPT));
994 this->output_com = GTK_COMBO_BOX (glade_xml_get_widget(xml, TOOL_OUTPUT));
995 this->error_com = GTK_COMBO_BOX (glade_xml_get_widget(xml, TOOL_ERROR));
996 this->input_com = GTK_COMBO_BOX (glade_xml_get_widget(xml, TOOL_INPUT));
997 this->input_en = GTK_EDITABLE (glade_xml_get_widget(xml, TOOL_INPUT_VALUE));
998 this->input_var_bt = GTK_BUTTON (glade_xml_get_widget(xml, TOOL_INPUT_VARIABLE));
999 this->shortcut_bt = GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, TOOL_SHORTCUT));
1000 atp_variable_dialog_set_entry (&this->input_file_var, this->input_en);
1001 atp_variable_dialog_set_entry (&this->input_string_var, this->input_en);
1002 this->icon_en = GNOME_ICON_ENTRY (glade_xml_get_widget(xml, TOOL_ICON));
1004 /* Add combox box value */
1005 set_combo_box_enum_model (this->error_com, atp_get_error_type_list());
1006 set_combo_box_enum_model (this->output_com, atp_get_output_type_list());
1007 set_combo_box_enum_model (this->input_com, atp_get_input_type_list());
1009 atp_clear_tool_editor (this);
1010 atp_populate_tool_editor (this);
1011 atp_update_sensitivity (this);
1013 /* Connect all signals */
1014 glade_xml_signal_connect_data (xml, EDITOR_RESPONSE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_response), this);
1015 glade_xml_signal_connect_data (xml, EDITOR_PARAM_VARIABLE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_param_variable_show), this);
1016 glade_xml_signal_connect_data (xml, EDITOR_DIR_VARIABLE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_dir_variable_show), this);
1017 glade_xml_signal_connect_data (xml, EDITOR_TOGGLE_SHORCUT_SIGNAL, GTK_SIGNAL_FUNC (on_editor_shortcut_toggle), this);
1018 glade_xml_signal_connect_data (xml, EDITOR_TOGGLE_TERMINAL_SIGNAL, GTK_SIGNAL_FUNC (on_editor_terminal_toggle), this);
1019 glade_xml_signal_connect_data (xml, EDITOR_TOGGLE_SCRIPT_SIGNAL, GTK_SIGNAL_FUNC (on_editor_script_toggle), this);
1020 glade_xml_signal_connect_data (xml, EDITOR_INPUT_VARIABLE_SIGNAL, GTK_SIGNAL_FUNC (on_editor_input_variable_show), this);
1021 glade_xml_signal_connect_data (xml, EDITOR_INPUT_CHANGED_SIGNAL, GTK_SIGNAL_FUNC (on_editor_input_changed), this);
1023 g_object_unref (xml);
1025 return TRUE;
1028 ATPToolEditor*
1029 atp_tool_editor_new (ATPUserTool *tool, ATPToolEditorList *list, struct _ATPToolDialog *dialog)
1031 ATPToolEditor *this;
1033 /* Search a already existing tool editor with same name */
1034 for (this = list->first; this != NULL; this = this->next)
1036 /* Name use the same string, so a string comparaison is not necessary */
1037 if (atp_user_tool_get_name (this->tool) == atp_user_tool_get_name (tool))
1039 return this;
1043 /* Not found, create a new object */
1044 this = g_new0(ATPToolEditor, 1);
1045 this->parent = dialog;
1046 this->owner = list;
1047 this->tool = tool;
1048 atp_variable_dialog_construct (&this->param_var, this, ATP_VARIABLE_DEFAULT);
1049 atp_variable_dialog_construct (&this->dir_var, this, ATP_VARIABLE_REPLACE);
1050 atp_variable_dialog_construct (&this->input_file_var, this, ATP_VARIABLE_REPLACE);
1051 atp_variable_dialog_construct (&this->input_string_var, this, ATP_VARIABLE_REPLACE);
1053 /* Add it in the list */
1054 if (list != NULL)
1056 this->next = list->first;
1057 list->first = this;
1060 return this;
1063 gboolean
1064 atp_tool_editor_free (ATPToolEditor *this)
1066 ATPToolEditor **prev;
1068 atp_variable_dialog_destroy (&this->input_string_var);
1069 atp_variable_dialog_destroy (&this->input_file_var);
1070 atp_variable_dialog_destroy (&this->dir_var);
1071 atp_variable_dialog_destroy (&this->param_var);
1073 if (this->shortcut != NULL) g_free (this->shortcut);
1075 if (this->owner == NULL)
1077 /* tool editor is not in a list */
1078 gtk_widget_destroy (GTK_WIDGET (this->dialog));
1079 g_free (this);
1081 return TRUE;
1084 /* Search tool editor in list */
1085 for (prev = &this->owner->first; *prev != NULL; prev = &((*prev)->next))
1087 if (*prev == this)
1089 /* remove tool editor from list */
1090 *prev = this->next;
1091 /* delete tool editor object */
1092 gtk_widget_destroy (GTK_WIDGET (this->dialog));
1093 g_free (this);
1095 return TRUE;
1099 /* tool editor not found in list */
1100 return FALSE;
1103 /* Tool editor list
1104 * This list all the current active tool editors, it is mainly useful for
1105 * avoiding to have two dialogs editing the same tool. It could be possible
1106 * because the tool editing dialog is not modal.
1107 *---------------------------------------------------------------------------*/
1109 ATPToolEditorList*
1110 atp_tool_editor_list_construct (ATPToolEditorList* this)
1112 this->first = NULL;
1114 return this;
1117 void
1118 atp_tool_editor_list_destroy (ATPToolEditorList* this)
1120 ATPToolEditor *ted;
1122 for ( ; (ted = this->first) != NULL;)
1124 atp_tool_editor_free (ted);