~ubuntu-branches/ubuntu/oneiric/gnome-panel/oneiric

« back to all changes in this revision

Viewing changes to doc/reference/panel-applet/panel-applet-docs.sgml

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-05-30 11:04:49 UTC
  • mfrom: (1.3.4 upstream)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: james.westby@ubuntu.com-20110530110449-ut1tc5t61rpvf9e3
Tags: upstream-3.0.2
ImportĀ upstreamĀ versionĀ 3.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
<?xml version="1.0" standalone="no"?>
2
 
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
3
 
    "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
4
 
<!ENTITY PanelApplet SYSTEM "xml/panel-applet.xml">
5
 
<!ENTITY PanelAppletGConf SYSTEM "xml/panel-applet-gconf.xml">
6
 
]>
 
2
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
 
3
               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
 
4
<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
7
5
 
8
 
<book id="libpanel-applet">
9
6
  <bookinfo>
10
7
    <title>Panel Applet Library Reference Manual</title>
11
 
    <authorgroup>
12
 
      <author>
13
 
        <firstname>Mark</firstname>
14
 
        <surname>McLoughlin</surname>
15
 
        <affiliation>
16
 
          <address>
17
 
            <email>mark@skynet.ie</email>
18
 
          </address>
19
 
        </affiliation>
20
 
      </author>
21
 
    </authorgroup>
22
 
 
23
 
    <copyright>
24
 
      <year>2001</year>
25
 
      <year>2003</year>
26
 
      <holder>Sun Microsystems, Inc.</holder>
27
 
    </copyright>
28
 
 
29
 
    <abstract>
30
 
      <para>
31
 
This manual documents the interfaces of the panel applet
32
 
library for GNOME 2.x and a short guide to porting applets from
33
 
the GNOME 1.x interfaces.
34
 
      </para>
35
 
    </abstract>
36
 
 
37
8
  </bookinfo>
38
9
 
39
 
  <chapter id="applet-writing">
40
 
    <title>Writing Applets</title>
41
 
 
42
 
    <para>Writing applets is very simple. You take some boiler plate
43
 
code like below, change a couple of things and write the code that
44
 
implements your widgetry. The hardest part is writing your widgetry -
45
 
and its completely up to yourself how hard that should be.
46
 
    </para>
47
 
 
48
 
    <sect1 id="hello-world">
49
 
      <title>Hello World Applet</title>
50
 
 
51
 
      <para>As usual, following the pointless tradition of starting with
52
 
an example of how get 'Hello World' on the screen in some form, here's
53
 
just about the simplest applet you could write.
54
 
      </para>
55
 
 
56
 
      <programlisting>
57
 
#include &lt;string.h&gt;
58
 
 
59
 
#include &lt;panel-applet.h&gt;
60
 
#include &lt;gtk/gtklabel.h&gt;
61
 
 
62
 
static gboolean
63
 
hello_applet_fill (PanelApplet *applet,
64
 
                   const gchar *iid,
65
 
                   gpointer     data)
66
 
{
67
 
        GtkWidget *label;
68
 
 
69
 
        if (strcmp (iid, "OAFIID:My_HelloApplet") != 0)
70
 
                return FALSE;
71
 
 
72
 
        label = gtk_label_new ("Hello World");
73
 
        gtk_container_add (GTK_CONTAINER (applet), label);
74
 
 
75
 
        gtk_widget_show_all (GTK_WIDGET (applet));
76
 
 
77
 
        return TRUE;
78
 
}
79
 
 
80
 
 
81
 
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:My_HelloApplet_Factory",
82
 
                             PANEL_TYPE_APPLET,
83
 
                             "TheHelloWorldApplet",
84
 
                             "0",
85
 
                             hello_applet_fill,
86
 
                             NULL);
87
 
      </programlisting>
88
 
 
89
 
      <para>The code here is very similar to writing a normal Bonobo
90
 
control. You define a factory using PANEL_APPLET_BONOBO_FACTORY(),
91
 
passing it a factory function like hello_applet_fill().
92
 
      </para>
93
 
 
94
 
      <para>libpanel-applet automatically creates a #PanelApplet object
95
 
for you, passing this to your factory method. Here, you should fill
96
 
the applet with your widgets just like a #GtkBin. For example, if you
97
 
were writing a cdplayer applet you would create a #GtkHBox, pack the
98
 
hbox with the cdplayer buttons and in turn add the hbox to the applet.
99
 
      </para>
100
 
 
101
 
    </sect1>
102
 
 
103
 
    <sect1 id="server-files">
104
 
      <title>Bonobo Activation .server Files For Applets</title>
105
 
 
106
 
      <para>Since an applet is a bonobo component, you must write
107
 
a .server file so that the bonobo activation daemon is aware that
108
 
your component exists and how to activate it. Copy and paste is
109
 
your friend here ...
110
 
      </para>
111
 
 
112
 
      <programlisting>
113
 
&lt;oaf_info&gt;
114
 
&lt;oaf_server iid="OAFIID:My_HelloApplet_Factory" type="exe"
115
 
            location="test-bonobo-applet"&gt;
116
 
 
117
 
        &lt;oaf_attribute name="repo_ids" type="stringv"&gt;
118
 
                &lt;item value="IDL:Bonobo/GenericFactory:1.0"/&gt;
119
 
                &lt;item value="IDL:Bonobo/Unknown:1.0"/&gt;
120
 
        &lt;/oaf_attribute&gt;
121
 
        &lt;oaf_attribute name="name" type="string" value="Hello World Applet Factory"/&gt;
122
 
        &lt;oaf_attribute name="description" type="string" value="My first applet factory"/&gt;
123
 
&lt;/oaf_server&gt;
124
 
 
125
 
&lt;oaf_server iid="OAFIID:My_HelloApplet" type="factory"
126
 
            location="OAFIID:My_HelloApplet_Factory"&gt;
127
 
 
128
 
        &lt;oaf_attribute name="repo_ids" type="stringv"&gt;
129
 
                &lt;item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/&gt;
130
 
                &lt;item value="IDL:Bonobo/Control:1.0"/&gt;
131
 
                &lt;item value="IDL:Bonobo/Unknown:1.0"/&gt;
132
 
        &lt;/oaf_attribute&gt;
133
 
        &lt;oaf_attribute name="name" type="string" value="Hello World Applet"/&gt;
134
 
        &lt;oaf_attribute name="description" type="string" value="My first applet for the GNOME2 panel"/&gt;
135
 
        &lt;oaf_attribute name="panel:icon" type="string" value="gnome-applets.png"/&gt;
136
 
&lt;/oaf_server&gt;
137
 
&lt;/oaf_info&gt;
138
 
      </programlisting>
139
 
 
140
 
      <para>Probably the most important thing to note here is that, unlike
141
 
.server files for other bonobo components, applet .server files contain
142
 
