Add plugin_signal_connect() for connecting plugin signals at
runtime and also for connecting to any GObject signal. Add 'Plugin Utility Functions' on main page. Add foreach_array() macro. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@4041 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
parent
264ac9186c
commit
69922305e0
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
2009-07-29 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
|
||||
|
||||
* src/pluginprivate.h, src/utils.h, src/plugindata.h,
|
||||
src/stash.c, src/pluginutils.c, src/plugins.c, src/pluginutils.h,
|
||||
doc/pluginsymbols.c, doc/plugins.dox, plugins/geanyfunctions.h,
|
||||
plugins/filebrowser.c:
|
||||
Add plugin_signal_connect() for connecting plugin signals at
|
||||
runtime and also for connecting to any GObject signal.
|
||||
Add 'Plugin Utility Functions' on main page.
|
||||
Add foreach_array() macro.
|
||||
|
||||
|
||||
2009-07-28 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
|
||||
|
||||
* wscript: Fix compiling error with waf.
|
||||
|
@ -42,9 +42,10 @@
|
||||
* To get started, see the @link howto Plugin Howto @endlink.
|
||||
*
|
||||
* Other pages:
|
||||
* - @link plugindata.h Main Datatypes and Macros @endlink
|
||||
* - @link pluginsymbols.c Plugin Symbols @endlink
|
||||
* - @link plugindata.h Main Datatypes and Macros @endlink
|
||||
* - @link signals Plugin Signals @endlink
|
||||
* - @link pluginutils.c Plugin Utility Functions @endlink
|
||||
* - @link guidelines Plugin Writing Guidelines @endlink
|
||||
*
|
||||
* @note Some of these pages are also listed in Related Pages.
|
||||
@ -56,10 +57,13 @@
|
||||
*
|
||||
* @section Usage
|
||||
*
|
||||
* To use plugin signals in Geany, you simply create a PluginCallback array, list the signals
|
||||
* you want to listen to and create the appropiate signal callbacks for each signal.
|
||||
* The callback array is read @a after plugin_init() has been called.
|
||||
* @note The PluginCallback array has to be ended with a final NULL entry.
|
||||
* To use plugin signals in Geany, you have two options:
|
||||
*
|
||||
* -# Create a PluginCallback array with the @ref plugin_callbacks symbol. List the signals
|
||||
* you want to listen to and create the appropiate signal callbacks for each signal.
|
||||
* The callback array is read @a after plugin_init() has been called.
|
||||
* -# Use plugin_signal_connect(), which can be called at any time and can also connect
|
||||
* to non-Geany signals (such as GTK widget signals).
|
||||
*
|
||||
* The following code demonstrates how to use signals in Geany plugins. The code can be inserted
|
||||
* in your plugin code at any desired position.
|
||||
@ -76,6 +80,7 @@ PluginCallback plugin_callbacks[] =
|
||||
{ NULL, NULL, FALSE, NULL }
|
||||
};
|
||||
* @endcode
|
||||
* @note The PluginCallback array has to be ended with a final @c NULL entry.
|
||||
*
|
||||
* @section Signals
|
||||
*
|
||||
|
@ -66,7 +66,8 @@ const GeanyFunctions *geany_functions;
|
||||
PluginFields *plugin_fields;
|
||||
|
||||
/** An array for connecting GeanyObject events, which should be terminated with
|
||||
* @c {NULL, NULL, FALSE, NULL}. See @link signals Signal documentation @endlink. */
|
||||
* @c {NULL, NULL, FALSE, NULL}. See @link signals Signal documentation @endlink.
|
||||
* @see plugin_signal_connect(). */
|
||||
PluginCallback plugin_callbacks[];
|
||||
|
||||
/** Most plugins should use the PLUGIN_KEY_GROUP() macro to define it. However,
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
|
||||
GeanyPlugin *geany_plugin;
|
||||
GeanyData *geany_data;
|
||||
GeanyFunctions *geany_functions;
|
||||
|
||||
@ -87,12 +88,10 @@ static struct
|
||||
} popup_items;
|
||||
|
||||
|
||||
static void document_activate_cb(GObject *obj, GeanyDocument *doc, gpointer data);
|
||||
static void project_change_cb(GObject *obj, GKeyFile *config, gpointer data);
|
||||
|
||||
PluginCallback plugin_callbacks[] =
|
||||
{
|
||||
{ "document-activate", (GCallback) &document_activate_cb, TRUE, NULL },
|
||||
{ "project-open", (GCallback) &project_change_cb, TRUE, NULL },
|
||||
{ "project-save", (GCallback) &project_change_cb, TRUE, NULL },
|
||||
{ NULL, NULL, FALSE, NULL }
|
||||
@ -1020,6 +1019,9 @@ void plugin_init(GeanyData *data)
|
||||
0, 0, "focus_file_list", _("Focus File List"), NULL);
|
||||
keybindings_set_item(plugin_key_group, KB_FOCUS_PATH_ENTRY, kb_activate,
|
||||
0, 0, "focus_path_entry", _("Focus Path Entry"), NULL);
|
||||
|
||||
plugin_signal_connect(geany_plugin, NULL, "document-activate", TRUE,
|
||||
(GCallback) &document_activate_cb, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
geany_functions->p_plugin->add_toolbar_item
|
||||
#define plugin_module_make_resident \
|
||||
geany_functions->p_plugin->module_make_resident
|
||||
#define plugin_signal_connect \
|
||||
geany_functions->p_plugin->signal_connect
|
||||
#define document_new_file \
|
||||
geany_functions->p_document->new_file
|
||||
#define document_get_current \
|
||||
|
@ -50,7 +50,7 @@
|
||||
enum {
|
||||
/** The Application Programming Interface (API) version, incremented
|
||||
* whenever any plugin data types are modified or appended to. */
|
||||
GEANY_API_VERSION = 149,
|
||||
GEANY_API_VERSION = 150,
|
||||
|
||||
/** The Application Binary Interface (ABI) version, incremented whenever
|
||||
* existing fields in the plugin data types have to be changed or reordered. */
|
||||
@ -138,7 +138,7 @@ GeanyPlugin;
|
||||
};
|
||||
|
||||
|
||||
/** callback array entry */
|
||||
/** Callback array entry type used with the @ref plugin_callbacks symbol. */
|
||||
typedef struct PluginCallback
|
||||
{
|
||||
/** The name of signal, must be an existing signal. For a list of available signals,
|
||||
@ -546,6 +546,9 @@ typedef struct PluginFuncs
|
||||
{
|
||||
void (*add_toolbar_item)(GeanyPlugin *plugin, GtkToolItem *item);
|
||||
void (*module_make_resident) (GeanyPlugin *plugin);
|
||||
void (*signal_connect) (GeanyPlugin *plugin,
|
||||
GObject *object, gchar *signal_name, gboolean after,
|
||||
GCallback callback, gpointer user_data);
|
||||
}
|
||||
PluginFuncs;
|
||||
|
||||
|
@ -32,6 +32,7 @@ typedef struct GeanyPluginPrivate
|
||||
{
|
||||
GeanyAutoSeparator toolbar_separator;
|
||||
gboolean resident;
|
||||
GArray *signal_ids; /* gulong signal IDs to disconnect when unloading */
|
||||
}
|
||||
GeanyPluginPrivate;
|
||||
|
||||
|
@ -72,8 +72,6 @@ typedef struct Plugin
|
||||
GeanyPlugin public; /* fields the plugin can read */
|
||||
GeanyPluginPrivate priv; /* GeanyPlugin type private data, same as (*public.priv) */
|
||||
|
||||
gulong *signal_ids; /* signal IDs to disconnect when unloading */
|
||||
gsize signal_ids_len;
|
||||
GeanyKeyGroup *key_group;
|
||||
|
||||
void (*init) (GeanyData *data); /* Called when the plugin is enabled */
|
||||
@ -100,7 +98,8 @@ static void pm_show_dialog(GtkMenuItem *menuitem, gpointer user_data);
|
||||
|
||||
static PluginFuncs plugin_funcs = {
|
||||
&plugin_add_toolbar_item,
|
||||
&plugin_module_make_resident
|
||||
&plugin_module_make_resident,
|
||||
&plugin_signal_connect
|
||||
};
|
||||
|
||||
static DocumentFuncs doc_funcs = {
|
||||
@ -455,16 +454,12 @@ static void add_callbacks(Plugin *plugin, PluginCallback *callbacks)
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
plugin->signal_ids_len = len;
|
||||
plugin->signal_ids = g_new(gulong, len);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
cb = &callbacks[i];
|
||||
|
||||
plugin->signal_ids[i] = (cb->after) ?
|
||||
g_signal_connect_after(geany_object, cb->signal_name, cb->callback, cb->user_data) :
|
||||
g_signal_connect(geany_object, cb->signal_name, cb->callback, cb->user_data);
|
||||
plugin_signal_connect(&plugin->public, NULL, cb->signal_name, cb->after,
|
||||
cb->callback, cb->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,14 +681,16 @@ plugin_new(const gchar *fname, gboolean init_plugin, gboolean add_to_list)
|
||||
|
||||
static void remove_callbacks(Plugin *plugin)
|
||||
{
|
||||
guint i;
|
||||
GArray *signal_ids = plugin->priv.signal_ids;
|
||||
gulong *i;
|
||||
|
||||
if (plugin->signal_ids == NULL)
|
||||
if (signal_ids == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < plugin->signal_ids_len; i++)
|
||||
g_signal_handler_disconnect(geany_object, plugin->signal_ids[i]);
|
||||
g_free(plugin->signal_ids);
|
||||
foreach_array(gulong, i, signal_ids)
|
||||
g_signal_handler_disconnect(geany_object, *i);
|
||||
|
||||
g_array_free(signal_ids, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,3 +92,33 @@ void plugin_module_make_resident(GeanyPlugin *plugin)
|
||||
}
|
||||
|
||||
|
||||
/** Connect a signal which will be disconnected on unloading the plugin, to prevent a possible segfault.
|
||||
* @param plugin Must be @ref geany_plugin.
|
||||
* @param object Object to connect to, or @c NULL when using @link signals Geany signals @endlink.
|
||||
* @param signal_name The name of the signal. For a list of available
|
||||
* signals, please see the @link signals Signal documentation @endlink.
|
||||
* @param after Set to @c TRUE to call your handler after the main signal handlers have been called
|
||||
* (if supported by @a signal_name).
|
||||
* @param callback The function to call when the signal is emitted.
|
||||
* @param user_data The user data passed to the signal handler.
|
||||
* @see plugin_callbacks. */
|
||||
void plugin_signal_connect(GeanyPlugin *plugin,
|
||||
GObject *object, gchar *signal_name, gboolean after,
|
||||
GCallback callback, gpointer user_data)
|
||||
{
|
||||
gulong id;
|
||||
|
||||
if (!object)
|
||||
object = geany_object;
|
||||
|
||||
id = after ?
|
||||
g_signal_connect_after(object, signal_name, callback, user_data) :
|
||||
g_signal_connect(object, signal_name, callback, user_data);
|
||||
|
||||
if (!plugin->priv->signal_ids)
|
||||
plugin->priv->signal_ids = g_array_new(FALSE, FALSE, sizeof(gulong));
|
||||
|
||||
g_array_append_val(plugin->priv->signal_ids, id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,4 +32,8 @@ void plugin_add_toolbar_item(GeanyPlugin *plugin, GtkToolItem *item);
|
||||
|
||||
void plugin_module_make_resident(GeanyPlugin *plugin);
|
||||
|
||||
void plugin_signal_connect(GeanyPlugin *plugin,
|
||||
GObject *object, gchar *signal_name, gboolean after,
|
||||
GCallback callback, gpointer user_data);
|
||||
|
||||
#endif /* PLUGINUTILS_H */
|
||||
|
@ -62,10 +62,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "stash.h"
|
||||
#include "utils.h" /* only for utils_get_setting_*(). Stash should not depend on Geany. */
|
||||
|
||||
#define foreach_array(type, item, array) \
|
||||
foreach_c_array(item, ((type*)(gpointer)array->data), array->len)
|
||||
#include "utils.h" /* only for foreach_*, utils_get_setting_*(). Stash should not depend on Geany. */
|
||||
|
||||
|
||||
struct GeanyPrefEntry
|
||||
|
@ -64,6 +64,13 @@
|
||||
#define foreach_c_array(item, array, len) \
|
||||
for (item = array; item < &array[len]; item++)
|
||||
|
||||
/** Iterates all items in @a array.
|
||||
* @param type Type of @a item.
|
||||
* @param item pointer to item in @a array.
|
||||
* @param array @c GArray to traverse. */
|
||||
#define foreach_array(type, item, array) \
|
||||
foreach_c_array(item, ((type*)(gpointer)array->data), array->len)
|
||||
|
||||
/** Iterates all the pointers in @a ptr_array.
|
||||
* @param item pointer in @a ptr_array.
|
||||
* @param idx @c guint index into @a ptr_array.
|
||||
|
Loading…
x
Reference in New Issue
Block a user