2 * classbuilder.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2007 Alexander Rodin <rodin(dot)alexander(at)gmail(dot)com>
5 * Copyright 2007-2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6 * Copyright 2007-2010 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program 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. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 /* Class Builder - creates source files containing a new class interface and definition. */
28 #include "geanyplugin.h"
31 GeanyData
*geany_data
;
32 GeanyFunctions
*geany_functions
;
35 PLUGIN_VERSION_CHECK(GEANY_API_VERSION
)
37 PLUGIN_SET_INFO(_("Class Builder"), _("Creates source files for new class types."), VERSION
,
41 static GtkWidget
*main_menu_item
= NULL
;
50 typedef struct _ClassInfo ClassInfo
;
57 gchar
*class_name_low
;
64 gchar
*constructor_decl
;
65 gchar
*destructor_decl
;
67 gchar
*constructor_impl
;
68 gchar
*destructor_impl
;
69 gchar
*gtk_destructor_registration
;
72 typedef struct _CreateClassDialog
76 GtkWidget
*class_name_entry
;
77 GtkWidget
*header_entry
;
78 GtkWidget
*source_entry
;
79 GtkWidget
*base_name_entry
;
80 GtkWidget
*base_header_entry
;
81 GtkWidget
*base_header_global_box
;
82 GtkWidget
*base_gtype_entry
;
83 GtkWidget
*create_constructor_box
;
84 GtkWidget
*create_destructor_box
;
85 GtkWidget
*gtk_constructor_type_entry
;
89 static const gchar templates_cpp_class_header
[] = "{fileheader}\n\n\
90 #ifndef {header_guard}\n\
91 #define {header_guard}\n\
93 class {class_name}{base_decl}\n\
100 /* add your private declarations */\n\
103 #endif /* {header_guard} */ \n\
106 static const gchar templates_cpp_class_source
[] = "{fileheader}\n\n\
107 #include \"{header}\"\n\
109 {constructor_impl}\n\
113 static const gchar templates_gtk_class_header
[] = "{fileheader}\n\n\
114 #ifndef __{header_guard}__\n\
115 #define __{header_guard}__\n\
119 #define {class_name_up}_TYPE ({class_name_low}_get_type())\n\
120 #define {class_name_up}(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\\\n\
121 {class_name_up}_TYPE, {class_name}))\n\
122 #define {class_name_up}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\\\n\
123 {class_name_up}_TYPE, {class_name}Class))\n\
124 #define IS_{class_name_up}(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\\\n\
125 {class_name_up}_TYPE))\n\
126 #define IS_{class_name_up}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\\\n\
127 {class_name_up}_TYPE))\n\
129 typedef struct _{class_name} {class_name};\n\
130 typedef struct _{class_name}Class {class_name}Class;\n\
132 struct _{class_name}Private;\n\
134 struct _{class_name}\n\
136 {base_name} parent;\n\
137 /* add your public declarations here */\n\
139 struct _{class_name}Private *priv;\n\
142 struct _{class_name}Class\n\
144 {base_name}Class parent_class;\n\
147 GType {class_name_low}_get_type (void);\n\
152 #endif /* __{header_guard}__ */\n\
155 static const gchar templates_gtk_class_source
[] = "{fileheader}\n\
156 #include \"{header}\"\n\
158 typedef struct _{class_name}Private {class_name}Private;\n\
160 struct _{class_name}Private\n\
162 /* add your private declarations here */\n\
167 G_DEFINE_TYPE({class_name}, {class_name_low}, {base_gtype});\n\
169 static void {class_name_low}_class_init({class_name}Class *klass)\n\
171 {gtk_destructor_registration}\n\
172 g_type_class_add_private((gpointer)klass, sizeof({class_name}Private));\n\
177 static void {class_name_low}_init({class_name} *self)\n\
179 self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self,\n\
180 {class_name_up}_TYPE, {class_name}Private);\n\
184 {constructor_impl}\n\
188 static void cc_dlg_on_set_sensitive_toggled(GtkWidget
*toggle_button
, GtkWidget
*target_widget
);
189 static void cc_dlg_on_class_name_entry_changed(GtkWidget
*entry
, CreateClassDialog
*cc_dlg
);
190 static void cc_dlg_on_base_name_entry_changed(GtkWidget
*entry
, CreateClassDialog
*cc_dlg
);
191 static gboolean
create_class(CreateClassDialog
*cc_dlg
);
194 /* The list must be ended with NULL as an extra check that arg_count is correct. */
196 free_pointers(gsize arg_count
, ...)
202 va_start(a
, arg_count
);
203 for (i
= 0; i
< arg_count
; i
++)
205 ptr
= va_arg(a
, gpointer
);
208 ptr
= va_arg(a
, gpointer
);
210 g_warning("Wrong arg_count!");
216 get_template_class_header(ClassInfo
*class_info
)
218 gchar
*fileheader
= NULL
;
219 GString
*template = NULL
;
221 switch (class_info
->type
)
223 case GEANY_CLASS_TYPE_CPP
:
224 fileheader
= templates_get_template_fileheader(GEANY_FILETYPES_CPP
, class_info
->header
);
225 template = g_string_new(templates_cpp_class_header
);
226 utils_string_replace_all(template, "{fileheader}", fileheader
);
227 utils_string_replace_all(template, "{header_guard}", class_info
->header_guard
);
228 utils_string_replace_all(template, "{base_include}", class_info
->base_include
);
229 utils_string_replace_all(template, "{class_name}", class_info
->class_name
);
230 utils_string_replace_all(template, "{base_decl}", class_info
->base_decl
);
231 utils_string_replace_all(template, "{constructor_decl}",
232 class_info
->constructor_decl
);
233 utils_string_replace_all(template, "{destructor_decl}",
234 class_info
->destructor_decl
);
237 case GEANY_CLASS_TYPE_GTK
:
238 fileheader
= templates_get_template_fileheader(GEANY_FILETYPES_C
, class_info
->header
);
239 template = g_string_new(templates_gtk_class_header
);
240 utils_string_replace_all(template, "{fileheader}", fileheader
);
241 utils_string_replace_all(template, "{header_guard}", class_info
->header_guard
);
242 utils_string_replace_all(template, "{base_include}", class_info
->base_include
);
243 utils_string_replace_all(template, "{class_name}", class_info
->class_name
);
244 utils_string_replace_all(template, "{class_name_up}", class_info
->class_name_up
);
245 utils_string_replace_all(template, "{class_name_low}", class_info
->class_name_low
);
246 utils_string_replace_all(template, "{base_name}", class_info
->base_name
);
247 utils_string_replace_all(template, "{constructor_decl}",
248 class_info
->constructor_decl
);
255 return g_string_free(template, FALSE
);
262 get_template_class_source(ClassInfo
*class_info
)
264 gchar
*fileheader
= NULL
;
265 GString
*template = NULL
;
267 switch (class_info
->type
)
269 case GEANY_CLASS_TYPE_CPP
:
270 fileheader
= templates_get_template_fileheader(GEANY_FILETYPES_CPP
, class_info
->source
);
271 template = g_string_new(templates_cpp_class_source
);
272 utils_string_replace_all(template, "{fileheader}", fileheader
);
273 utils_string_replace_all(template, "{header}", class_info
->header
);
274 utils_string_replace_all(template, "{class_name}", class_info
->class_name
);
275 utils_string_replace_all(template, "{base_include}", class_info
->base_include
);
276 utils_string_replace_all(template, "{base_name}", class_info
->base_name
);
277 utils_string_replace_all(template, "{constructor_impl}",
278 class_info
->constructor_impl
);
279 utils_string_replace_all(template, "{destructor_impl}",
280 class_info
->destructor_impl
);
283 case GEANY_CLASS_TYPE_GTK
:
284 fileheader
= templates_get_template_fileheader(GEANY_FILETYPES_C
, class_info
->source
);
285 template = g_string_new(templates_gtk_class_source
);
286 utils_string_replace_all(template, "{fileheader}", fileheader
);
287 utils_string_replace_all(template, "{header}", class_info
->header
);
288 utils_string_replace_all(template, "{class_name}", class_info
->class_name
);
289 utils_string_replace_all(template, "{class_name_up}", class_info
->class_name_up
);
290 utils_string_replace_all(template, "{class_name_low}", class_info
->class_name_low
);
291 utils_string_replace_all(template, "{base_name}", class_info
->base_name
);
292 utils_string_replace_all(template, "{base_gtype}", class_info
->base_gtype
);
293 utils_string_replace_all(template, "{destructor_decl}", class_info
->destructor_decl
);
294 utils_string_replace_all(template, "{constructor_impl}",
295 class_info
->constructor_impl
);
296 utils_string_replace_all(template, "{destructor_impl}",
297 class_info
->destructor_impl
);
298 utils_string_replace_all(template, "{gtk_destructor_registration}",
299 class_info
->gtk_destructor_registration
);
306 return g_string_free(template, FALSE
);
312 void show_dialog_create_class(gint type
)
314 CreateClassDialog
*cc_dlg
;
322 cc_dlg
= g_new0(CreateClassDialog
, 1);
323 cc_dlg
->class_type
= type
;
325 cc_dlg
->dialog
= gtk_dialog_new_with_buttons(_("Create Class"),
326 GTK_WINDOW(geany
->main_widgets
->window
),
328 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
329 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
331 g_signal_connect_swapped(cc_dlg
->dialog
, "destroy", G_CALLBACK(g_free
), (gpointer
)cc_dlg
);
333 main_box
= ui_dialog_vbox_new(GTK_DIALOG(cc_dlg
->dialog
));
335 frame
= ui_frame_new_with_alignment(_("Class"), &align
);
336 gtk_container_add(GTK_CONTAINER(main_box
), frame
);
338 vbox
= gtk_vbox_new(FALSE
, 10);
339 gtk_container_add(GTK_CONTAINER(align
), vbox
);
341 hbox
= gtk_hbox_new(FALSE
, 10);
342 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
344 label
= gtk_label_new(_("Class name:"));
345 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
347 cc_dlg
->class_name_entry
= gtk_entry_new();
348 gtk_box_pack_start(GTK_BOX(hbox
), cc_dlg
->class_name_entry
, TRUE
, TRUE
, 0);
349 g_signal_connect(cc_dlg
->class_name_entry
, "changed",
350 G_CALLBACK(cc_dlg_on_class_name_entry_changed
), cc_dlg
);
352 hbox
= gtk_hbox_new(FALSE
, 10);
353 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
355 label
= gtk_label_new(_("Header file:"));
356 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
358 cc_dlg
->header_entry
= gtk_entry_new();
359 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->header_entry
);
361 hbox
= gtk_hbox_new(FALSE
, 10);
362 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
364 label
= gtk_label_new(_("Source file:"));
365 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
367 cc_dlg
->source_entry
= gtk_entry_new();
368 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->source_entry
);
370 frame
= ui_frame_new_with_alignment(_("Inheritance"), &align
);
371 gtk_container_add(GTK_CONTAINER(main_box
), frame
);
373 vbox
= gtk_vbox_new(FALSE
, 10);
374 gtk_container_add(GTK_CONTAINER(align
), vbox
);
376 hbox
= gtk_hbox_new(FALSE
, 10);
377 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
379 label
= gtk_label_new(_("Base class:"));
380 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
382 cc_dlg
->base_name_entry
= gtk_entry_new();
383 if (type
== GEANY_CLASS_TYPE_GTK
)
384 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->base_name_entry
), "GObject");
385 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->base_name_entry
);
386 g_signal_connect(cc_dlg
->base_name_entry
, "changed",
387 G_CALLBACK(cc_dlg_on_base_name_entry_changed
), (gpointer
)cc_dlg
);
389 hbox
= gtk_hbox_new(FALSE
, 10);
390 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
392 label
= gtk_label_new(_("Base header:"));
393 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
395 cc_dlg
->base_header_entry
= gtk_entry_new();
396 if (type
== GEANY_CLASS_TYPE_GTK
)
397 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->base_header_entry
), "glib-object.h");
398 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->base_header_entry
);
400 cc_dlg
->base_header_global_box
= gtk_check_button_new_with_label(_("Global"));
401 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cc_dlg
->base_header_global_box
), TRUE
);
402 gtk_box_pack_end(GTK_BOX(hbox
), cc_dlg
->base_header_global_box
, FALSE
, FALSE
, 0);
404 if (type
== GEANY_CLASS_TYPE_GTK
)
406 hbox
= gtk_hbox_new(FALSE
, 10);
407 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
409 label
= gtk_label_new(_("Base GType:"));
410 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
412 cc_dlg
->base_gtype_entry
= gtk_entry_new();
413 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->base_gtype_entry
), "G_TYPE_OBJECT");
414 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->base_gtype_entry
);
417 frame
= ui_frame_new_with_alignment(_("Options"), &align
);
418 gtk_container_add(GTK_CONTAINER(main_box
), frame
);
420 vbox
= gtk_vbox_new(FALSE
, 10);
421 gtk_container_add(GTK_CONTAINER(align
), vbox
);
423 hbox
= gtk_hbox_new(FALSE
, 10);
424 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
426 cc_dlg
->create_constructor_box
= gtk_check_button_new_with_label(_("Create constructor"));
427 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cc_dlg
->create_constructor_box
), TRUE
);
428 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->create_constructor_box
);
430 cc_dlg
->create_destructor_box
= gtk_check_button_new_with_label(_("Create destructor"));
431 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->create_destructor_box
);
433 if (type
== GEANY_CLASS_TYPE_GTK
)
435 hbox
= gtk_hbox_new(FALSE
, 10);
436 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
437 g_signal_connect(cc_dlg
->create_constructor_box
, "toggled",
438 G_CALLBACK(cc_dlg_on_set_sensitive_toggled
), (gpointer
)hbox
);
440 label
= gtk_label_new(_("GTK+ constructor type"));
441 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
443 cc_dlg
->gtk_constructor_type_entry
= gtk_entry_new();
444 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->gtk_constructor_type_entry
), "GObject");
445 gtk_container_add(GTK_CONTAINER(hbox
), cc_dlg
->gtk_constructor_type_entry
);
448 gtk_widget_show_all(cc_dlg
->dialog
);
449 while (gtk_dialog_run(GTK_DIALOG(cc_dlg
->dialog
)) == GTK_RESPONSE_OK
)
451 if (create_class(cc_dlg
))
456 gtk_widget_destroy(cc_dlg
->dialog
);
457 /* g_object_unref(G_OBJECT(cc_dlg->dialog)); */
461 static void cc_dlg_on_set_sensitive_toggled(GtkWidget
*toggle_button
, GtkWidget
*target_widget
)
463 g_return_if_fail(toggle_button
!= NULL
);
464 g_return_if_fail(GTK_IS_TOGGLE_BUTTON(toggle_button
));
465 g_return_if_fail(target_widget
!= NULL
);
466 g_return_if_fail(GTK_IS_WIDGET(target_widget
));
468 gtk_widget_set_sensitive(target_widget
,
469 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button
)));
473 static void cc_dlg_on_class_name_entry_changed(GtkWidget
*entry
, CreateClassDialog
*cc_dlg
)
475 gchar
*class_name_down
;
479 g_return_if_fail(entry
!= NULL
);
480 g_return_if_fail(GTK_IS_ENTRY(entry
));
481 g_return_if_fail(cc_dlg
!= NULL
);
483 class_name_down
= g_ascii_strdown(gtk_entry_get_text(GTK_ENTRY(entry
)), -1);
484 class_header
= g_strconcat(class_name_down
, ".h", NULL
);
485 if (cc_dlg
->class_type
== GEANY_CLASS_TYPE_CPP
)
486 class_source
= g_strconcat(class_name_down
, ".cpp", NULL
);
488 class_source
= g_strconcat(class_name_down
, ".c", NULL
);
490 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->header_entry
), class_header
);
491 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->source_entry
), class_source
);
493 g_free(class_name_down
);
494 g_free(class_header
);
495 g_free(class_source
);
499 static gchar
* str_case_split(const gchar
*str
, gchar splitter
)
503 g_return_val_if_fail(str
!= NULL
, NULL
);
507 result
= g_string_new(NULL
);
508 g_string_append_c(result
, *str
);
509 while (*(++str
) != '\0')
511 if (g_ascii_isupper(*str
) && g_ascii_islower(result
->str
[result
->len
- 1]))
512 g_string_append_c(result
, splitter
);
513 g_string_append_c(result
, *str
);
515 return g_string_free(result
, FALSE
);
519 static void cc_dlg_on_base_name_entry_changed(GtkWidget
*entry
, CreateClassDialog
*cc_dlg
)
521 gchar
*base_name_splitted
;
525 g_return_if_fail(entry
!= NULL
);
526 g_return_if_fail(GTK_IS_ENTRY(entry
));
527 g_return_if_fail(cc_dlg
!= NULL
);
529 base_name_splitted
= str_case_split(gtk_entry_get_text(GTK_ENTRY(entry
)), '_');
530 if (! g_ascii_strncasecmp(gtk_entry_get_text(GTK_ENTRY(entry
)), "gtk", 3))
531 /*tmp = g_strconcat("gtk/", gtk_entry_get_text(GTK_ENTRY(entry)), ".h", NULL);*/
532 /* With GTK 2.14 (and later GTK 3), single header includes are encouraged */
533 tmp
= g_strdup("gtk/gtk.h");
534 else if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(entry
)), "GObject"))
535 tmp
= g_strdup("glib-object.h");
537 tmp
= g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry
)), ".h", NULL
);
538 base_header
= g_ascii_strdown(tmp
, -1);
541 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->base_header_entry
), base_header
);
543 if (cc_dlg
->class_type
== GEANY_CLASS_TYPE_GTK
)
546 if (! g_ascii_strncasecmp(gtk_entry_get_text(GTK_ENTRY(entry
)), "gtk", 3))
547 tmp
= g_strdup_printf("%.3s_TYPE%s",
549 base_name_splitted
+ 3);
550 else if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(entry
)), "GObject"))
551 tmp
= g_strdup("G_TYPE_OBJECT");
553 tmp
= g_strconcat(base_name_splitted
, "_TYPE", NULL
);
554 base_gtype
= g_ascii_strup(tmp
, -1);
555 gtk_entry_set_text(GTK_ENTRY(cc_dlg
->base_gtype_entry
), base_gtype
);
561 g_free(base_name_splitted
);
566 static gboolean
create_class(CreateClassDialog
*cc_dlg
)
568 ClassInfo
*class_info
;
573 g_return_val_if_fail(cc_dlg
!= NULL
, FALSE
);
575 if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->class_name_entry
)), ""))
578 class_info
= g_new0(ClassInfo
, 1);
579 class_info
->type
= cc_dlg
->class_type
;
580 class_info
->class_name
= g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->class_name_entry
)));
581 tmp
= str_case_split(class_info
->class_name
, '_');
582 class_info
->class_name_up
= g_ascii_strup(tmp
, -1);
583 class_info
->class_name_low
= g_ascii_strdown(class_info
->class_name_up
, -1);
584 if (! utils_str_equal(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->base_name_entry
)), ""))
586 class_info
->base_name
= g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->base_name_entry
)));
587 class_info
->base_include
= g_strdup_printf("\n#include %c%s%c\n",
588 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg
->base_header_global_box
)) ?
590 gtk_entry_get_text(GTK_ENTRY(cc_dlg
->base_header_entry
)),
591 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg
->base_header_global_box
)) ?
596 class_info
->base_name
= g_strdup("");
597 class_info
->base_include
= g_strdup("");
599 class_info
->header
= g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->header_entry
)));
600 class_info
->header_guard
= g_ascii_strup(class_info
->header
, -1);
601 g_strdelimit(class_info
->header_guard
, ".-", '_');
602 switch (class_info
->type
)
604 case GEANY_CLASS_TYPE_CPP
:
606 class_info
->source
= g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->source_entry
)));
607 if (! utils_str_equal(class_info
->base_name
, ""))
608 class_info
->base_decl
= g_strdup_printf(": public %s", class_info
->base_name
);
610 class_info
->base_decl
= g_strdup("");
611 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg
->create_constructor_box
)))
613 gchar
*base_constructor
;
615 if (utils_str_equal(class_info
->base_name
, ""))
616 base_constructor
= g_strdup("");
618 base_constructor
= g_strdup_printf("\t: %s()\n", class_info
->base_name
);
619 class_info
->constructor_decl
= g_strdup_printf("%s();\n", class_info
->class_name
);
620 class_info
->constructor_impl
= g_strdup_printf("\n%s::%s()\n%s{\n\t\n}\n",
621 class_info
->class_name
, class_info
->class_name
, base_constructor
);
622 g_free(base_constructor
);
626 class_info
->constructor_decl
= g_strdup("");
627 class_info
->constructor_impl
= g_strdup("");
629 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg
->create_destructor_box
)))
631 class_info
->destructor_decl
=
632 g_strdup_printf("virtual ~%s();\n", class_info
->class_name
);
633 class_info
->destructor_impl
= g_strdup_printf("\n%s::~%s()\n{\n\t\n}\n",
634 class_info
->class_name
, class_info
->class_name
);
638 class_info
->destructor_decl
= g_strdup("");
639 class_info
->destructor_impl
= g_strdup("");
643 case GEANY_CLASS_TYPE_GTK
:
645 class_info
->base_gtype
= g_strdup(gtk_entry_get_text(
646 GTK_ENTRY(cc_dlg
->base_gtype_entry
)));
647 class_info
->source
= g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg
->source_entry
)));
648 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg
->create_constructor_box
)))
650 class_info
->constructor_decl
= g_strdup_printf("%s*\t%s_new\t\t\t(void);\n",
651 gtk_entry_get_text(GTK_ENTRY(cc_dlg
->gtk_constructor_type_entry
)),
652 class_info
->class_name_low
);
653 class_info
->constructor_impl
= g_strdup_printf("\n"
656 "\treturn g_object_new(%s_TYPE, NULL);\n"
658 gtk_entry_get_text(GTK_ENTRY(cc_dlg
->gtk_constructor_type_entry
)),
659 class_info
->class_name_low
,
660 class_info
->class_name_up
);
664 class_info
->constructor_decl
= g_strdup("");
665 class_info
->constructor_impl
= g_strdup("");
667 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg
->create_destructor_box
)))
669 class_info
->gtk_destructor_registration
=
670 g_strdup_printf("GObjectClass *g_object_class;\n\n"
671 "\tg_object_class = G_OBJECT_CLASS(klass);\n\n"
672 "\tg_object_class->finalize = %s_finalize;\n",
673 class_info
->class_name_low
);
674 class_info
->destructor_decl
=
675 g_strdup_printf("static void %s_finalize \t\t\t(GObject *object);\n",
676 class_info
->class_name_low
);
677 class_info
->destructor_impl
= g_strdup_printf("\n"
678 "static void %s_finalize(GObject *object)\n"
681 "\tg_return_if_fail(object != NULL);\n"
682 "\tg_return_if_fail(IS_%s(object));\n\n"
683 "\tself = %s(object);\n\n"
684 "\tG_OBJECT_CLASS(%s_parent_class)->finalize(object);\n"
686 class_info
->class_name_low
,
687 class_info
->class_name
,
688 class_info
->class_name_up
,
689 class_info
->class_name_up
,
690 class_info
->class_name_low
);
694 class_info
->gtk_destructor_registration
= g_strdup("");
695 class_info
->destructor_decl
= g_strdup("");
696 class_info
->destructor_impl
= g_strdup("");
702 /* only create the files if the filename is not empty */
703 if (! utils_str_equal(class_info
->source
, ""))
705 text
= get_template_class_source(class_info
);
706 doc
= document_new_file(class_info
->source
, NULL
, NULL
);
707 sci_set_text(doc
->editor
->sci
, text
);
711 if (! utils_str_equal(class_info
->header
, ""))
713 text
= get_template_class_header(class_info
);
714 doc
= document_new_file(class_info
->header
, NULL
, NULL
);
715 sci_set_text(doc
->editor
->sci
, text
);
719 free_pointers(17, tmp
, class_info
->class_name
, class_info
->class_name_up
,
720 class_info
->base_name
, class_info
->class_name_low
, class_info
->base_include
,
721 class_info
->header
, class_info
->header_guard
, class_info
->source
, class_info
->base_decl
,
722 class_info
->constructor_decl
, class_info
->constructor_impl
,
723 class_info
->gtk_destructor_registration
, class_info
->destructor_decl
,
724 class_info
->destructor_impl
, class_info
->base_gtype
, class_info
, NULL
);
730 on_menu_create_cpp_class_activate (GtkMenuItem
*menuitem
,
733 show_dialog_create_class(GEANY_CLASS_TYPE_CPP
);
738 on_menu_create_gtk_class_activate (GtkMenuItem
*menuitem
,
741 show_dialog_create_class(GEANY_CLASS_TYPE_GTK
);
745 void plugin_init(GeanyData
*data
)
747 GtkWidget
*menu_create_class1
;
748 GtkWidget
*menu_create_class1_menu
;
749 GtkWidget
*menu_create_cpp_class
;
750 GtkWidget
*menu_create_gtk_class
;
752 menu_create_class1
= ui_image_menu_item_new (GTK_STOCK_ADD
, _("Create Cla_ss"));
753 gtk_container_add (GTK_CONTAINER (geany
->main_widgets
->tools_menu
), menu_create_class1
);
755 menu_create_class1_menu
= gtk_menu_new ();
756 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_create_class1
), menu_create_class1_menu
);
758 menu_create_cpp_class
= gtk_menu_item_new_with_mnemonic (_("_C++ Class"));
759 gtk_container_add (GTK_CONTAINER (menu_create_class1_menu
), menu_create_cpp_class
);
761 menu_create_gtk_class
= gtk_menu_item_new_with_mnemonic (_("_GTK+ Class"));
762 gtk_container_add (GTK_CONTAINER (menu_create_class1_menu
), menu_create_gtk_class
);
764 g_signal_connect(menu_create_cpp_class
, "activate",
765 G_CALLBACK (on_menu_create_cpp_class_activate
),
767 g_signal_connect(menu_create_gtk_class
, "activate",
768 G_CALLBACK (on_menu_create_gtk_class_activate
),
771 gtk_widget_show_all(menu_create_class1
);
773 ui_add_document_sensitive(menu_create_class1
);
774 main_menu_item
= menu_create_class1
;
778 void plugin_cleanup(void)
780 gtk_widget_destroy(main_menu_item
);