a special attribute called 'panel:icon'. This is used by the panel to display
143
 
an entry for the applet in the 'Add to Panel' dialog.
144
 
      </para>
145
 
    </sect1>
146
 
 
147
 
    <sect1 id="applet-popups">
148
 
      <title>Defining a Popup Context Menu</title>
149
 
 
150
 
      <para>FIXME: write</para>
151
 
    </sect1>
152
 
 
153
 
    <sect1 id="panel-signals">
154
 
      <title>Detecting Changes in the Panel.</title>
155
 
 
156
 
      <para>FIXME: write</para>
157
 
    </sect1>
158
 
 
159
 
    <sect1 id="session-saving">
160
 
      <title>Session/Preference Saving.</title>
161
 
 
162
 
      <para>FIXME: write</para>
163
 
    </sect1>
164
 
 
165
 
    <sect1 id="multi-applets">
166
 
      <title>Multiple Applets</title>
167
 
 
168
 
      <para>FIXME: write</para>
169
 
    </sect1>
170
 
 
171
 
  </chapter>
172
 
 
173
 
  <chapter id="applet-porting">
174
 
    <title>Porting Applets from the GNOME 1.x interfaces</title>
175
 
 
176
 
      <para>In GNOME 1.x the applet interface lived in a header called
177
 
<filename>applet-widget.h</filename>. The interface was based on GOAD,
178
 
the GNOME 1.x object activation framework. A new interface was
179
 
designed for GNOME 2.x using the power of bonobo UI embedding and the
180
 
new object activation framework, bonobo-activation. The interface is
181
 
intended to be easy to use, cruft free, but semantically similar to
182
 
the old API in order to make porting relatively painless.</para>
183
 
 
184
 
      <simplesect id="applet-porting-activation">
185
 
      <title>Applet Activation</title>
186
 
 
187
 
        <para>The first thing to change when porting to the new API is
188
 
the header. Include <filename>panel-applet.h</filename> instead of
189
 
<filename>applet-widget.h</filename>.</para>
190
 
 
191
 
        <para>Next you need to change how the applet is activated.
192
 
Browsing through old applet's code, its obvious that this was done in
193
 
various ways in the past. The best advice is to hunt out the calls to
194
 
applet_widget_init, applet_widget_new and applet_widget_add.
195
 
applet_widget_new and applet_widget_add are now effectively merged
196
 
into one call panel_applet_new, to which the top-level widget of the
197
 
applet should be passed. applet_widget_init is not neccessary anymore.
198
 
So the new code should look something like this</para>
199
 
 
200
 
      <programlisting>
201
 
#include &lt;panel-applet.h&gt;
202
 
 
203
 
static BonoboObject *
204
 
blah_applet_new ()
205
 
{
206
 
        PanelApplet *applet;
207
 
 
208
 
        /*
209
 
         * The old code setting up the applet widgetry
210
 
         * goes here. So effectively delete calls to
211
 
         * applet_widget_init and applet_widget_new
212
 
         * and the replace applet_widget_add with a call
213
 
         * to panel_applet_new.
214
 
         */
215
 
 
216
 
        applet = panel_applet_new (label);
217
 
 
218
 
        return BONOBO_OBJECT (panel_applet_get_control (applet));
219
 
}
220
 
 
221
 
static BonoboObject *
222
 
blah_applet_factory (BonoboGenericFactory *this,
223
 
                     const gchar          *iid,
224
 
                     gpointer              data)
225
 
{
226
 
        BonoboObject *applet = NULL;
227
 
 
228
 
        if (!strcmp (iid, "OAFIID:BlahApplet"))
229
 
                applet = blah_applet_new ();
230
 
 
231
 
        return applet;
232
 
}
233
 
 
234
 
 
235
 
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:BlahApplet_Factory",
236
 
                             "Blah",
237
 
                             "0",
238
 
                             blah_applet_factory,
239
 
                             NULL)
240
 
      </programlisting>
241
 
 
242
 
        <para>You should use PANEL_APPLET_BONOBO_FACTORY or
243
 
PANEL_APPLET_BONOBO_SHLIB_FACTORY depending on whether you want the
244
 
applet to be out of process or in process.</para>
245
 
 
246
 
      </simplesect>
247
 
 
248
 
      <simplesect id="applet-porting-activation-files">
249
 
      <title>Activation files</title>
250
 
 
251
 
        <para>The next thing to do may be to port from a
252
 
<filename>.gnorba</filename> file to a bonobo-activation
253
 
<filename>.server</filename> file. You no longer need a .desktop file
254
 
for applets. A <filename>.gnorba</filename> looks something like this
255
 
:</para>
256
 
 
257
 
        <programlisting>
258
 
[blah]
259
 
type=exe
260
 
repo_id=IDL:GNOME/Applet:1.0
261
 
description=Blah
262
 
location_info=blah-de-blah
263
 
        </programlisting>
264
 
 
265
 
        <para>Your <filename>.server</filename> file should look like
266
 
this :</para>
267
 
 
268
 
        <programlisting>
269
 
&lt;oaf_info&gt;
270
 
 
271
 
&lt;oaf_server iid="OAFIID:BlahApplet"
272
 
            type="exe"
273
 
            location="blah-de-blah-2"&gt;
274
 
 
275
 
        &lt;oaf_attribute name="repo_ids" type="stringv"&gt;
276
 
                &lt;item value="IDL:Bonobo/GenericFactory:1.0""/&gt;
277
 
                &lt;item value="IDL:Bonobo/Unknown:1.0"/&gt;
278
 
        &lt;/oaf_attribute&gt;
279
 
        &lt;oaf_attribute name="name" type="string" value="Blah Factory"/&gt;
280
 
        &lt;oaf_attribute name="description" type="string" value="Blah De Blah"/&gt;
281
 
 
282
 
&lt;/oaf_server&gt;
283
 
 
284
 
&lt;oaf_server iid="OAFIID:BlahApplet"
285
 
            type="factory"
286
 
            location="OAFIID:BlahApplet_Factory"&gt;
287
 
 
288
 
        &lt;oaf_attribute name="repo_ids" type="stringv"&gt;
289
 
                &lt;item value="IDL:GNOME/PanelAppletShell:1.0"/&gt;
290
 
                &lt;item value="IDL:Bonobo/Control:1.0"/&gt;
291
 
                &lt;item value="IDL:Bonobo/Unknown:1.0"/&gt;
292
 
        &lt;/oaf_attribute&gt;
293
 
        &lt;oaf_attribute name="name" type="string" value="Blah Applet"/&gt;
294
 
        &lt;oaf_attribute name="description" type="string" value="Blah De Blah"/&gt;
295
 
        &lt;oaf_attribute name="panel:icon" type="string" value="blah-de-blah.png"/&gt;
296
 
 
297
 
&lt;/oaf_server&gt;
298
 
 
299
 
