comparison doc/SIGNAL-HOWTO.dox @ 19025:c3e80350c270

- Added a lovely Doxygen signals tutorial
author William Ehlhardt <williamehlhardt@gmail.com>
date Sun, 15 Jul 2007 06:28:08 +0000
parents
children f3e0b1221765
comparison
equal deleted inserted replaced
19024:264f00bc8f22 19025:c3e80350c270
1 /** @page signal-howto Signals HOWTO
2
3 @section Introduction
4 The libpurple signals interface is used for general event notification, such
5 as plugins being loaded or unloaded, allowing the GUI frontend to respond
6 appropriately to changing internal data. Unfortunately, its use is not at all
7 obvious from the information in the header files. This document uses code
8 snippets from the Pidgin/libpurple plugin systems to illustrate the proper
9 use of signals.
10
11 @section overview Overview of Signals
12 Signals in libpurple are very similar to those in GTK+. When certain events
13 happen, a named signal is "emitted" from a certain object. Emitting the
14 signal triggers a series of callbacks that have been "connected" to that
15 signal for that object. These callbacks take appropriate action in response
16 to the signal.
17
18 @section registering_signal Registering a Signal
19 The first step of using a signal is registering it with libpurple so that
20 callbacks may be connected to it. This is done using purple_signal_register()
21 Here is a slightly modified example from @c purple_plugins_init in
22 @c libpurple/plugin.c :
23
24 @code
25 purple_signal_register( purple_plugins_get_handle(), /* Instance */
26 "plugin-load", /* Signal name */
27 purple_marshal_VOID__POINTER,/* Marshal function */
28 NULL, /* Callback return value type */
29 1, /* Number of callback arguments (not including void *data) */
30 purple_value_new(PURPLE_TYPE_SUBTYPE,PURPLE_SUBTYPE_PLUGIN) /* Type of first callback argument */
31 );
32 @endcode
33
34 @subsection Instance
35 A reference to the object from which this signal is emitted, and to which
36 potential callbacks should be connected. In this case, it will be the entire
37 plugin module emitting the signal.
38
39 @subsection signalname Signal Name
40 Unique identifier for the signal itself.
41
42 @subsection therest Callback function definition
43 The rest of the arguments specify the form of the callback function.
44
45 @subsubsection marshalfunc Marshal Function
46 @c purple_marshal_VOID__POINTER represents the callback function prototype,
47 not including a "data" argument, explained later. The form is
48 @c purple_marshal_RETURNVALUETYPE__ARG1TYPE_ARG2TYPE_ETC. See signals.h for
49 more possible types.
50
51 In this case, the callback will have the form
52 @code
53 void cb(void *arg1, void *data)
54 @endcode
55
56 If @c purple_marshal_BOOLEAN__POINTER_POINTER_POINTER were specified, it
57 would be:
58 @code
59 gboolean cb(void *arg1, void *arg2, void *arg3, void *data)
60 @endcode
61
62 The @c void @c *data argument at the end of each callback function
63 provides the data argument given to purple_signal_connect() .
64
65 @subsubsection cb_ret_type Callback return value type
66 In our case, this is NULL, meaning "returns void".
67 @todo This could be described better.
68
69 @subsubsection num_args Number of arguments
70 The number of arguments (not including @c data ) that the callback function
71 will take.
72
73 @subsubsection type_arg Type of argument
74 @c purple_value_new(PURPLE_TYPE_SUBTYPE,PURPLE_SUBTYPE_PLUGIN) specifies that
75 the first argument given to the callback will be a @c PurplePlugin* . You
76 will need as many "type of argument" arguments to purple_signal_register() as
77 you specified in "Number of arguments" above.
78
79 @todo Describe this more.
80
81 @See value.h
82
83 @section connect Connecting to the signal
84 Once the signal is registered, you can connect callbacks to it. First, you
85 must define a callback function, such as this one from gtkplugin.c :
86 @code
87 static void plugin_load_cb(PurplePlugin *plugin, gpointer data)
88 {
89 GtkTreeView *view = (GtkTreeView *)data;
90 plugin_loading_common(plugin, view, TRUE);
91 }
92 @endcode
93 Note that the callback function prototype matches that specified in the call
94 to purple_signal_register() above.
95
96 Once the callback function is defined, you can connect it to the signal.
97 Again from gtkplugin.c , in @c pidgin_plugin_dialog_show() :
98 @code
99 purple_signal_connect(purple_plugins_get_handle(), "plugin-load", /* What to connect to */
100 plugin_dialog, /* Object receiving the signal */
101 PURPLE_CALLBACK(plugin_load_cb), /* Callback function */
102 event_view, /* Data to pass to the callback function
103 );
104 @endcode
105
106 The first two arguments ("What to connect to") specify the object emitting
107 the signal (the plugin module) and what signal to listen for ("plugin-load").
108
109 The object receiving the signal is @c plugin_dialog , the Pidgin plugins
110 dialog. When @c plugin_dialog is deleted, then
111 @c purple_signals_disconnect_by_handle(plugin_dialog) should be called to
112 remove all signal connections it is associated with.
113
114 The callback function is given using a helper macro, and finally the
115 @c data argument to be passed to @c plugin_load_cb is given as @c event_view,
116 a pointer to the GTK widget that @c plugin_load_cb needs to update.
117
118 @section emit-signal Emitting a signal
119 Connecting callbacks to signals is all well and good, but how do you "fire"
120 the signal and trigger the callback? At some point, you must "emit" the
121 signal, which immediately calls all connected callbacks.
122
123 As seen in @c purple_plugin_load() in plugin.c :
124 @code
125 purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
126 @endcode
127 This causes the signal "plugin-load" to be emitted from the plugin module
128 (given by @c purple_plugins_get_handle() ), with the newly loaded plugin as
129 the argument to pass to any registered callback functions.
130
131 In our example, @c plugin_load_cb is called immediately as
132 @code
133 plugin_load_cb(plugin, event_view);
134 @endcode
135 and does whatever it does.
136
137 */