Revision: 3581 http://geany.svn.sourceforge.net/geany/?rev=3581&view=rev Author: eht16 Date: 2009-02-14 17:37:28 +0000 (Sat, 14 Feb 2009)
Log Message: ----------- Add a plugin howto to the plugin API docs, written by Frank.
Modified Paths: -------------- trunk/ChangeLog trunk/doc/plugins.dox
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-02-14 11:53:42 UTC (rev 3580) +++ trunk/ChangeLog 2009-02-14 17:37:28 UTC (rev 3581) @@ -1,3 +1,9 @@ +2009-02-14 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + + * doc/plugins.dox: + Add a plugin howto to the plugin API docs, written by Frank. + + 2009-02-13 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/msgwindow.c:
Modified: trunk/doc/plugins.dox =================================================================== --- trunk/doc/plugins.dox 2009-02-14 11:53:42 UTC (rev 3580) +++ trunk/doc/plugins.dox 2009-02-14 17:37:28 UTC (rev 3581) @@ -3,6 +3,7 @@ * * Copyright 2008-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> * Copyright 2008-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com> + * Copyright 2009 Frank Lanitz <frank(at)frank(dot)uvena(dot)de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +31,7 @@ * * @mainpage Geany Plugin API Documentation * - * @author Enrico Tröger, Nick Treleaven + * @author Enrico Tröger, Nick Treleaven, Frank Lanitz * @date $Date$ * * @section Intro @@ -331,70 +332,229 @@ * plugins by writing a simple "Hello World" plugin in C. * * - * @section start Getting started + * @section buildenv Build environment * - * @subsection structure Plugin structure - * - * Every plugin must contain some essential symbols unless it won't work. A complete - * list of all necessary and optional symbols can be found in - * @link pluginsymbols.c Plugin Symbols @endlink. - * Every plugin should include "geany.h" and "plugindata.h" which provide necessary - * preprocessor macros and other basic information. - * There are two important preprocessor macros which need to be used at the beginning: - * PLUGIN_SET_INFO() and PLUGIN_VERSION_CHECK(). - * - * PLUGIN_SET_INFO() tells Geany about basic plugin information like name, description, - * version and author of the plugin. - * - * PLUGIN_VERSION_CHECK() checks for compatibility of the API version which - * the plugin uses with the used Geany sources. Furthermore, it also checks - * the binary compatiblity of the plugin with Geany. - * - * A few functions are necessary to let Geany work with the plugin, at least plugin_init() must - * exist in the plugin. plugin_cleanup() should also be used to free allocated memory or destroy - * created widgets. - * - * @subsection buildenv Build environment - * * To be able to write plugins for Geany, you need the source code and some development - * packages for GTK and its dependencies. I will only describe the way to compile and + * packages for GTK and its dependencies. The following will only describe the way to compile and * build plugins on Unix-like systems [1]. * If you already have the Geany source code and compiled it from them, you can skip the * following. * - * First you need to get the source code of Geany from the website at - * http://www.geany.org/Download/Releases [2]. Then install the development files for GTK + * First you need to have Geany installed. Then install the development files for GTK * and its dependencies. The easiest way to do this is to use your distribution's package * management system, e.g. on Debian and Ubuntu systems you can use * @code apt-get install libgtk2.0-dev intltool @endcode - * This will install all necessary files to be able to compile Geany and plugins. On other + * This will install all necessary files to be able to compile plugins for Geany. On other * distributions, the package names and commands to use may differ. * - * Basically, we are done at this point and could continue with writing the plugin code. - * You don't need necessarily to configure and build the Geany sources when the sources - * have the same version as your running Geany installation. But if the version of the - * sources differ from your Geany installation or especially when you used the source code - * from the Subversion repository, we strongly recommend to configure and build these - * sources and use it. To do so, run @code - ./configure && make - su -c "make install" - * @endcode - * in your Geany source directory. This will build and install Geany on your system. + * Basically, you are done at this point and could continue with writing the plugin code. * * [1] For Windows, it is basically the same but you might have some more work on setting up * the general build environment(compiler, GTK development files, ...). This is described on * Geany's website at http://www.geany.org/Support/BuildingOnWin32. * - * [2] You can also use the bleedging edge source code from our Subversion repository. - * More information about this can be found at http://www.geany.org/Download/SVN. + * @section helloworld "Hello World" * - * @section helloworld "Hello World" + * When writing a plugin, you will find a couple of functions or macros which are mandatory + * and some which are free to use for implementing some useful feature once your plugin + * becomes more powerful like including a configuration or help dialog. * - * We want to write a really simple "Hello World" plugin which opens a message dialog - * and just prints "Hello World". + * You should start your plugin with including some of the needed C header files and defining + * some basic global variables which will help you to access all needed functions of the plugin + * API in a more comfortable way. * + * Let's start with the very basic headers and add more later if necessary. + * @code +#include "geany.h" +#include "plugindata.h" +#include "geanyfunctions.h" + * @endcode * - * ... to be continued ... + * @a geany.h will include the necessary GTK header files, so there is no need to include + * @a gtk/gtk.h yourself. * + * @a plugindata.h contains the biggest part of the plugin API and provides some basic macros. * + * @a geanyfunctions.h provide some macros for convenient access to the plugin API. + * + * Later, you will note that by adding more functionality more header file includes will be + * necessary. Best practice for including header files is to always include @a geany.h at first, + * then include other necessary header files and at last include plugindata.h and @a + * geanyfunctions.h. + * + * The you should define three basic variables which will give access to data fields and + * functions provided by the plugin API. + * @code +GeanyPlugin *geany_plugin; +GeanyData *geany_data; +GeanyFunctions *geany_functions; + * @endcode + * + * Now you can go on and write your first lines for your new plugin. As mentioned before, + * you will need to implement and fill out a couple of functions/macros to make the plugin work. + * So let's start with PLUGIN_VERSION_CHECK(). + * + * PLUGIN_VERSION_CHECK() is a convenient way to tell Geany which version of Geany's plugin API + * is needed at minimum to run your plugin. The value is defined in + * @a plugindata.h by @a GEANY_API_VERSION. In most cases this should be your minimum. + * Nevertheless when setting this value, you should choose the lowest possible version here to + * make the plugin compatible with a bigger number of versions of Geany. + * + * As the next step, you will need to tell Geany a couple of basic information of your plugin, + * so it is able to show them e.g. on the plugin manager dialog. + * + * For doing this, you should use PLUGIN_SET_INFO() which expects 4 values: + * - Plugin name that should appear on the plugin manager dialog + * - Short plugin description + * - Plugin version + * - Author. + * + * Based on this, the line could look like: + * @code +PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world", + "1.0", "John Doe john.doe@example.org"); + * @endcode + * + * Once this is done, you will need to implement the function which will be executed when the + * plugin is loaded. Part of that function could be adding and removing of an item to + * Geany's Tools menu, setting up keybindings or registering some callbacks. Also you will + * need to implement the function that is called when your plugin is unloaded. + * These functions are called plugin_init() and plugin_cleanup(). Let's see how it could look like: + * @code +PLUGIN_VERSION_CHECK(130) + +PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world", + "1.0", "Joe Doe joe.doe@example.org"); + +void plugin_init(GeanyData *data) +{ +} + +void plugin_cleanup(void) +{ +} + * @endcode + * + * If you think this plugin seems to doesn't implement any function right now and only waste + * some memory, you are right. At least, it should compile and load/unload on in Geany nicely. + * Now you have the very basic layout of a new plugin. Great, isn't it? + * + * Let's go on and implement some real functionality. + * + * As mentioned before, plugin_init() will be called when the plugin is loaded in Geany. + * So it should implement everything that needs to be done during startup. In this example case, + * we like to add a menu item to Geany's Tools menu which runs a dialog printing "Hello World". + * @code +void plugin_init(GeanyData *data) +{ + GtkWidget *main_menu_item; + + // Create a new menu item and show it + main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World"); + gtk_widget_show(main_menu_item); + + // Attach the new menu item to the Tools menu + gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), + main_menu_item); + + // Connect the menu item with a callback function + // which is called when the item is clicked + g_signal_connect(main_menu_item, "activate", + G_CALLBACK(item_activate_cb), NULL); +} + * @endcode + * + * This will add an item to the Tools menu and connect this item to a function which implements + * what should be done when the menu item is activated by the user. + * This is done by g_signal_connect(). The Tools menu can be accessed with + * geany->main_widgets->tools_menu. The structure @a main_widgets contains pointers to some + * main GUI elements in Geany. To be able to use it, you must include ui_utils.h. This can + * be done by adding the following line to the include section of your code. + * @code +#include "ui_utils.h" + * @endcode + * + * Geany is offering a simple API for showing message dialogs. So the function contains + * only a few lines like: + * @code +void item_activate_cb(GtkMenuItem *menuitem, gpointer user_data) +{ + dialogs_show_msgbox(GTK_MESSAGE_INFO, "Hello World"); +} + * @endcode + * + * For the moment you don't need to worry about the parameters of that function. + * + * Do you remember, you need to clean up when unloading the plugin? Because of this, + * some more action is required. + * + * To remove the menu item from the Tools menu, you can use gtk_widget_destroy(). + * gtk_widget_destroy() expects a pointer to a GtkWidget object. + * + * First you should add gtk_widget_destroy() to your plugin_cleanup() function. + * The argument for gtk_widget_destroy() is the widget object you created earlier in + * plugin_init(). To be able to access this pointer in plugin_cleanup(), you need to move + * its definition from plugin_init() into the global context so its visibility will increase + * and it can be accessed in all functions. + * @code +static GtkWidget *main_menu_item = NULL; + +// ... +void plugin_init(GeanyData *data) +{ + main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World"); + gtk_widget_show(main_menu_item); +// ... +} + +void plugin_cleanup(void) +{ + gtk_widget_destroy(main_menu_item); +} + * @endcode + * + * This will ensure, your menu item will be removed from the Tools menu as well as from + * memory once your plugin is unloaded and you don't leave any memory leaks back. + * Once this is done, your first plugin is ready. Congratulations! + * + * The complete listing (without comments): + * @code +#include "geany.h" +#include "ui_utils.h" +#include "plugindata.h" +#include "geanyfunctions.h" + +GeanyPlugin *geany_plugin; +GeanyData *geany_data; +GeanyFunctions *geany_functions; + +PLUGIN_VERSION_CHECK(130) + +PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world", + "1.0", "John Doe john.doe@example.org"); + + +static GtkWidget *main_menu_item = NULL; + +static void item_activate_cb(GtkMenuItem *menuitem, gpointer gdata) +{ + dialogs_show_msgbox(GTK_MESSAGE_INFO, "Hello World"); +} + +void plugin_init(GeanyData *data) +{ + main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World"); + gtk_widget_show(main_menu_item); + gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), + main_menu_item); + g_signal_connect(main_menu_item, "activate", + G_CALLBACK(item_activate_cb), NULL); +} + +void plugin_cleanup(void) +{ + gtk_widget_destroy(main_menu_item); +} + * @endcode + * **/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.