&lt;/oaf_info&gt;
300
 
        </programlisting>
301
 
 
302
 
        <para>A lot of this should be copied and pasted. The most
303
 
important bit is "panel:icon" which specfies the icon
304
 
that should be displayed in the "Add to Panel" dialog.</para>
305
 
 
306
 
      </simplesect>
307
 
 
308
 
      <simplesect id="applet-porting-menus">
309
 
      <title>Context Menu</title>
310
 
 
311
 
        <para>Most applets also place extra menu items into it context
312
 
menu. It might be a good idea to port this next. In GNOME 1.x this was
313
 
done using the applet_widget_register_stock_callback API call. In
314
 
GNOME 2.x 3 things must be done</para>
315
 
 
316
 
        <itemizedlist>
317
 
        <listitem><para>An xml desription of the popup menu must be
318
 
written.</para></listitem>
319
 
        <listitem><para>A description of the verbs must be prepared.
320
 
This is basically a list of callbacks to be call when a certain menu
321
 
item is clicked in the popup.</para></listitem>
322
 
        <listitem><para>The menu is registered using a call to
323
 
panel_applet_setup_menu.</para></listitem>
324
 
        </itemizedlist>
325
 
 
326
 
        <para>The xml description should look something like this
327
 
:</para>
328
 
 
329
 
        <programlisting>
330
 
static const char fish_menu_xml [] =
331
 
        "&lt;popup name=\"button3\"&gt;\n"
332
 
        "   &lt;menuitem name=\"Properties Item\" verb=\"BlahProperties\" _label=\"Properties ...\"\n"
333
 
        "             pixtype=\"stock\" pixname=\"gtk-properties\"/&gt;\n"
334
 
        "   &lt;menuitem name=\"Help Item\" verb=\"BlahHelp\" _label=\"Help\"\n"
335
 
        "             pixtype=\"stock\" pixname=\"gtk-help\"/&gt;\n"
336
 
        "   &lt;menuitem name=\"About Item\" verb=\"BlahAbout\" _label=\"About ...\"\n"
337
 
        "             pixtype=\"stock\" pixname=\"gnome-stock-about\"/&gt;\n"
338
 
        "&lt;/popup&gt;\n";
339
 
        </programlisting>
340
 
 
341
 
        <para>This could also be in a seperate
342
 
<filename>.xml</filename> file and loaded with
343
 
panel_applet_setup_menu_from_file. The description of the verbs should
344
 
look something like :</para>
345
 
 
346
 
        <programlisting>
347
 
static const BonoboUIVerb fish_menu_verbs [] = {
348
 
        BONOBO_UI_VERB ("BlahProperties", display_properties_dialog),
349
 
        BONOBO_UI_VERB ("BlahHelp",       display_help_dialog),
350
 
        BONOBO_UI_VERB ("BlahAbout",      display_about_dialog),
351
 
 
352
 
        BONOBO_UI_VERB_END
353
 
};
354
 
        </programlisting>
355
 
 
356
 
        <para>This is just a list of callbacks invoked when the menu
357
 
items are clicked. There are other macros you may use other than
358
 
BONOBO_UI_VERB - see
359
 
<filename>bonobo-ui-component.h</filename>.</para>
360
 
 
361
 
        <para>To actually register the menu you just do something like
362
 
:</para>
363
 
 
364
 
        <programlisting>
365
 
        panel_applet_setup_menu (PANEL_APPLET (blah->applet),
366
 
                                 blah_menu_xml,
367
 
                                 blah_menu_verbs,
368
 
                                 blah);
369
 
        </programlisting>
370
 
 
371
 
        <para>The last argument is the user_data argument passed back
372
 
to the callbacks.</para>
373
 
 
374
 
        </simplesect>
375
 
 
376
 
  </chapter>
377
 
 
378
 
  <chapter id="panel-applet">
379
 
    <title>The Panel Applet Library</title>
380
 
 
381
 
    &PanelApplet;
382
 
    &PanelAppletGConf;
383
 
  </chapter>
 
10
  <part id="overview">
 
11
   <title>Panel Applet Library Overview</title>
 
12
 
 
13
    <para>
 
14
     Applets are small applications that are embedded in the GNOME panel. They can be used to give quick access to some features, or to display the state of something specific.
 
15
    </para>
 
16
 
 
17
   <para>
 
18
     The Panel Applet library is what should be used to write applets as it handles all the communication with the GNOME panel. It hides all of the embedding process of the applet behind a <link linkend="PanelApplet"><type>PanelApplet</type></link> widget. It also provides <link linkend="PanelApplet"><type>PanelApplet</type></link> API to properly integrate the applet in the panel.
 
19
   </para>
 
20
 
 
21
   <note><simpara>
 
22
    Keep in mind that starting with GNOME 3, the panel and applets are only available in the fallback mode. An applet will therefore not be usable in the default GNOME that users may use.
 
23
   </simpara></note>
 
24
 
 
25
  </part>
 
26
 
 
27
  <part id="getting-started">
 
28
    <title>Getting Started with the Panel Applet library</title>
 
29
 
 
30
   <chapter id="getting-started.intro">
 
31
    <title>Introduction</title>
 
32
 
 
33
    <para>
 
34
     While applets are rather simple to write, they are not the most easy form of interaction to users for two reasons: it is not intuitive how to add or remove applets for many users, and the restriction in size of applets can limit their interface. Therefore, before writing an applet, think hard whether this is the form of interaction that is best for the feature you want to provide.
 
35
    </para>
 
36
 
 
37
    <note><simpara>
 
38
     Keep in mind that starting with GNOME 3, the panel and applets are only available in the fallback mode. An applet will therefore not be usable in the default GNOME that users may use.
 
39
    </simpara></note>
 
40
 
 
41
   </chapter>
 
42
 
 
43
   <chapter id="getting-started.concepts">
 
44
    <title>Concepts</title>
 
45
 
 
46
    <sect2 id="getting-started.concepts.applet-types">
 
47
     <title>Applet Types</title>
 
48
 
 
49
     <para>
 
50
      The applet type is the identifier representing a type of applets to the panel. It is a simple string, like <constant>HelloWorldApplet</constant> and is unique per <link linkend="getting-started.concepts.applet-factory">applet factory</link>.
 
51
     </para>
 
52
 
 
53
    </sect2>
 
54
 
 
55
    <sect2 id="getting-started.concepts.applet-factory">
 
56
     <title>Applet Factory</title>
 
57
 
 
58
     <para>
 
59
      The applet factory is an implementation detail that is mostly hidden by the Panel Applet library, but it still appears in a few places (<link linkend="PANEL-APPLET-OUT-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_OUT_PROCESS_FACTORY()</function></link>, <link linkend="PANEL-APPLET-IN-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_IN_PROCESS_FACTORY()</function></link> and <link linkend="getting-started.install.panel-applet"><filename>.panel-applet</filename> files</link>) so it is important to understand what is an applet factory.
 
