1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * plugin.c
4 * Copyright (C) Ishan Chattopadhyaya 2009 <ichattopadhyaya@gmail.com>
5 *
6 * plugin.c is free software.
7 *
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * plugin.c is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with plugin.c. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
23 */
24
25 #include <config.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <libanjuta/anjuta-shell.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/interfaces/ianjuta-iterable.h>
31 #include <libanjuta/interfaces/ianjuta-document.h>
32 #include <libanjuta/interfaces/ianjuta-document-manager.h>
33 #include <libanjuta/interfaces/ianjuta-editor.h>
34 #include <libanjuta/interfaces/ianjuta-file.h>
35 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
36 #include <libanjuta/interfaces/ianjuta-editor-language.h>
37 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
38 #include <libanjuta/interfaces/ianjuta-preferences.h>
39 #include <libanjuta/interfaces/ianjuta-language.h>
40 #include <libanjuta/interfaces/ianjuta-indenter.h>
41
42 #include "plugin.h"
43 #include "python-indentation.h"
44
45 /* Pixmaps */
46 #define ANJUTA_STOCK_AUTOINDENT "anjuta-indent"
47
48 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-indentation-python-style.xml"
49 #define PROPERTIES_FILE_UI PACKAGE_DATA_DIR"/glade/anjuta-indentation-python-style.ui"
50 #define ICON_FILE "anjuta-indentation-python-style-plugin.png"
51
52 /* Preferences keys */
53 #define ANJUTA_PREF_SCHEMA_PREFIX "org.gnome.anjuta."
54 #define PREF_SCHEMA "org.gnome.anjuta.plugins.indent-python"
55
56 static gpointer parent_class;
57
58 static void
on_editor_char_inserted_python(IAnjutaEditor * editor,IAnjutaIterable * insert_pos,gchar ch,IndentPythonPlugin * plugin)59 on_editor_char_inserted_python (IAnjutaEditor *editor,
60 IAnjutaIterable *insert_pos,
61 gchar ch,
62 IndentPythonPlugin *plugin)
63 {
64 python_indent (plugin, editor, insert_pos, ch);
65 }
66
67 static void
install_support(IndentPythonPlugin * lang_plugin)68 install_support (IndentPythonPlugin *lang_plugin)
69 {
70 IAnjutaLanguage* lang_manager =
71 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin)->shell,
72 IAnjutaLanguage, NULL);
73
74 if (!lang_manager)
75 return;
76
77 if (lang_plugin->support_installed)
78 return;
79
80 lang_plugin->current_language =
81 ianjuta_language_get_name_from_editor (lang_manager,
82 IANJUTA_EDITOR_LANGUAGE (lang_plugin->current_editor), NULL);
83
84 if (lang_plugin->current_language &&
85 (g_str_equal (lang_plugin->current_language, "Python")))
86 {
87 g_signal_connect (lang_plugin->current_editor,
88 "char-added",
89 G_CALLBACK (on_editor_char_inserted_python),
90 lang_plugin);
91 }
92 else
93 {
94 return;
95 }
96
97 python_indent_init (lang_plugin);
98 /* Disable editor intern auto-indent */
99 ianjuta_editor_set_auto_indent (IANJUTA_EDITOR(lang_plugin->current_editor),
100 FALSE, NULL);
101
102 lang_plugin->support_installed = TRUE;
103 }
104
105 static void
uninstall_support(IndentPythonPlugin * lang_plugin)106 uninstall_support (IndentPythonPlugin *lang_plugin)
107 {
108 if (!lang_plugin->support_installed)
109 return;
110
111 if (lang_plugin->current_language &&
112 (g_str_equal (lang_plugin->current_language, "Python")))
113 {
114 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
115 G_CALLBACK (on_editor_char_inserted_python),
116 lang_plugin);
117 }
118
119 lang_plugin->support_installed = FALSE;
120 }
121
122 static void
on_editor_language_changed(IAnjutaEditor * editor,const gchar * new_language,IndentPythonPlugin * plugin)123 on_editor_language_changed (IAnjutaEditor *editor,
124 const gchar *new_language,
125 IndentPythonPlugin *plugin)
126 {
127 uninstall_support (plugin);
128 install_support (plugin);
129 }
130
131 static void
on_editor_added(AnjutaPlugin * plugin,const gchar * name,const GValue * value,gpointer data)132 on_editor_added (AnjutaPlugin *plugin, const gchar *name,
133 const GValue *value, gpointer data)
134 {
135 IndentPythonPlugin *lang_plugin;
136 IAnjutaDocument* doc = IANJUTA_DOCUMENT(g_value_get_object (value));
137 lang_plugin = ANJUTA_PLUGIN_INDENT_PYTHON(plugin);
138
139
140 if (IANJUTA_IS_EDITOR(doc))
141 {
142 lang_plugin->current_editor = G_OBJECT(doc);
143 }
144 else
145 {
146 lang_plugin->current_editor = NULL;
147 return;
148 }
149 if (lang_plugin->current_editor)
150 {
151 IAnjutaEditor* editor = IANJUTA_EDITOR (lang_plugin->current_editor);
152 GFile* current_editor_file = ianjuta_file_get_file (IANJUTA_FILE (editor),
153 NULL);
154
155 if (current_editor_file)
156 {
157 lang_plugin->current_editor_filename = g_file_get_path (current_editor_file);
158 g_object_unref (current_editor_file);
159 }
160
161 install_support (lang_plugin);
162 g_signal_connect (lang_plugin->current_editor, "language-changed",
163 G_CALLBACK (on_editor_language_changed),
164 plugin);
165 }
166 }
167
168 static void
on_editor_removed(AnjutaPlugin * plugin,const gchar * name,gpointer data)169 on_editor_removed (AnjutaPlugin *plugin, const gchar *name,
170 gpointer data)
171 {
172 IndentPythonPlugin *lang_plugin;
173 lang_plugin = ANJUTA_PLUGIN_INDENT_PYTHON (plugin);
174
175 if (lang_plugin->current_editor)
176 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
177 G_CALLBACK (on_editor_language_changed),
178 plugin);
179
180 uninstall_support (lang_plugin);
181
182
183 g_free (lang_plugin->current_editor_filename);
184 lang_plugin->current_editor_filename = NULL;
185 lang_plugin->current_editor = NULL;
186 lang_plugin->current_language = NULL;
187 }
188
189 static void
on_auto_indent(GtkAction * action,gpointer data)190 on_auto_indent (GtkAction *action, gpointer data)
191 {
192 IndentPythonPlugin *lang_plugin = ANJUTA_PLUGIN_INDENT_PYTHON (data);
193
194 python_indent_auto (lang_plugin, NULL, NULL);
195 }
196
197 static GtkActionEntry actions[] = {
198 {
199 "ActionMenuEdit",
200 NULL, N_("_Edit"),
201 NULL, NULL, NULL
202 },
203 {
204 "ActionEditAutoindent",
205 GTK_STOCK_NEW, //ANJUTA_STOCK_AUTOINDENT,
206 N_("Auto-Indent"), "<control>i",
207 N_("Auto-indent current line or selection based on indentation settings"),
208 G_CALLBACK (on_auto_indent)
209 }
210 };
211
212 static gboolean
indent_python_plugin_activate(AnjutaPlugin * plugin)213 indent_python_plugin_activate (AnjutaPlugin *plugin)
214 {
215 AnjutaUI *ui;
216
217 IndentPythonPlugin *python_plugin;
218 python_plugin = (IndentPythonPlugin*) plugin;
219
220 python_plugin->prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
221
222 /* Add all UI actions and merge UI */
223 ui = anjuta_shell_get_ui (plugin->shell, NULL);
224
225 python_plugin->action_group =
226 anjuta_ui_add_action_group_entries (ui, "ActionGroupPythonIndent",
227 _("Python Indentation"),
228 actions,
229 G_N_ELEMENTS (actions),
230 GETTEXT_PACKAGE, TRUE,
231 plugin);
232 python_plugin->uiid = anjuta_ui_merge (ui, UI_FILE);
233
234 /* Add watches */
235 python_plugin->editor_watch_id = anjuta_plugin_add_watch (plugin,
236 IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
237 on_editor_added,
238 on_editor_removed,
239 NULL);
240 return TRUE;
241 }
242
243 static gboolean
indent_python_plugin_deactivate(AnjutaPlugin * plugin)244 indent_python_plugin_deactivate (AnjutaPlugin *plugin)
245 {
246
247 AnjutaUI *ui;
248 IndentPythonPlugin *lang_plugin;
249 lang_plugin = (IndentPythonPlugin*) (plugin);
250
251 anjuta_plugin_remove_watch (plugin,
252 lang_plugin->editor_watch_id,
253 TRUE);
254
255 ui = anjuta_shell_get_ui (plugin->shell, NULL);
256 anjuta_ui_remove_action_group (ui, ANJUTA_PLUGIN_INDENT_PYTHON(plugin)->action_group);
257 anjuta_ui_unmerge (ui, ANJUTA_PLUGIN_INDENT_PYTHON(plugin)->uiid);
258
259 return TRUE;
260 }
261
262 static void
indent_python_plugin_finalize(GObject * obj)263 indent_python_plugin_finalize (GObject *obj)
264 {
265 /* Finalization codes here */
266 G_OBJECT_CLASS (parent_class)->finalize (obj);
267 }
268
269 static void
indent_python_plugin_dispose(GObject * obj)270 indent_python_plugin_dispose (GObject *obj)
271 {
272 /* Disposition codes */
273 IndentPythonPlugin *plugin = (IndentPythonPlugin*)obj;
274
275 if (plugin->settings)
276 g_object_unref (plugin->settings);
277 plugin->settings = NULL;
278
279 G_OBJECT_CLASS (parent_class)->dispose (obj);
280 }
281
282 static void
indent_python_plugin_instance_init(GObject * obj)283 indent_python_plugin_instance_init (GObject *obj)
284 {
285 IndentPythonPlugin *plugin = (IndentPythonPlugin*)obj;
286 plugin->action_group = NULL;
287 plugin->current_editor = NULL;
288 plugin->current_language = NULL;
289 plugin->editor_watch_id = 0;
290 plugin->uiid = 0;
291 plugin->settings = g_settings_new (PREF_SCHEMA);
292 }
293
294 static void
indent_python_plugin_class_init(GObjectClass * klass)295 indent_python_plugin_class_init (GObjectClass *klass)
296 {
297 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
298
299 parent_class = g_type_class_peek_parent (klass);
300
301 plugin_class->activate = indent_python_plugin_activate;
302 plugin_class->deactivate = indent_python_plugin_deactivate;
303 klass->finalize = indent_python_plugin_finalize;
304 klass->dispose = indent_python_plugin_dispose;
305 }
306
307
308 static void
ipreferences_merge(IAnjutaPreferences * ipref,AnjutaPreferences * prefs,GError ** e)309 ipreferences_merge (IAnjutaPreferences* ipref, AnjutaPreferences* prefs,
310 GError** e)
311 {
312 GError* error = NULL;
313 IndentPythonPlugin* plugin = ANJUTA_PLUGIN_INDENT_PYTHON (ipref);
314 plugin->bxml = gtk_builder_new ();
315
316 /* Add preferences */
317 if (!gtk_builder_add_from_file (plugin->bxml, PROPERTIES_FILE_UI, &error))
318 {
319 g_warning ("Couldn't load builder file: %s", error->message);
320 g_error_free (error);
321 }
322 anjuta_preferences_add_from_builder (prefs,
323 plugin->bxml, plugin->settings,
324 "preferences", _("Indentation"),
325 ICON_FILE);
326 }
327
328 static void
ipreferences_unmerge(IAnjutaPreferences * ipref,AnjutaPreferences * prefs,GError ** e)329 ipreferences_unmerge (IAnjutaPreferences* ipref, AnjutaPreferences* prefs,
330 GError** e)
331 {
332 IndentPythonPlugin* plugin = ANJUTA_PLUGIN_INDENT_PYTHON (ipref);
333 anjuta_preferences_remove_page(prefs, _("Indentation"));
334 g_object_unref (plugin->bxml);
335 }
336
337 static void
ipreferences_iface_init(IAnjutaPreferencesIface * iface)338 ipreferences_iface_init (IAnjutaPreferencesIface* iface)
339 {
340 iface->merge = ipreferences_merge;
341 iface->unmerge = ipreferences_unmerge;
342 }
343
344 static void
iindenter_indent(IAnjutaIndenter * indenter,IAnjutaIterable * start,IAnjutaIterable * end,GError ** e)345 iindenter_indent (IAnjutaIndenter* indenter,
346 IAnjutaIterable* start,
347 IAnjutaIterable* end,
348 GError** e)
349 {
350 IndentPythonPlugin* plugin = ANJUTA_PLUGIN_INDENT_PYTHON (indenter);
351
352 python_indent_auto (plugin,
353 start, end);
354 }
355
356 static void
iindenter_iface_init(IAnjutaIndenterIface * iface)357 iindenter_iface_init (IAnjutaIndenterIface* iface)
358 {
359 iface->indent = iindenter_indent;
360 }
361
362 ANJUTA_PLUGIN_BEGIN (IndentPythonPlugin, indent_python_plugin);
363 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences, IANJUTA_TYPE_PREFERENCES);
364 ANJUTA_PLUGIN_ADD_INTERFACE(iindenter, IANJUTA_TYPE_INDENTER);
365 ANJUTA_PLUGIN_END;
366
367 ANJUTA_SIMPLE_PLUGIN (IndentPythonPlugin, indent_python_plugin);
368