Provided by: perlpanel_0.9.1+cvs20051225-2ubuntu1_all bug

NAME

       perlpanel-applet-howto - explains how to write applets for the PerlPanel

EXAMPLE

               # declare our package:
               package PerlPanel::Applet::HelloWorld;

               # constructor:
               sub new {
                       my $self                = {};
                       $self->{package}        = shift;
                       bless($self, $self->{package});
                       return $self;
               }

               # build the widget:
               sub configure {
                       my $self = shift;
                       $self->{widget} = Gtk2::Button->new('Click Me!');
                       $self->widget->signal_connect(
                               'clicked',
                               sub {
                                       PerlPanel::alert(
                                               'Hello World!'
                                       );
                               }
                       );
                       $self->widget->show_all;
               }

               # return the widget;
               sub widget {
                       return $_[0]->{widget};
               }

               # return the expand (1 or 0) for packing:
               sub expand {
                       return 0;
               }

               # return the fill (1 or 0) for packing:
               sub fill {
                       return 0;
               }

               # return 'start' or 'end':
               sub end {
                       return 'start';
               }

               sub get_default_config {
                       my $hashref = {
                               name    => 'value',
                               'foo'   => 'bar',
                               'list'  => [1, 2, 3, 4, 5],
                       };
                       return $hashref;
               }

               1;

INTRODUCTION

       It is very easy to write applets for the PerlPanel. Applets are simple Perl objects, and
       are allowed to do anything that a normal Gtk2-Perl program might do.

       The package name for the applet must be of the form

               PerlPanel::Applet::AppletName

       and should have the filename

               AppletName.pm

       In order to work properly with the PerlPanel, they need to have an interface the PerlPanel
       can understand.

       When it loads a module, PerlPanel will create a new instance of the applet. It will then
       call various methods of the object in order to work out what to do with it.

       These methods are explained below.

APPLET TYPES

       Since Version 0.7.0, PerlPanel has supported two applet types: single and multi. Single
       applets are just like applets developed for older versions of PerlPanel - if more than one
       instance of the applet was on the panel, then those instances would all use the same set
       of configuration data.

       Multi applets are different. A multi applet can appear several times on the panel, and
       each instance can have its own configuration settings.

       CREATING A MULTI APPLET

       The first thing you have to do is create a package variable called $MULTI:

               package PerlPanel::Applet::FooBar;
               use vars qw($MULTI);

               $MULTI = 1;

       The value of $MULTI must be a true value (1 is the simplest).

       When PerlPanel loads the applet, it checks the value of this variable and if it's true,
       then it supplies an ID argument to the applet constructor. See below for details.

       Finally, when you are querying for a configuration hashref, you must supply the ID
       mentioned above in your call to "PerlPanel::get_config()". See below for more details.

REQUIRED METHODS

               $applet->new

       The constructor. The arguments supplied to the constructor vary, depending on whether the
       applet has been defined as a multi applet or not.

       If the $MULTI variable has not been set, then @_ will look like this:

               @_ = ($package);

       where $package is a scalar containing the package name of the applet, eg
       "PerlPanel::Applet:FooBar". If the $MULTI variable is true, then @_ will look like this:

               @_ = ($package, $id);

       where $id is a scalar containing the ID of the instance. You must store this ID and use it
       when you request config data.

               $applet->configure

       This stage is intended for the loading of config data, creation of widgets, etc.

               $applet->widget

       This method should return the Gtk widget that is to be displayed on the panel. It can be
       any kind of Gtk widget apart from a window.

               $applet->expand
               $applet->fill

       The panel uses a horizontal packing box to contain the applet widgets.  These two methods
       return integer values for the 'expand' and 'fill' arguments to "pack_start()".

               $applet->get_default_config

       This method returns a reference to a hash containing the default configuration data. This
       data is imported into the user's config file and is saved to disk and can then be modified
       by the user as needed. It is only called once - the first time the applet is loaded, after
       which the panel will use the data from the user's config file.

       If this methods returns "undef" then the panel will assume there is no configuration data.

       NB: The "end()" function is now deprecated and does not need to be used in new applets.

