Add a plugin howto to the plugin API docs, written by Frank.
git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@3581 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
parent
08fd390c5d
commit
b422347922
@ -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:
|
||||
|
250
doc/plugins.dox
250
doc/plugins.dox
@ -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 @@ PluginCallback plugin_callbacks[] =
|
||||
* plugins by writing a simple "Hello World" plugin in C.
|
||||
*
|
||||
*
|
||||
* @section start Getting started
|
||||
*
|
||||
* @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
|
||||
* @section 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
|
||||
*
|
||||
**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user