60
     </para>
 
61
 
 
62
     <para>
 
63
      The applet factory is the object that will create a new applet instance when the panel requests a new applet to be created. It is identified with a simple string id, for example <constant>HelloWorldFactory</constant>.
 
64
     </para>
 
65
 
 
66
     <para>
 
67
      The requests the applet factory will receive from the panel specify which type of applet should be created. This is what makes it possible to have more than one applet types in one applet binary. In most cases, however, the applet factory will be specific to only one applet type. The map between applet types and the applet factory is recorded in <link linkend="getting-started.install.panel-applet"><filename>.panel-applet</filename> files</link>.
 
68
     </para>
 
69
 
 
70
     <para>
 
71
      There is only one applet factory per applet binary, and it is always running before any applet instance is created by the applet binary. The applet factory is created via <link linkend="PANEL-APPLET-OUT-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_OUT_PROCESS_FACTORY()</function></link> or <link linkend="PANEL-APPLET-IN-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_IN_PROCESS_FACTORY()</function></link>.
 
72
     </para>
 
73
 
 
74
    </sect2>
 
75
 
 
76
    <sect2 id="getting-started.concepts.applet-instances">
 
77
     <title>Applet Instances</title>
 
78
 
 
79
     <para>
 
80
      There is no restriction as to how many instances of one applet type can be created. The user might choose to add more than one <constant>HelloWorldApplet</constant> applets to his panels. This can have some implications on the design used to write applets. The most important implication is that it is generally wrong to have global variables to keep a state specific to an applet instance.
 
81
     </para>
 
82
 
 
83
    </sect2>
 
84
 
 
85
   </chapter>
 
86
 
 
87
   <chapter id="getting-started.example">
 
88
    <title>Hello World Example</title>
 
89
 
 
90
    <para>
 
91
     An example is worth a million words, so here is a simple one:
 
92
    </para>
 
93
 
 
94
    <example id="getting-started.example.simple">
 
95
     <title>Hello World applet</title>
 
96
     <programlisting language="c">
 
97
#include &lt;gtk/gtk.h&gt;
 
98
#include &lt;panel-applet.h&gt;
 
99
 
 
100
static gboolean
 
101
hello_world_applet_start (PanelApplet *applet)
 
102
{
 
103
    GtkWidget *label;
 
104
 
 
105
    label = gtk_label_new ("Hello World");
 
106
    gtk_container_add (GTK_CONTAINER (applet), label);
 
107
    gtk_widget_show_all (GTK_WIDGET (applet));
 
108
 
 
109
    return TRUE;
 
110
}
 
111
 
 
112
static gboolean
 
113
hello_world_factory_callback (PanelApplet  *applet,
 
114
                              const gchar  *iid,
 
115
                              gpointer      data)
 
116
{
 
117
    gboolean retval = FALSE;
 
118
 
 
119
    if (g_strcmp0 (iid, "HelloWorldApplet") == 0)
 
120
        retval = hello_world_applet_start (applet);
 
121
 
 
122
    return retval;
 
123
}
 
124
 
 
125
PANEL_APPLET_OUT_PROCESS_FACTORY ("HelloWorldFactory",
 
126
                                  PANEL_TYPE_APPLET,
 
127
                                  hello_world_factory_callback,
 
128
                                  NULL)
 
129
     </programlisting>
 
130
    </example>
 
131
 
 
132
    <para>
 
133
     Here are the few things that are important in this example:
 
134
    </para>
 
135
 
 
136
    <itemizedlist>
 
137
     <listitem>
 
138
      <para>
 
139
       <link linkend="PANEL-APPLET-OUT-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_OUT_PROCESS_FACTORY()</function></link>: this creates an <link linkend="getting-started.concepts.applet-factory">applet factory</link> named <constant>HelloWorldFactory</constant>, and each time this applet factory will create an applet instance, it will call <function>hello_world_factory_callback()</function> with a <link linkend="PanelApplet"><type>PanelApplet</type></link> object already created.
 
140
      </para>
 
141
     </listitem>
 
142
     <listitem>
 
143
      <para>
 
144
      <function>hello_world_factory_callback()</function>: this checks if the request to create an applet instance is for an <link linkend="getting-started.concepts.applet-types">applet type</link> supported by the <link linkend="getting-started.concepts.applet-factory">applet factory</link>. Here we can see that we only support the <constant>HelloWorldApplet</constant> applet type. This function returns <constant>TRUE</constant> on success and <constant>FALSE</constant> on failures.
 
145
      </para>
 
146
     </listitem>
 
147
     <listitem>
 
148
      <para>
 
149
      <function>hello_world_applet_start()</function>: this is where we actually setup the <link linkend="PanelApplet"><type>PanelApplet</type></link> widget for the work the applet should do. This can include filling the widget, connecting to signals, etc.
 
150
      </para>
 
151
     </listitem>
 
152
    </itemizedlist>
 
153
 
 
154
    <para>
 
155
     While the previous example is simple, it can be useful to directly subclass the <link linkend="PanelApplet"><type>PanelApplet</type></link> type. This makes it easy to have a per-applet instance private structure, among other benefits.
 
156
    </para>
 
157
 
 
158
    <example id="getting-started.example.subclass">
 
159
     <title>Hello World applet, with a PanelApplet subclass</title>
 
160
     <programlisting language="c">
 
161
#include &lt;gtk/gtk.h&gt;
 
162
#include &lt;panel-applet.h&gt;
 
163
 
 
164
#define HELLO_WORLD_TYPE_APPLET (hello_world_applet_get_type ())
 
165
 
 
166
typedef struct _HelloWorldApplet        HelloWorldApplet;
 
167
typedef struct _HelloWorldAppletClass   HelloWorldAppletClass;
 
168
typedef struct _HelloWorldAppletPrivate HelloWorldAppletPrivate;
 
169
 
 
170
struct _HelloWorldApplet {
 
171
    PanelApplet parent_object;
 
172
 
 
173
    /*&lt; private &gt;*/
 
174
    HelloWorldAppletPrivate *priv;
 
175
};
 
176
 
 
177
struct _HelloWorldAppletClass {
 
178
    PanelAppletClass parent_class;
 
179
};
 
180
 
 
181
struct _HelloWorldAppletPrivate
 
182
{
 
183
    GtkWidget *label;
 
184
};
 
185
 
 
186
static GType hello_world_applet_get_type (void) G_GNUC_CONST;
 
187
 
 
188
G_DEFINE_TYPE (HelloWorldApplet, hello_world_applet, PANEL_TYPE_APPLET);
 
189
 
 
190
static void
 
191
hello_world_applet_init (HelloWorldApplet *applet)
 