HISTORICAL NOTE

       The following sections describe the variables and functions that PerlPanel provides that
       make applet writing easier. Prior to version 0.4.0, the functions below were accessed
       using the form

               $PerlPanel::OBJECT_REF->function_name

       As of version 0.4.0, the syntax is

               PerlPanel::function_name

       Compatibility with the old syntax was removed in version 0.7.0.

USEFUL VARIABLES

       You can access the following variables in your code that give you access to the internal
       guts of the panel:

               $PerlPanel::OBJECT_REF

       This is a reference to the main panel object. A number of methods are available for your
       use, they're explained below.

               @PerlPanel::APPLET_DIRS

       This contains directory paths which PerlPanel will use to search for applets. It will at
       least contain "$PREFIX/lib/perlpanel/PerlPanel/Applet" and "$HOME/.perlpanel/applets".

USEFUL FUNCTIONS

               PerlPanel::get_config($appletname, [$id])

       This function returns a reference containing the configuration data for the applet. The
       structure of the data will be that defined by the "get_default_config" function.

       If you supply the second $id argument, then the function will return the appropriate
       config data for the instance of the applet defined by $id.

               PerlPanel::tips()

       This returns a "Gtk2::Tooltips" object ready for use. In versions prior to 0.4.0, this was
       accessed using $PerlPanel::TOOLTIPS_REF.

               PerlPanel::icon()

       This returns a GdkPixbuf object containing the PerlPanel icon. You should use this pixbuf
       to set the icon for any windows you create, eg:

               $dialog->set_icon(PerlPanel::icon);

       You don't need to resize the pixbuf, this is done when the application (a window manager,
       or task list) requires it.

               PerlPanel::icon_size()

       The size of icons on the panel, in pixels. You should use this to scale things so that
       everything fits nicely together.

               PerlPanel::screen_width

               PerlPanel::screen_height

       These two methods return the width and height (in pixels) of the default display.
       PerlPanel attempts to work this out if the system's Gtk+ is recent enough (ie later than
       2.2.0), otherwise it will take them from the output of the xdpyinfo(1) program.

               PerlPanel::position

       This returns the panel's physical position on-screen, either 'top' or 'bottom'. This is
       useful for when you want to show popup menus from your applets (for an example, see the
       BBMenu applet), and need to know the position of the panel.

               PerlPanel::save_config

       This tells the panel to save its configuration data to the resource file.

               PerlPanel::shutdown

       This tells the panel to save its config file to disk and exit.

               PerlPanel::request_string($message, $callback)

       This is a clone of the request_string method from the Gnome libs, so that PerlPanel isn't
       dependent on Gnome being installed. It prompts the user for a string using $message, and
       executes $callback when the user presses 'Ok' or hits the Enter key. The callback's $_[0]
       will contain the supplied string.

               PerlPanel::request_password($message, $callback)

       As above, except the entry widget will not show the entered characters.

               PerlPanel::question($message, $ok_callback,
                       $cancel_callback)

       This prompts the user to answer a Yes/No type question. $ok_callback is executed when the
       user hits 'Ok'. Working out what happens when the user hits 'Cancel' is left as an
       exercise for the reader.

               PerlPanel::error($message, $ok_callback)

       This pops up a dialog with an error icon and the given message.  $ok_callback is executed
       if the user hits the 'Ok' button.

               PerlPanel::warning($message, $ok_callback)

       This pops up a dialog with a warning icon (less severe than an error) and the given
       message. $ok_callback is executed if the user hits the 'Ok' button.

               PerlPanel::notify($message, $ok_callback)

       This pops up a dialog with a information icon and the given message.  $ok_callback is
       executed if the user hits the 'Ok' button.

               PerlPanel::get_widget_position($widget)

       This returns two numbers corresponding to the position on-screen of the top-left corner of
       $widget. This means that $widget must be visible on screen.

               PerlPanel::get_mouse_pointer

       This returns two numbers corresponding to the position on-screen of the mouse pointer.

               PerlPanel::exec_wait($cmd, $callback)

       This function allows you to execute a command and wait for it to finish, without
       interrupting the Gtk main loop, and without inducing unneeded CPU load with a custom
       "while()" loop. The command contained in $cmd is opened as a filehandle - so calling
       applications which detach from STDOUT are not recommended. "exec_wait" creates a Glib
       handler and waits for "eof" from the handle. Then it executes the function in $callback.

       This function exists mainly because the 'IconBar' applet needs a way to wait for the
       desktop entry editor to close.

               PerlPanel::load_glade($name);

       This returns a "Gtk2::GladeXML" object. PerlPanel scans two directories looking for a file
       named "$name.glade":

               $HOME/.local/share/perlpanel/glade
               $PREFIX/share/perlpanel/glade

       or returns undef if it can't find anything. This is a keyboard-plastic saving utility
       only, and doesn't do anything else.

               PerlPanel::has_application_menu

       Returns a true value if an application launcher menu (BBMenu for example) is present in
       the user's applet list.

               PerlPanel::has_action_menu

       Returns a true value if an ActionMenu applet is in the user's applet list.

               PerlPanel::has_pager

       Returns a true value if an Pager applet is in the user's applet list.

               PerlPanel::lookup_icon($icon);

       This is a convenience function that wraps Gtk2::IconTheme. The $icon argument is the name
       of a program or similar. This function will return a filename or "undef" if unsuccessful.

               PerlPanel::remove_applet($appletname, $id);

       This method is only useful to multi applets. It tells PerlPanel to remove the $id instance
       of the $appletname applet from the panel. This is useful for when you want to provide a
       "remove" option in a context menu.

               PerlPanel::launch($command, $notification);

       This command provides a wrapper to the "system()" function, with additional support for
       the Startup Notification specification. When $notification is defined, then the user is
       given visible feedback that the application is being launched. Once the application has
       started (and identified itself to the panel), or a certain period of time has elapsed, the
       feedback is cancelled.

