Add support for creating PHP classes (patch by Ondrej Donek, thanks).

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@4887 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2010-05-09 15:47:39 +00:00
parent 534e36b3bf
commit a2b0ec155b
4 changed files with 277 additions and 41 deletions

View File

@ -1,3 +1,9 @@
2010-05-09 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* THANKS, src/about.c, plugins/classbuilder.c:
Add support for creating PHP classes (patch by Ondrej Donek, thanks).
2010-05-08 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/highlighting.c:

1
THANKS
View File

@ -77,6 +77,7 @@ Jon Senior <jon(at)restlesslemon(dot)co(dot)uk> - R tagmanager parser patch
Can Koy <cankoy(at)ymail(dot)com> - Multiple changes/improvements
Yoann Le Montagner <yoann(dot)le-montagner(at)m4x(dot)org> - set VTE bold color
Dimitar Zhekov <hamster(at)mbox(dot)contact(dot)bg> - matching brace improvements patch
Ondrej Donek <ondrejd(at)gmail(dot)com> - Support for creating PHP classes with the classbuilder plugin
Translators:
------------

View File

@ -27,8 +27,7 @@
#include "geanyplugin.h"
GeanyData *geany_data;
GeanyData *geany_data;
GeanyFunctions *geany_functions;
@ -44,7 +43,8 @@ static GtkWidget *main_menu_item = NULL;
enum
{
GEANY_CLASS_TYPE_CPP,
GEANY_CLASS_TYPE_GTK
GEANY_CLASS_TYPE_GTK,
GEANY_CLASS_TYPE_PHP
};
typedef struct _ClassInfo ClassInfo;
@ -67,6 +67,11 @@ struct _ClassInfo
gchar *constructor_impl;
gchar *destructor_impl;
gchar *gtk_destructor_registration;
// These are needed only for PHP classes
gchar *namespace_decl;
gchar *implements_decl;
gchar *abstract_decl;
gchar *singleton_impl;
};
typedef struct _CreateClassDialog
@ -83,6 +88,11 @@ typedef struct _CreateClassDialog
GtkWidget *create_constructor_box;
GtkWidget *create_destructor_box;
GtkWidget *gtk_constructor_type_entry;
// These are needed only for PHP classes
GtkWidget *class_namespace_entry;
GtkWidget *class_implements_entry;
GtkWidget *create_isabstract_box;
GtkWidget *create_issingleton_box;
} CreateClassDialog;
@ -184,6 +194,18 @@ static void {class_name_low}_init({class_name} *self)\n\
{constructor_impl}\n\
";
static const gchar templates_php_class_source[] = "<?php\n\
{fileheader}\n\
{namespace_decl}\n\
{base_include}\n\
{abstract_decl}class {class_name}{base_decl}{implements_decl}\n\{\n\
{singleton_impl}\
{constructor_impl}\
{destructor_impl}\n\
// ...\n\n\
}\n\
";
static void cc_dlg_on_set_sensitive_toggled(GtkWidget *toggle_button, GtkWidget *target_widget);
static void cc_dlg_on_class_name_entry_changed(GtkWidget *entry, CreateClassDialog *cc_dlg);
@ -298,6 +320,21 @@ get_template_class_source(ClassInfo *class_info)
utils_string_replace_all(template, "{gtk_destructor_registration}",
class_info->gtk_destructor_registration);
break;
case GEANY_CLASS_TYPE_PHP:
fileheader = templates_get_template_fileheader(GEANY_FILETYPES_PHP, class_info->source);
template = g_string_new(templates_php_class_source);
utils_string_replace_all(template, "{fileheader}", fileheader);
utils_string_replace_all(template, "{namespace_decl}", class_info->namespace_decl);
utils_string_replace_all(template, "{base_include}", class_info->base_include);
utils_string_replace_all(template, "{abstract_decl}", class_info->abstract_decl);
utils_string_replace_all(template, "{class_name}", class_info->class_name);
utils_string_replace_all(template, "{base_decl}", class_info->base_decl);
utils_string_replace_all(template, "{implements_decl}", class_info->implements_decl);
utils_string_replace_all(template, "{constructor_impl}", class_info->constructor_impl);
utils_string_replace_all(template, "{destructor_impl}", class_info->destructor_impl);
utils_string_replace_all(template, "{singleton_impl}", class_info->singleton_impl);
break;
}
g_free(fileheader);
@ -331,7 +368,25 @@ void show_dialog_create_class(gint type)
g_signal_connect_swapped(cc_dlg->dialog, "destroy", G_CALLBACK(g_free), (gpointer)cc_dlg);
main_box = ui_dialog_vbox_new(GTK_DIALOG(cc_dlg->dialog));
if (type == GEANY_CLASS_TYPE_PHP)
{
frame = ui_frame_new_with_alignment(_("Namespace"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
vbox = gtk_vbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(align), vbox);
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
label = gtk_label_new(_("Namespace:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
cc_dlg->class_namespace_entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(hbox), cc_dlg->class_namespace_entry, TRUE, TRUE, 0);
}
frame = ui_frame_new_with_alignment(_("Class"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
@ -348,25 +403,28 @@ void show_dialog_create_class(gint type)
gtk_box_pack_start(GTK_BOX(hbox), cc_dlg->class_name_entry, TRUE, TRUE, 0);
g_signal_connect(cc_dlg->class_name_entry, "changed",
G_CALLBACK(cc_dlg_on_class_name_entry_changed), cc_dlg);
if (type != GEANY_CLASS_TYPE_PHP)
{
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
label = gtk_label_new(_("Header file:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
cc_dlg->header_entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->header_entry);
}
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
label = gtk_label_new(_("Header file:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
cc_dlg->header_entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->header_entry);
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
label = gtk_label_new(_("Source file:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
cc_dlg->source_entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->source_entry);
frame = ui_frame_new_with_alignment(_("Inheritance"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
@ -387,20 +445,26 @@ void show_dialog_create_class(gint type)
G_CALLBACK(cc_dlg_on_base_name_entry_changed), (gpointer)cc_dlg);
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
label = gtk_label_new(_("Base header:"));
gtk_container_add(GTK_CONTAINER(vbox), hbox);
if (type == GEANY_CLASS_TYPE_PHP)
label = gtk_label_new(_("Base source:"));
else
label = gtk_label_new(_("Base header:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
cc_dlg->base_header_entry = gtk_entry_new();
if (type == GEANY_CLASS_TYPE_GTK)
gtk_entry_set_text(GTK_ENTRY(cc_dlg->base_header_entry), "glib-object.h");
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->base_header_entry);
cc_dlg->base_header_global_box = gtk_check_button_new_with_label(_("Global"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box), TRUE);
gtk_box_pack_end(GTK_BOX(hbox), cc_dlg->base_header_global_box, FALSE, FALSE, 0);
if (type != GEANY_CLASS_TYPE_PHP)
{
cc_dlg->base_header_global_box = gtk_check_button_new_with_label(_("Global"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box), TRUE);
gtk_box_pack_end(GTK_BOX(hbox), cc_dlg->base_header_global_box, FALSE, FALSE, 0);
}
if (type == GEANY_CLASS_TYPE_GTK)
{
hbox = gtk_hbox_new(FALSE, 10);
@ -413,7 +477,19 @@ void show_dialog_create_class(gint type)
gtk_entry_set_text(GTK_ENTRY(cc_dlg->base_gtype_entry), "G_TYPE_OBJECT");
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->base_gtype_entry);
}
if (type == GEANY_CLASS_TYPE_PHP)
{
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
label = gtk_label_new(_("Implements:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
cc_dlg->class_implements_entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->class_implements_entry);
}
frame = ui_frame_new_with_alignment(_("Options"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
@ -429,7 +505,19 @@ void show_dialog_create_class(gint type)
cc_dlg->create_destructor_box = gtk_check_button_new_with_label(_("Create destructor"));
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->create_destructor_box);
if (type == GEANY_CLASS_TYPE_PHP)
{
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
cc_dlg->create_isabstract_box = gtk_check_button_new_with_label(_("Is abstract"));
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->create_isabstract_box);
cc_dlg->create_issingleton_box = gtk_check_button_new_with_label(_("Is singleton"));
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->create_issingleton_box);
}
if (type == GEANY_CLASS_TYPE_GTK)
{
hbox = gtk_hbox_new(FALSE, 10);
@ -472,6 +560,7 @@ static void cc_dlg_on_set_sensitive_toggled(GtkWidget *toggle_button, GtkWidget
static void cc_dlg_on_class_name_entry_changed(GtkWidget *entry, CreateClassDialog *cc_dlg)
{
gchar *class_name;
gchar *class_name_down;
gchar *class_header;
gchar *class_source;
@ -480,16 +569,20 @@ static void cc_dlg_on_class_name_entry_changed(GtkWidget *entry, CreateClassDial
g_return_if_fail(GTK_IS_ENTRY(entry));
g_return_if_fail(cc_dlg != NULL);
class_name_down = g_ascii_strdown(gtk_entry_get_text(GTK_ENTRY(entry)), -1);
class_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
class_name_down = g_ascii_strdown(class_name, -1);
class_header = g_strconcat(class_name_down, ".h", NULL);
if (cc_dlg->class_type == GEANY_CLASS_TYPE_CPP)
class_source = g_strconcat(class_name_down, ".cpp", NULL);
else if (cc_dlg->class_type == GEANY_CLASS_TYPE_PHP)
class_source = g_strconcat(class_name, ".php", NULL);
else
class_source = g_strconcat(class_name_down, ".c", NULL);
gtk_entry_set_text(GTK_ENTRY(cc_dlg->header_entry), class_header);
gtk_entry_set_text(GTK_ENTRY(cc_dlg->source_entry), class_source);
g_free(class_name);
g_free(class_name_down);
g_free(class_header);
g_free(class_source);
@ -525,7 +618,7 @@ static void cc_dlg_on_base_name_entry_changed(GtkWidget *entry, CreateClassDialo
g_return_if_fail(entry != NULL);
g_return_if_fail(GTK_IS_ENTRY(entry));
g_return_if_fail(cc_dlg != NULL);
base_name_splitted = str_case_split(gtk_entry_get_text(GTK_ENTRY(entry)), '_');
if (! g_ascii_strncasecmp(gtk_entry_get_text(GTK_ENTRY(entry)), "gtk", 3))
/*tmp = g_strconcat("gtk/", gtk_entry_get_text(GTK_ENTRY(entry)), ".h", NULL);*/
@ -533,9 +626,16 @@ static void cc_dlg_on_base_name_entry_changed(GtkWidget *entry, CreateClassDialo
tmp = g_strdup("gtk/gtk.h");
else if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(entry)), "GObject"))
tmp = g_strdup("glib-object.h");
else if (cc_dlg->class_type == GEANY_CLASS_TYPE_PHP)
tmp = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), ".php", NULL);
else
tmp = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), ".h", NULL);
base_header = g_ascii_strdown(tmp, -1);
if (cc_dlg->class_type == GEANY_CLASS_TYPE_PHP)
base_header = g_strdup(tmp);
else
base_header = g_ascii_strdown(tmp, -1);
g_free(tmp);
gtk_entry_set_text(GTK_ENTRY(cc_dlg->base_header_entry), base_header);
@ -584,12 +684,21 @@ static gboolean create_class(CreateClassDialog *cc_dlg)
if (! utils_str_equal(gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_name_entry)), ""))
{
class_info->base_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_name_entry)));
class_info->base_include = g_strdup_printf("\n#include %c%s%c\n",
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
if (class_info->type != GEANY_CLASS_TYPE_PHP)
{
class_info->base_include = g_strdup_printf("\n#include %c%s%c\n",
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
'<' : '\"',
gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_header_entry)),
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_header_entry)),
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
'>' : '\"');
}
else
{
class_info->base_include = g_strdup_printf("\nrequire_once \"%s\";\n",
gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_header_entry)));
class_info->base_decl = g_strdup_printf(" extends %s", class_info->base_name);
}
}
else
{
@ -697,8 +806,110 @@ static gboolean create_class(CreateClassDialog *cc_dlg)
}
break;
}
case GEANY_CLASS_TYPE_PHP:
{
gchar *tmp;
class_info->source = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->source_entry)));
tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->class_namespace_entry)));
if (! utils_str_equal(tmp, ""))
class_info->namespace_decl = g_strdup_printf("namespace %s;", tmp);
else
class_info->namespace_decl = g_strdup("");
tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->class_implements_entry)));
if (! utils_str_equal(tmp, ""))
class_info->implements_decl = g_strdup_printf(" implements %s", tmp);
else
class_info->implements_decl = g_strdup("");
g_free(tmp);
if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_constructor_box)) &&
! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_isabstract_box)))
{
class_info->constructor_impl = g_strdup_printf("\n"
"\t/**\n"
"\t * Constructor of class %s.\n"
"\t *\n"
"\t * @return void\n"
"\t */\n"
"\tpublic function __construct()\n"
"\t{\n"
"\t\t// ...\n"
"\t}\n",
class_info->class_name);
}
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_constructor_box)) &&
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_isabstract_box)))
{
class_info->constructor_impl = g_strdup_printf("\n"
"\t/**\n"
"\t * Constructor of class %s.\n"
"\t *\n"
"\t * @return void\n"
"\t */\n"
"\tprotected function __construct()\n"
"\t{\n"
"\t\t// ...\n"
"\t}\n",
class_info->class_name);
}
else
class_info->constructor_impl = g_strdup("");
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_destructor_box)))
{
class_info->destructor_impl = g_strdup_printf("\n"
"\t/**\n"
"\t * Destructor of class %s.\n"
"\t *\n"
"\t * @return void\n"
"\t */\n"
"\tpublic function __destruct()\n"
"\t{\n"
"\t\t// ...\n"
"\t}\n",
class_info->class_name);
}
else
class_info->destructor_impl = g_strdup("");
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_isabstract_box)))
class_info->abstract_decl = g_strdup("abstract ");
else
class_info->abstract_decl = g_strdup("");
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_issingleton_box)))
{
class_info->singleton_impl = g_strdup_printf("\n"
"\t/**\n"
"\t * Holds instance of self.\n"
"\t * \n"
"\t * @var %s\n"
"\t */\n"
"\tprotected static $kInstance = null;\n\n"
"\t/**\n"
"\t * Returns instance of self.\n"
"\t * \n"
"\t * @return %s\n"
"\t */\n"
"\tpublic static function getInstance() {\n"
"\t\tif(!(self::$kInstance instanceof %s)) {\n"
"\t\t\tself::$kInstance = new self();\n"
"\t\t}\n"
"\t\treturn self::$kInstance;\n"
"\t}\n",
class_info->class_name,
class_info->class_name,
class_info->class_name);
}
else
class_info->singleton_impl = g_strdup("");
break;
}
}
/* only create the files if the filename is not empty */
if (! utils_str_equal(class_info->source, ""))
{
@ -708,7 +919,8 @@ static gboolean create_class(CreateClassDialog *cc_dlg)
g_free(text);
}
if (! utils_str_equal(class_info->header, ""))
if (! utils_str_equal(class_info->header, "") &&
class_info->type != GEANY_CLASS_TYPE_PHP)
{
text = get_template_class_header(class_info);
doc = document_new_file(class_info->header, NULL, NULL);
@ -721,7 +933,9 @@ static gboolean create_class(CreateClassDialog *cc_dlg)
class_info->header, class_info->header_guard, class_info->source, class_info->base_decl,
class_info->constructor_decl, class_info->constructor_impl,
class_info->gtk_destructor_registration, class_info->destructor_decl,
class_info->destructor_impl, class_info->base_gtype, class_info, NULL);
class_info->destructor_impl, class_info->base_gtype,
class_info->namespace_decl, class_info->implements_decl,
class_info->abstract_decl, class_info->singleton_impl, class_info, NULL);
return TRUE;
}
@ -742,12 +956,21 @@ on_menu_create_gtk_class_activate (GtkMenuItem *menuitem,
}
static void
on_menu_create_php_class_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
show_dialog_create_class(GEANY_CLASS_TYPE_PHP);
}
void plugin_init(GeanyData *data)
{
GtkWidget *menu_create_class1;
GtkWidget *menu_create_class1_menu;
GtkWidget *menu_create_cpp_class;
GtkWidget *menu_create_gtk_class;
GtkWidget *menu_create_php_class;
menu_create_class1 = ui_image_menu_item_new (GTK_STOCK_ADD, _("Create Cla_ss"));
gtk_container_add (GTK_CONTAINER (geany->main_widgets->tools_menu), menu_create_class1);
@ -760,6 +983,9 @@ void plugin_init(GeanyData *data)
menu_create_gtk_class = gtk_menu_item_new_with_mnemonic (_("_GTK+ Class"));
gtk_container_add (GTK_CONTAINER (menu_create_class1_menu), menu_create_gtk_class);
menu_create_php_class = gtk_menu_item_new_with_mnemonic (_("_PHP Class"));
gtk_container_add (GTK_CONTAINER (menu_create_class1_menu), menu_create_php_class);
g_signal_connect(menu_create_cpp_class, "activate",
G_CALLBACK (on_menu_create_cpp_class_activate),
@ -767,6 +993,9 @@ void plugin_init(GeanyData *data)
g_signal_connect(menu_create_gtk_class, "activate",
G_CALLBACK (on_menu_create_gtk_class_activate),
NULL);
g_signal_connect(menu_create_php_class, "activate",
G_CALLBACK (on_menu_create_php_class_activate),
NULL);
gtk_widget_show_all(menu_create_class1);

View File

@ -89,8 +89,8 @@ static const gchar *contributors =
"Giuseppe Torelli, Guillaume de Rorthais, Guillaume Hoffmann, Herbert Voss, Jason Oster, "
"Jean-François Wauthy, Jeff Pohlmeyer, Jesse Mayes, John Gabriele, Jon Senior, Jon Strait, Josef Whiter, "
"Jörn Reder, Kelvin Gardiner, Kevin Ellwood, Kristoffer A. Tjernås, Lex Trotman, Marko Peric, Matti Mårds, "
"Moritz Barsnick, Peter Strand, Philipp Gildein, Pierre Joye, Rob van der Linde, Robert McGinley, "
"Roland Baudin, Ross McKay, S Jagannathan, Saleem Abdulrasool, "
"Moritz Barsnick, Ondrej Donek, Peter Strand, Philipp Gildein, Pierre Joye, Rob van der Linde, "
"Robert McGinley, Roland Baudin, Ross McKay, S Jagannathan, Saleem Abdulrasool, "
"Sebastian Kraft, Shiv, Slava Semushin, Stefan Oltmanns, Tamim, Thomas Martitz, Tomás Vírseda, "
"Tyler Mulligan, Walery Studennikov, Yura Siamashka";