192
{
 
193
    applet->priv = G_TYPE_INSTANCE_GET_PRIVATE (applet, HELLO_WORLD_TYPE_APPLET,
 
194
                                                HelloWorldAppletPrivate);
 
195
 
 
196
    applet->priv->label = gtk_label_new ("Hello World");
 
197
    gtk_container_add (GTK_CONTAINER (applet), applet->priv->label);
 
198
    gtk_widget_show (applet->priv->label);
 
199
}
 
200
 
 
201
static void
 
202
hello_world_applet_class_init (HelloWorldAppletClass *klass)
 
203
{
 
204
  g_type_class_add_private (class, sizeof (HelloWorldAppletPrivate));
 
205
}
 
206
 
 
207
static gboolean
 
208
hello_world_applet_start (HelloWorldApplet *applet)
 
209
{
 
210
    gtk_widget_show (GTK_WIDGET (applet));
 
211
 
 
212
    return TRUE;
 
213
}
 
214
 
 
215
static gboolean
 
216
hello_world_factory_callback (HelloWorldApplet *applet,
 
217
                              const gchar      *iid,
 
218
                              gpointer          data)
 
219
{
 
220
    gboolean retval = FALSE;
 
221
 
 
222
    if (g_strcmp0 (iid, "HelloWorldApplet") == 0)
 
223
        retval = hello_world_applet_start (applet);
 
224
 
 
225
    return retval;
 
226
}
 
227
 
 
228
PANEL_APPLET_OUT_PROCESS_FACTORY ("HelloWorldFactory",
 
229
                                  HELLO_WORLD_TYPE_APPLET,
 
230
                                  (PanelAppletFactoryCallback) hello_world_factory_callback,
 
231
                                  NULL)
 
232
     </programlisting>
 
233
    </example>
 
234
 
 
235
   </chapter>
 
236
 
 
237
   <chapter id="getting-started.context-menu">
 
238
    <title>Using a Context Menu</title>
 
239
 
 
240
    <para>
 
241
     The Panel Applet library uses <type>GtkAction</type> to define menu items appearing in the context menu of the applet.
 
242
    </para>
 
243
 
 
244
    <sect2 id="getting-started.context-menu.content">
 
245
     <title>Guidelines for Context Menu</title>
 
246
 
 
247
     <para>
 
248
      To help guarantee consistency in the interaction with applets, there are some guidelines that are recommended to follow:
 
249
     </para>
 
250
 
 
251
     <itemizedlist>
 
252
      <listitem>
 
253
       <para>
 
254
        Do not make the context menu too long: if you have more than five or six menu items, then it might be worth investing efforts on rethinking what is important in the menu.
 
255
       </para>
 
256
      </listitem>
 
257
      <listitem>
 
258
       <para>
 
259
        For the menu item that will enable the user to configure the applet, use "Preferences" for the label, and try to avoid "Configure", "Configuration", "Settings", etc.
 
260
       </para>
 
261
      </listitem>
 
262
      <listitem>
 
263
       <para>
 
264
        Avoid putting a "Help" menu item. The user will usually explicitly add the applet, so it is expected that he knows what the applet is about. Putting a "Help" menu item in the context menu is therefore too prominent. It might make sense to add a "Help" button in the Preferences dialog, though.
 
265
       </para>
 
266
      </listitem>
 
267
      <listitem>
 
268
       <para>
 
269
        If you agree, avoid putting a "About" menu item. To the user, applets are not different applications but elements of one global application, the panel. Of course, this means that credits for working on the applet are not visible to the user.
 
270
       </para>
 
271
      </listitem>
 
272
     </itemizedlist>
 
273
 
 
274
    </sect2>
 
275
 
 
276
    <sect2 id="getting-started.context-menu.setup">
 
277
     <title>Setting Up the Menu</title>
 
278
 
 
279
     <para>
 
280
      The only part of dealing with a context menu that is specific to applets is how to setup the context menu. Once it is setup, this is really just a matter of using <type>GtkAction</type>.
 
281
     </para>
 
282
 
 
283
     <para>
 
284
      To setup the context menu of the applet, the <link linkend="panel-applet-setup-menu-from-file"><function>panel_applet_setup_menu_from_file()</function></link> function should be used, with a path to a <link linkend="getting-started.context-menu.xml-file">menu XML file</link> and a <type>GtkActionGroup</type> object containing all actions that are used in the menu XML file. The example below shows how to achieve this:
 
285
     </para>
 
286
 
 
287
     <example>
 
288
     <title>Hello World applet, with a context menu</title>
 
289
      <programlisting language="c">
 
290
#include &lt;glib/gi18n.h&gt;
 
291
#include &lt;gtk/gtk.h&gt;
 
292
#include &lt;panel-applet.h&gt;
 
293
 
 
294
/* This would usually be defined in config.h */
 
295
#define GETTEXT_PACKAGE "hello-world"
 
296
/* This would usually be defined in Makefile.am */
 
297
#define HELLO_WORLD_UI_DIR "/usr/share/hello-world"
 
298
 
 
299
static void hello_world_applet_prefs (GtkAction   *action,
 
300
                                      PanelApplet *applet);
 
301
static void hello_world_applet_say   (GtkAction   *action,
 
302
                                      PanelApplet *applet);
 
303
 
 
304
static const GtkActionEntry hello_world_menu_actions [] = {
 
305
        { "HelloWorldPrefs", GTK_STOCK_HELP, N_("_Preferences"),
 
306
          NULL, NULL,
 
307
          G_CALLBACK (hello_world_applet_prefs) },
 
308
        { "HelloWorldSay", GTK_STOCK_ABOUT, N_("_Say Hello"),
 
309
          NULL, NULL,
 
310
          G_CALLBACK (hello_world_applet_say) }
 
311
};
 
312
 
 
313
static void
 
314
hello_world_applet_prefs (GtkAction   *action,
 
315
                          PanelApplet *applet)
 
316
{
 
317
    GtkWidget *dialog;
 
318
    dialog = gtk_message_dialog_new (NULL, 0,
 
319
                                    GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
 
320
                                    "Preferences");
 
321
    g_signal_connect (dialog, "response",
 
322
                      G_CALLBACK (gtk_widget_destroy), NULL);
 
323
    gtk_widget_show (dialog);
 
324
}
 
325
 
 
326
static void
 
327
hello_world_applet_say (GtkAction   *action,
 
328
                        PanelApplet *applet)
 
329
{
 
330
    GtkWidget *dialog;
 
331
    dialog = gtk_message_dialog_new (NULL, 0,
 
332
                                    GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
 
333
                                    "Hello World!");
 
334
    g_signal_connect (dialog, "response",
 
335
                      G_CALLBACK (gtk_widget_destroy), NULL);
 
336
    gtk_widget_show (dialog);
 
337
}
 
338
 
 
339
static gboolean
 
340
hello_world_applet_start (PanelApplet *applet)
 