INTERNATIONALISATION SUPPORT

       PerlPanel has support for foreign languages, using the "Locale::gettext" module. PerlPanel
       provides a special function for retrieving a translation of a string:

               $translated = _($original, %params);

       $original is the original, presumably English, string. Any occurances of the keys of
       %params are replaced with their values, for example:

               $translated = _(
                       "there are {number} {type} {object}",
                       number  => 6,
                       type    => 'red',
                       object  => 'apples'
               );

       Applet authors are encouraged to wrap all the strings they use in their applets in "_()".

WRITING MENU APPLETS

       PerlPanel provides an easy-to-use base menu class for creating menu applets.  Consult
       PerlPanel::MenuBase for more information.

MANAGING TIMEOUTS

       The use of Glib timeouts (as described in Glib::MainLoop) requires careful consideration
       for PerlPanel. Applet objects and widgets may be created and destroyed many times during
       the lifetime of the PerlPanel process. If these applets make use of a timeout, and that
       timeout is not properly managed, then over time a large amount of CPU time may be used up
       by timeouts that were created by applets that are no longer in use.

       PerlPanel has a system to track timeouts created by applets, and to remove them when the
       panel is reloaded, or when a particular applet is removed from the panel. Instead of using
       "Glib::Timeout->add($msec, $callback)" to set up your applet, use the following function:

               $id = PerlPanel::add_timeout($msec, $callback);

       The arguments and return values for this function are identical to those of
       "Glib::Timeout->add()". When the panel is reloaded, all the applets are removed and new
       ones are created, so the panel will automatically clean up these timeouts.

       When you want to cancel a timeout, use this function:

               PerlPanel::remove_timeout($id);

       When the code in $callback is executed, it will receive a reference to a scalar containing
       the ID as the first member of @_. So if you want to cancel the timeout from within the
       callback, you can call write like this:

               PerlPanel::remove_timeout(${shift()});

