changeset 19025:c3e80350c270

- Added a lovely Doxygen signals tutorial
author William Ehlhardt <williamehlhardt@gmail.com>
date Sun, 15 Jul 2007 06:28:08 +0000
parents 264f00bc8f22
children b3acaf46d9ad
files doc/Makefile.am doc/SIGNAL-HOWTO.dox
diffstat 2 files changed, 138 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/doc/Makefile.am	Sat Jul 14 04:49:30 2007 +0000
+++ b/doc/Makefile.am	Sun Jul 15 06:28:08 2007 +0000
@@ -3,6 +3,7 @@
 EXTRA_DIST = \
 	C-HOWTO.dox \
 	PERL-HOWTO.dox \
+	SIGNAL-HOWTO.dox \
 	TCL-HOWTO.dox \
 	TracFooter.html \
 	TracHeader.html \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/SIGNAL-HOWTO.dox	Sun Jul 15 06:28:08 2007 +0000
@@ -0,0 +1,137 @@
+/** @page signal-howto Signals HOWTO
+
+ @section Introduction
+  The libpurple signals interface is used for general event notification, such
+  as plugins being loaded or unloaded, allowing the GUI frontend to respond
+  appropriately to changing internal data. Unfortunately, its use is not at all
+  obvious from the information in the header files. This document uses code
+  snippets from the Pidgin/libpurple plugin systems to illustrate the proper
+  use of signals.
+
+ @section overview Overview of Signals
+  Signals in libpurple are very similar to those in GTK+. When certain events
+  happen, a named signal is "emitted" from a certain object. Emitting the
+  signal triggers a series of callbacks that have been "connected" to that
+  signal for that object. These callbacks take appropriate action in response
+  to the signal.
+
+ @section registering_signal Registering a Signal
+  The first step of using a signal is registering it with libpurple so that
+  callbacks may be connected to it. This is done using purple_signal_register()
+  Here is a slightly modified example from @c purple_plugins_init in 
+  @c libpurple/plugin.c :
+
+  @code
+	purple_signal_register( purple_plugins_get_handle(), /* Instance */
+				"plugin-load",               /* Signal name */
+				purple_marshal_VOID__POINTER,/* Marshal function */
+				NULL,                        /* Callback return value type */
+				1,                           /* Number of callback arguments (not including void *data) */
+				purple_value_new(PURPLE_TYPE_SUBTYPE,PURPLE_SUBTYPE_PLUGIN) /* Type of first callback argument */
+				);
+  @endcode
+
+  @subsection Instance
+  A reference to the object from which this signal is emitted, and to which
+  potential callbacks should be connected. In this case, it will be the entire
+  plugin module emitting the signal.
+  
+  @subsection signalname Signal Name
+  Unique identifier for the signal itself.
+
+  @subsection therest Callback function definition
+  The rest of the arguments specify the form of the callback function.
+
+  @subsubsection marshalfunc Marshal Function
+  @c purple_marshal_VOID__POINTER represents the callback function prototype,
+  not including a "data" argument, explained later. The form is 
+  @c purple_marshal_RETURNVALUETYPE__ARG1TYPE_ARG2TYPE_ETC. See signals.h for
+  more possible types.
+
+  In this case, the callback will have the form
+  @code
+	void cb(void *arg1, void *data)
+  @endcode
+
+  If @c purple_marshal_BOOLEAN__POINTER_POINTER_POINTER were specified, it
+  would be:
+  @code
+	gboolean cb(void *arg1, void *arg2, void *arg3, void *data)
+  @endcode
+
+  The @c void @c *data argument at the end of each callback function
+  provides the data argument given to purple_signal_connect() .
+
+  @subsubsection cb_ret_type Callback return value type
+  In our case, this is NULL, meaning "returns void".
+  @todo This could be described better.
+
+  @subsubsection num_args Number of arguments
+  The number of arguments (not including @c data ) that the callback function
+  will take.
+
+  @subsubsection type_arg Type of argument
+  @c purple_value_new(PURPLE_TYPE_SUBTYPE,PURPLE_SUBTYPE_PLUGIN) specifies that
+  the first argument given to the callback will be a @c PurplePlugin* . You
+  will need as many "type of argument" arguments to purple_signal_register() as
+  you specified in "Number of arguments" above.
+
+  @todo Describe this more.
+
+  @See value.h
+
+  @section connect Connecting to the signal
+  Once the signal is registered, you can connect callbacks to it. First, you
+  must define a callback function, such as this one from gtkplugin.c :
+  @code
+static void plugin_load_cb(PurplePlugin *plugin, gpointer data)
+{
+	GtkTreeView *view = (GtkTreeView *)data;
+	plugin_loading_common(plugin, view, TRUE);
+}
+  @endcode
+  Note that the callback function prototype matches that specified in the call
+  to purple_signal_register() above.
+
+  Once the callback function is defined, you can connect it to the signal.
+  Again from gtkplugin.c , in @c pidgin_plugin_dialog_show() :
+  @code
+	purple_signal_connect(purple_plugins_get_handle(), "plugin-load", /* What to connect to */
+		plugin_dialog, /* Object receiving the signal */
+		PURPLE_CALLBACK(plugin_load_cb), /* Callback function */
+		event_view, /* Data to pass to the callback function
+		);
+  @endcode
+
+  The first two arguments ("What to connect to") specify the object emitting
+  the signal (the plugin module) and what signal to listen for ("plugin-load").
+
+  The object receiving the signal is @c plugin_dialog , the Pidgin plugins
+  dialog. When @c plugin_dialog is deleted, then 
+  @c purple_signals_disconnect_by_handle(plugin_dialog) should be called to
+  remove all signal connections it is associated with.
+
+  The callback function is given using a helper macro, and finally the
+  @c data argument to be passed to @c plugin_load_cb is given as @c event_view,
+  a pointer to the GTK widget that @c plugin_load_cb needs to update.
+
+  @section emit-signal Emitting a signal
+  Connecting callbacks to signals is all well and good, but how do you "fire"
+  the signal and trigger the callback? At some point, you must "emit" the
+  signal, which immediately calls all connected callbacks.
+
+  As seen in @c purple_plugin_load() in plugin.c :
+  @code
+	purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
+  @endcode
+  This causes the signal "plugin-load" to be emitted from the plugin module
+  (given by @c purple_plugins_get_handle() ), with the newly loaded plugin as
+  the argument to pass to any registered callback functions.
+
+  In our example, @c plugin_load_cb is called immediately as
+  @code
+	plugin_load_cb(plugin, event_view);
+  @endcode
+  and does whatever it does.
+  
+ */