341
{
 
342
    GtkWidget *label;
 
343
    GtkActionGroup *action_group;
 
344
    gchar *ui_path;
 
345
 
 
346
    label = gtk_label_new ("Hello World");
 
347
    gtk_container_add (GTK_CONTAINER (applet), label);
 
348
 
 
349
    action_group = gtk_action_group_new ("Hello World Applet Actions");
 
350
    gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
 
351
    gtk_action_group_add_actions (action_group,
 
352
                                  hello_world_menu_actions,
 
353
                                  G_N_ELEMENTS (hello_world_menu_actions),
 
354
                                  applet);
 
355
 
 
356
    ui_path = g_build_filename (HELLO_WORLD_UI_DIR, "hello-world-menu.xml", NULL);
 
357
    panel_applet_setup_menu_from_file (applet, ui_path, action_group);
 
358
 
 
359
    g_free (ui_path);
 
360
    g_object_unref (action_group);
 
361
 
 
362
    gtk_widget_show_all (GTK_WIDGET (applet));
 
363
 
 
364
    return TRUE;
 
365
}
 
366
 
 
367
static gboolean
 
368
hello_world_factory_callback (PanelApplet  *applet,
 
369
                              const gchar  *iid,
 
370
                              gpointer      data)
 
371
{
 
372
    gboolean retval = FALSE;
 
373
 
 
374
    if (g_strcmp0 (iid, "HelloWorldApplet") == 0)
 
375
        retval = hello_world_applet_start (applet);
 
376
 
 
377
    return retval;
 
378
}
 
379
 
 
380
PANEL_APPLET_OUT_PROCESS_FACTORY ("HelloWorldFactory",
 
381
                                  PANEL_TYPE_APPLET,
 
382
                                  hello_world_factory_callback,
 
383
                                  NULL)
 
384
      </programlisting>
 
385
     </example>
 
386
 
 
387
     <para>
 
388
      Here are the changes compared to the <link linkend="getting-started.example.simple">simple example</link> with no context menu:
 
389
     </para>
 
390
 
 
391
    <itemizedlist>
 
392
     <listitem>
 
393
      <para>
 
394
       We define a list of <type>GtkActionEntry</type> entries: <constant>hello_world_menu_actions</constant>. This will be used later on to build <type>GtkAction</type> objects, with their label and callback. We obviously implement the callbacks.
 
395
      </para>
 
396
     </listitem>
 
397
     <listitem>
 
398
      <para>
 
399
       We change <function>hello_world_applet_start()</function> to define a <type>GtkActionGroup</type> object, to which we add, with <function>gtk_action_group_add_actions()</function>, <type>GtkAction</type> objects based on the <type>GtkActionEntry</type> entries. Note that the the last argument to <function>gtk_action_group_add_actions()</function> will be passed as user data to the callbacks.
 
400
      </para>
 
401
     </listitem>
 
402
     <listitem>
 
403
      <para>
 
404
       We also change <function>hello_world_applet_start()</function> to add this <type>GtkActionGroup</type> object to the context menu of the applet, by calling <link linkend="panel-applet-setup-menu-from-file"><function>panel_applet_setup_menu_from_file()</function></link>. This function takes as argument a path to the <link linkend="getting-started.context-menu.xml-file">menu XML file</link> that will define how to display the <type>GtkAction</type> objects in the context menu.
 
405
      </para>
 
406
     </listitem>
 
407
    </itemizedlist>
 
408
 
 
409
    </sect2>
 
410
 
 
411
    <sect2 id="getting-started.context-menu.xml-file">
 
412
     <title>Menu XML File</title>
 
413
 
 
414
     <para>
 
415
      The file that is used to setup menu with the <link linkend="panel-applet-setup-menu-from-file"><function>panel_applet_setup_menu_from_file()</function></link> function is a <type>GtkUIManager</type> UI definition file, without the top-level <constant>&lt;ui&gt;</constant> tag. It must only contain menuitem entries and separators. For example:
 
416
     </para>
 
417
 
 
418
     <informalexample>
 
419
      <programlisting>
 
420
&lt;menuitem name="Hello World Prefs" action="HelloWorldPrefs" /&gt;
 
421
&lt;separator/&gt;
 
422
&lt;menuitem name="Hello World Say"   action="HelloWorldSay" /&gt;
 
423
      </programlisting>
 
424
     </informalexample>
 
425
 
 
426
    <para>
 
427
     Alternatively, the <link linkend="panel-applet-setup-menu"><function>panel_applet_setup_menu()</function></link> function can be used with a string containing directly the XML.
 
428
    </para>
 
429
 
 
430
    </sect2>
 
431
 
 
432
   </chapter>
 
433
 
 
434
   <chapter id="getting-started.settings">
 
435
    <title>Settings</title>
 
436
 
 
437
    <para>
 
438
     There are two main design patterns to store settings for an applet:
 
439
    </para>
 
440
 
 
441
    <itemizedlist>
 
442
     <listitem>
 
443
      <para>
 
444
       Global settings: those are settings that should be shared among all instances of the same applets. For instance, the preferred unit for temperature is something that the user will want to set only one. The way to store those settings is in no way specific to the Panel Applet library, as it should work like in any other application.
 
445
      </para>
 
446
     </listitem>
 
447
     <listitem>
 
448
      <para>
 
449
       Per-applet instance settings: those are settings that might be different depending on the instance of an applet. For instance, an applet whose goal is to display a picture should make it possible for the user to choose a different picture for each instance of the applet. The Panel Applet library provides API to help with this.
 
450
      </para>
 
451
     </listitem>
 
452
    </itemizedlist>
 
453
 
 
454
    <para>
 
455
     There is actually a third case, which is rather rare, though: per-screen settings. It might be that some applets control some per-screen settings, like the layout of the workspaces. There is currently no API to help with this as it is a very specific case that you will probably never have to deal with for a usual applet.
 
456
    </para>
 
457
 
 
458
     TODO: describe settings-oriented API
 
459
   </chapter>
 
460
 
 
461
   <chapter id="getting-started.install">
 
462
    <title>Making the Applet Visible to the Panel</title>
 
463
 
 
464
    <para>
 
465
     Simply installing the applet binary will obviously not be enough to make this applet working in the panel. Two files should be installed for this:
 
466
    </para>
 
467
 
 
468
    <itemizedlist>
 
469
     <listitem>
 
470
      <para>
 
471
       a <filename>.panel-applet</filename> file so that the panel knows that the applet.
 
472
      </para>
 
473
     </listitem>
 
474
     <listitem>
 
475
      <para>
 
476
       a D-Bus service file to autostart the binary when the panel wants to create an applet.
 
477
      </para>
 
478
     </listitem>
 
479
    </itemizedlist>
 
480
 
 
481
    <sect2 id="getting-started.install.panel-applet">
 