PACKAGING YOUR APPLET

       To create an applet package that a user can install without root access, you need to
       create a gzipped tar archive, with the name "AppletName-$Version.tar.gz", that has the
       following layout:

               /
               /applet.info
               /applets
               /applets/AppletName.pm
               /share
               /share/icons
               /share/icons/hicolor
               /share/icons/hicolor/48x48
               /share/icons/hicolor/48x48/apps
               /share/icons/hicolor/48x48/apps/perlpanel-applet-appletname.png
               /share/icons/hicolor/48x48/apps/perlpanel-applet-appletname-action-specific-icon.png
               /share/perlpanel
               /share/perlpanel/glade
               /share/perlpanel/glade/appletname.glade

       The "applet.info" file should contain a single line of the form:

               AppletName:A short description of what your applet does.:Category

       This line is appended to the user's applet.registry, so they see a descriptive entry in
       the Add Applet dialog. The first field must match the "AppletName" part of the tarball's
       name.

       The $Version part of the file name should contain only digits and periods. Valid version
       strings include: 1.00 (Perl style), 1.0.0 (Kernel style), and so on.

       The .pm file which contains your applet should go into "applets/". The installer will look
       for a file called "AppletName.pm", where "AppletName" is taken from the "AppletName" part
       of the tarball's name. PerlPanel will place this file into "$HOME/.perlpanel/applets".

       The files inside the "share/" subdirectory are installed into "$HOME/.local/share". This
       is a directory defined by the Freedesktop.org base directory specification as the place in
       which user specific data files should be stored. You can use this subdirectory to install
       Glade files (which can be accessed using "load_glade()" - see above), your applet's icon,
       and any supporting icons you may need. Using this path means that calls to "lookup_icon"
       will work out the same as if the icons were in "$PREFIX/share/icons", and can also be
       themed.

       For example, if your applet controls a media player, and you want to include icons for the
       Previous, Forward, Play and Pause buttons, you can include these icons like this:

               /share/icons/hicolor/48x48/apps/perlpanel-applet-mediaplayer-previous.png
               /share/icons/hicolor/48x48/apps/perlpanel-applet-mediaplayer-next.png
               /share/icons/hicolor/48x48/apps/perlpanel-applet-mediaplayer-play.png
               /share/icons/hicolor/48x48/apps/perlpanel-applet-mediaplayer-pause.png
               /share/icons/hicolor/48x48/apps/perlpanel-applet-mediaplayer-stop.png

       And then in your applet code, you can retrieve these icons by using this:

               my $pbf = PerlPanel::lookup_icon('mediaplayer-previous', PerlPanel::icon_size);

FURTHER CONSIDERATIONS

       Please try to keep the external dependencies of your applet to a minimum.  Remember that
       your applet may get installed on systems that have a very different set of applications
       installed on them. And never, ever hard-code paths to files you depend on.

       For example, this is very bad:

               my $executable = '/usr/bin/executable';

       If the user doesn't have the "executable" program, they may install it from source, in
       which case it will probably end up in "/usr/local/bin", and your applet will break for no
       reason.

       A much better solution is to do this:

               chomp(my $executable = `which executable 2>/dev/null`);
               if (!-x $executable) {
                       PerlPanel::warning(_('Cannot find the {program} program!', program => 'executable'));
               }

       This will allow "executable" to be anywhere in the user's path, and will alert the user if
       there was a problem.

       Another area where this can cause problems is the use of external shared files, such as
       graphics and icons. Wherever possible, package shared files in your tarball as shown in
       "PACKAGING YOUR APPLET".

AUTHOR

       Gavin Brown <gavin.brown@uk.com>.