482
     <title>Panel Applet File</title>
 
483
 
 
484
     <para>
 
485
      The <filename>.panel-applet</filename> file is a key file about the applet binary, describing the <link linkend="getting-started.concepts.applet-factory">applet factory</link> from the binary and the <link linkend="getting-started.concepts.applet-types">applet types</link> this factory can create.
 
486
     </para>
 
487
 
 
488
     <sect3>
 
489
      <title>Example</title>
 
490
      <informalexample>
 
491
       <programlisting>
 
492
[Applet Factory]
 
493
Id=HelloWorldFactory
 
494
Name=Hello World Applet Factory
 
495
Description=Factory for the window navigation related applets
 
496
 
 
497
[HelloWorldApplet]
 
498
Name=Hello World
 
499
Description=Factory for the Hello World applet example
 
500
Icon=hello-world-icon
 
501
       </programlisting>
 
502
      </informalexample>
 
503
     </sect3>
 
504
 
 
505
     <sect3>
 
506
      <title>Format</title>
 
507
      <para>
 
508
       The file must contain a <constant>Applet Factory</constant> group with the following keys:
 
509
      </para>
 
510
 
 
511
      <itemizedlist>
 
512
       <listitem>
 
513
        <para>
 
514
         <constant>Id</constant> (string): the identifier of the applet factory. This must be the same name that will be used as the first parameter to <link linkend="PANEL-APPLET-OUT-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_OUT_PROCESS_FACTORY()</function></link> or <link linkend="PANEL-APPLET-IN-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_IN_PROCESS_FACTORY()</function></link>.
 
515
        </para>
 
516
       </listitem>
 
517
       <listitem>
 
518
        <para>
 
519
         <constant>InProcess</constant> (boolean, optional): whether the applet should be <link linkend="getting-started.in-out-process">in-process or out-of-process</link>. By default, the applet is out-of-process.
 
520
        </para>
 
521
       </listitem>
 
522
       <listitem>
 
523
        <para>
 
524
         <constant>Location</constant> (string): the path to the applet binary. Only mandatory if <constant>InProcess</constant> is <constant>true</constant>.
 
525
        </para>
 
526
       </listitem>
 
527
       <listitem>
 
528
        <para>
 
529
         <constant>Name</constant> (localized string, optional): the name of the applet factory. For example: <constant>Hello World Factory</constant>.
 
530
        </para>
 
531
       </listitem>
 
532
       <listitem>
 
533
        <para>
 
534
         <constant>Description</constant> (localized string, optional): the description of the applet factory. For example: <constant>Factory for the Hello World applet example</constant>.
 
535
        </para>
 
536
       </listitem>
 
537
      </itemizedlist>
 
538
 
 
539
      <para>
 
540
       For each applet type, it must also contain a group named with the applet type identifier. Such a group must have the following keys:
 
541
      </para>
 
542
 
 
543
      <itemizedlist>
 
544
       <listitem>
 
545
        <para>
 
546
         <constant>Name</constant> (localized string): the name of the applet type. For example: <constant>Hello World</constant>.
 
547
        </para>
 
548
       </listitem>
 
549
       <listitem>
 
550
        <para>
 
551
         <constant>Description</constant> (localized string, optional): the description of the applet type. For example: <constant>Hello World applet example</constant>.
 
552
        </para>
 
553
       </listitem>
 
554
       <listitem>
 
555
        <para>
 
556
         <constant>Icon</constant> (string, optional): the icon name of the applet type. For example: <constant>hello-world-icon</constant>. It can also be the path to an icon, but this not recommended.
 
557
        </para>
 
558
       </listitem>
 
559
       <listitem>
 
560
        <para>
 
561
         <constant>BonoboId</constant> (list of strings, optional): a list of bonobo id. This will tell the panel that this applet type can be used instead of a bonobo applet if the bonobo applet id is in this list.
 
562
        </para>
 
563
       </listitem>
 
564
      </itemizedlist>
 
565
 
 
566
     </sect3>
 
567
 
 
568
     <sect3>
 
569
      <title>Installation</title>
 
570
      <para>
 
571
       The <filename>.panel-applet</filename> file must be installed in a specific directory to be discoverable by the panel. You can fetch this directory during <constant>configure</constant> withe following code:
 
572
      </para>
 
573
 
 
574
      <informalexample>
 
575
       <programlisting>
 
576
LIBPANEL_APPLET_DIR=`$PKG_CONFIG --variable=libpanel_applet_dir libpanelapplet-4.0`
 
577
AC_SUBST(LIBPANEL_APPLET_DIR)
 
578
       </programlisting>
 
579
      </informalexample>
 
580
 
 
581
     </sect3>
 
582
 
 
583
    </sect2>
 
584
 
 
585
    <sect2 id="getting-started.install.dbus-service">
 
586
     <title>D-Bus Service File</title>
 
587
 
 
588
     <para>
 
589
      The communication between the panel and the applet factory is done over D-Bus. When creating an applet, the panel will send a message to the D-Bus service of the applet factory. If the D-Bus service is not running yet, it must be started automatically. We use D-Bus activation for this, which requires install a standard D-Bus service file. Please refer to the <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-starting-services">D-Bus documentation</ulink> for more information about D-Bus service files.
 
590
     </para>
 
591
 
 
592
     <para>
 
593
      This is only needed for <link linkend="getting-started.in-out-process">out-of-process applets</link>, because in-process applets do no need to have their binary autostarted for obvious reasons.
 
594
     </para>
 
595
 
 
596
    </sect2>
 
597
 
 
598
   </chapter>
 
599
 
 
600
   <chapter id="getting-started.integration">
 
601
    <title>Proper Integration with the Panel</title>
 
602
 
 
603
    <para>
 
604
     Since the applets appear as part of the panel to users, it is important that they behave in a consistent way. A few steps can be completed to achieve proper integration.
 
605
    </para>
 
606
 
 
607
    <sect2 id="getting-started.integration.background">
 
608
     <title>Panel Background</title>
 
609
 
 
610
     <para>
 
611
     The panel can have different types of background, depending on how the user configures the panel. By default, applets do not respect the background that is configured and can therefore look out of place.
 
612
     </para>
 
613
 
 
614
     <para>
 
615
      The <link linkend="panel-applet-set-background-widget"><function>panel_applet_set_background_widget()</function></link> function can be used to automatically have the right background drawn for a specific widget. Just using this function on the <link linkend="PanelApplet"><type>PanelApplet</type></link> object itself, or its child is usually enough to have proper background integration.
 
616
     </para>
 
617
 
 
618
     <para>
 
619
      In some rare cases, though, <link linkend="panel-applet-set-background-widget"><function>panel_applet_set_background_widget()</function></link> will not be enough. The solution is then to connect to the <link linkend="PanelApplet-change-background"><function>"change-background"</function></link> signal of the <link linkend="PanelApplet"><type>PanelApplet</type></link> object: it will be emitted when the background has changed, and it will provide the <type>cairo_pattern_t</type> pattern to use as a basis to draw the background.
 
620
     </para>
 
621
 
 
622
    </sect2>
 
623
 
 
624
    <sect2 id="getting-started.integration.lockdown">
 
625
     <title>Panel Lockdown</title>
 
626
 
 
627
     <para>
 
628
      The panel has proper support for lockdown, and when it is locked down, it is expected that all applets behave consistently in a lockdown mode too. This generally means that the preferences of the applet should not be accessible, but it could also imply a restriction on the behavior of the applet.
 
629
     </para>
 
630
 
 
631
     <para>
 
632
      The <link linkend="panel-applet-get-locked-down"><function>panel_applet_get_locked_down()</function></link> function can be used to query the state of the panel lockdown. It is also possible to react to changes by monitoring the <link linkend="PanelApplet--locked-down"><function>"locked-down"</function></link> property of the <link linkend="PanelApplet"><type>PanelApplet</type></link> object. You can achieve this by connecting to the <function>"notify::locked-down"</function> event.
 
633
     </para>
 
634
 
 
635
     <para>
 
636
       In most cases, the <type>GBinding</type> API is enough to respect the panel lockdown: <function>g_object_bind_property()</function> can be used to automatically update the visiblity of a menu item in the context menu of the applet. In the following example, the <function>"HelloWorldPrefs"</function> action (which is an action from the context menu) will only be displayed if the panel is not locked down.
 
637
 
 
638
      <informalexample>
 
639
       <programlisting language="c">
 
640
action = gtk_action_group_get_action (action_group, "HelloWorldPrefs");
 
641
g_object_bind_property (applet, "locked-down",
 
642
                        action, "visible",
 
643
                        G_BINDING_DEFAULT|G_BINDING_INVERT_BOOLEAN|G_BINDING_SYNC_CREATE);
 
644
       </programlisting>
 
645
      </informalexample>
 
646
 
 
647
      <para>
 
648
       It is obviously possible to use <function>g_object_bind_property()</function> to change the visibility of widgets that appear outside of the context menu, like a button in a window.
 
649
      </para>
 
650
 
 
651
     </para>
 
652
 
 
653
    </sect2>
 
654
 
 
655
   </chapter>
 
656
 
 
657
   <chapter id="getting-started.in-out-process">
 
658
    <title>Out-of-Process vs In-Process</title>
 
659
 
 
660
    <para>
 
661
     Applets can either live in their own process ("out-of-process") or in the panel process ("in-process"). The decision to choose one or the other is done at build time, with the macro that you use to define the applet factory: <link linkend="PANEL-APPLET-OUT-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_OUT_PROCESS_FACTORY()</function></link> is used for out-of-process applets while <link linkend="PANEL-APPLET-IN-PROCESS-FACTORY:CAPS"><function>PANEL_APPLET_IN_PROCESS_FACTORY()</function></link> is used for in-process applets. Obviously, only one of those two macros can be used.
 
662
    </para>
 
663
 
 
664
    <para>
 
665
      For most practical matters, from the applet perspective, the two options are the same. In-process applets do offer a slightly better performance when the applet is loaded, but this should not affect much the user experience. However, an in-process applet can potentially affect the whole behavior of the panel, especially in case of crashes or memory corruptions: a crash in an in-process applet will crash the whole panel. It is therefore recommended to use out-of-process applets.
 
666
    </para>
 
667
   </chapter>
 
668
 
 
669
   <chapter id="getting-started.introspection">
 
670
    <title>Writing an applet in languages other than C</title>
 
671
 
 
672
    <para>
 
673
     The Panel Applet library comes with support for <ulink url="http://live.gnome.org/GObjectIntrospection">GObject Introspection</ulink>. This makes it possible to write applets in the languages that have <ulink url="http://live.gnome.org/GObjectIntrospection/Users">bindings based on GObject Introspection</ulink>.
 
674
    </para>
 
675
 
 
676
    <para>
 
677
     Here is a simple example of a python applet:
 
678
 
 
679
     <example>
 
680
      <title>Hello World applet, in Python</title>
 
681
      <programlisting language="python">
 
682
from gi.repository import Gtk
 
683
from gi.repository import PanelApplet
 
684
 
 
685
def applet_fill(applet):
 
686
    label = Gtk.Label("Hello World")
 
687
    applet.add(label)
 
688
    applet.show_all()
 
689
 
 
690
def applet_factory(applet, iid, data):
 
691
    if iid != "HelloWorldApplet":
 
692
       return False
 
693
 
 
694
    applet_fill(applet)
 
695
 
 
696
    return True
 
697
 
 
698
PanelApplet.Applet.factory_main("HelloWorldFactory",
 
699
                                PanelApplet.Applet.__gtype__,
 
700
                                applet_factory, None)
 
701
      </programlisting>
 
702
     </example>
 
703
    </para>
 
704
 
 
705
    <para>
 
706
     The only limitation of writing an applet in a language other than C is that the applet will not be able to run in the panel process: it will have to stay out-of-process. However, since it is recommended to leave applets out-of-process, this limitation is mitigated.
 
707
    </para>
 
708
   </chapter>
 
709
 
 
710
  </part>
 
711
 
 
712
  <part id="port-gnome2">
 
713
    <title>Porting Applets from GNOME 2.x</title>
 
714
 
 
715
   <refsect1 id="port-gnome2.dbus">
 
716
    <title>Porting a D-Bus-based Applet</title>
 
717
 
 
718
    <para>
 
719
     There is no major issue porting a D-Bus-based applet from GNOME 2.x, from a Panel Applet library perspective. It is actually likely that the main issues will be that the applet has to be ported to GTK+ 3. Please refer to the <ulink url="http://library.gnome.org/devel/gtk3/stable/gtk-migrating-2-to-3.html">GTK+ 2 to GTK+ 3 migration guide</ulink> for this.
 
720
    </para>
 
721
 
 
722
   </refsect1>
 
723
 
 
724
   <refsect1 id="port-gnome2.bonobo">
 
725
    <title>Porting a Bonobo-based Applet</title>
 
726
 
 
727
    <para>
 
728
     Please see the <ulink url="http://live.gnome.org/GnomeGoals/AppletsDbusMigration">documentation</ulink> on the wiki.
 
729
    </para>
 
730
 
 
731
   </refsect1>
 
732
 
 
733
  </part>
 
734
 
 
735
  <part id="reference">
 
736
    <title>API Reference</title>
 
737
 
 
738
    <xi:include href="xml/applet.xml"/>
 
739
    <xi:include href="xml/applet-factory.xml"/>
 
740
    <xi:include href="xml/gconf.xml"/>
 
741
  </part>
384
742
 
385
743
</book>