[Xfce4-commits] <xfce4-indicator-plugin:master> Merge remote-tracking branch 'origin/andrzejr/tmp3'

Mark Trompell noreply at xfce.org
Thu Apr 4 17:44:36 CEST 2013


Updating branch refs/heads/master
         to 305bd32976b88219e2432154c8500877283eb7ac (commit)
       from 54fde8601d0b15ef10a6c1b76ea5eb987992b995 (commit)

commit 305bd32976b88219e2432154c8500877283eb7ac
Merge: 54fde86 f60f6d5
Author: Mark Trompell <mark at foresightlinux.org>
Date:   Thu Apr 4 17:41:20 2013 +0200

    Merge remote-tracking branch 'origin/andrzejr/tmp3'

commit f60f6d59702faef79cb3c346002395cbd0696c86
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Wed Apr 3 01:46:26 2013 +0100

    Fixed #9040.
    
    This required getting replacing XfcePanelImage with GtkImage. The former
    does not work reliably with non-square icons and added automatization
    is not needed in this case.
    
    Only horizontal non-square icons are supported (vertical will be squeezed
    into a square shape). Non-square icons are rendered in a single row
    (like indicators with labels).

commit 985d34925075ffd8ea020cec1fd2e849d47aff83
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Tue Apr 2 20:17:03 2013 +0100

    indicator-button: minor fix to gtk_menu_popup call
    
    Getting time from the event structure rather than from
    gtk_get_current_event_time(). It does not solve menu flicker
    issues present in some indicators (appmenu, qt-sni etc), though.
    They seem to originate from the indicator itself.

commit 23dfad6c95ba2502b2c5d6b0c26722c3e09ff59e
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Fri Mar 22 01:37:16 2013 +0000

    Reworked indicator entry sorting
    
    Special case for libapplication.so, where entries have non-unique
    location fields. Sorting them by name (at least the order is same
    every time the panel is started).

commit 8c1c94439f5f7ba5e91f9c63ea7307c885de092c
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Fri Mar 22 00:36:35 2013 +0000

    Using 22px icon size by default.
    
    This is the size of icons most (all?) indicators provide.

commit dd4f96d9db59a24ad421fc13e8c633a384ce92a4
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Fri Mar 22 00:31:56 2013 +0000

    Added an About dialog.

commit bc0abf05233f99011c77d4d6dd27943059be37bd
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Fri Mar 22 00:30:15 2013 +0000

    Fixed crash on Xfce 4.8 (no xfce_dialog_show_help)
    
    Online help doesn't seem to work anyway (no page on docs.xfce.org for
    non-core plugins), so for now have reverted to
    goodies.xfce.org.

commit 8eb305349bff65313d8300defa8918675cc38bf6
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Thu Mar 14 01:22:35 2013 +0000

    Fixed a regression, inconsistent border sizes.
    
    Not sure why different buttons had different x/ythickness values.
    Fixed that by checking container's style. Also, reduced the border
    size by 2px.

commit 81c78516eec9103da0ba00c79ab2d936a91b6c99
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Thu Mar 14 00:44:46 2013 +0000

    Force a configuration-changed signal at start-up.

commit 346cfe1ab16173fc0c5fe13a23c144a94f99239e
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Wed Mar 13 01:16:13 2013 +0000

    Hiding one of "hidden"/"visible" columns to minimize confusion.

commit b552265a8ed94468d24f6eeb387a2a7b762cc94c
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Wed Mar 13 00:15:05 2013 +0000

    Added "pretty names" and indicators for known indicators.
    
    I've used listed indicators available in Ubuntu (12.10) repository.
    The names are unofficial and icons are picked from my own system.
    Please feel free to update/fix them.

commit 33d3eb312c04fb7ae12e2a316e52a838267e5e0a
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Tue Mar 12 22:53:25 2013 +0000

    Sort indicator entries by location.
    
    (or by name_hint, or don't sort at all)

commit 290c5f4596900e67f3c2e87f730812e8e48a9333
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Tue Mar 12 22:13:44 2013 +0000

    Properly connecting indicator-list-changed signal.

commit 0db001bdd6e764e2e375ac69ad01418c09c3b6da
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Tue Mar 12 02:08:51 2013 +0000

    Added support for indicator reordering.
    
    Fairly extensive changes to the indicator container class.
    Needs testing with more complex indicators (globalmenu etc).

commit 86c62c471dcaf3f2a9b84a501e9e49d2ffc1152e
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Mon Mar 11 02:17:21 2013 +0000

    Configuration system rework.
    
    Abstracted out configuration settings. All xfconf, configuration and
    dialog properies are now bound.
    Reworked parts of box and button classes to match the configuration
    system better.
    
    At the moment, filtering options (white/blacklists) work only at start-up.
    Not sure if libindicator allows unloading indicator modules.
    Also, for now, indicator sorting does not change the indicator order in
    the container.

commit 94c371f5760b00df1cbba141a12c3192aa339e2b
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Tue Dec 25 23:56:10 2012 +0000

    Plugged a memory leak.

commit 1c76403a300e778ca5e170acbbf3f01dde9c8c18
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Dec 9 02:46:58 2012 +0000

    Fixed menu positioning.
    
    Occasionally, e.g. when indicator was placed near the bottom
    of a vertical panel, the first click on a button resulted
    in an incorrect position/size of the menu. Subsequent clicks
    were "fixing" this behavior.
    
    This commit repositions the menu to reset its position and size.

commit 707ad099934c2e3ff7aab18c0601b6072e23f782
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Dec 2 21:34:37 2012 +0000

    Worked around crashes when plugin is loaded as an external plugin.
    
    The plugin used to crash when xfce4-panel was compiled with
    --enable-debug and the plugin was configured as an external module
    (X-XFCE-Internal=FALSE in indicator.desktop file).
    
    This was caused by the wrapper binary setting a more restrictive
    fatal mask than the xfce4-panel binary. As we are linking external
    code (indicators) we have no control over their use of g_warning or
    g_critical.
    
    This commit relaxes the fatal mask so that the use of g_warning or
    g_critical does not crash the plugin.

commit 00633e1de8308a1456a46f8dc03f7baa2a62c30a
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sat Nov 17 21:39:39 2012 +0000

    Removed unneeded event box causing issues with transparent panels.
    
    For unknown reasons indicator plugin was handling transparency
    correctly when run as an executable but not when run as a module.

commit aaa1b5f89857605cfbc512f17623d2c66e1f1512
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Wed Jul 25 17:35:50 2012 +0900

    Make sure the menu is closed when the button is removed.

commit 24788ad2952d8afc4e2135d176bd62a7755a3d87
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Thu May 10 23:47:10 2012 +0900

    Fixed compilation warnings
    
    The remaining ones:
    /usr/local/include/libindicator-0.4/libindicator/indicator-object.h:190:13: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
    come from libindicator headers.

commit c40c282be0037c4de230fc7178c786a5fbab3689
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Apr 29 02:33:43 2012 +0900

    Fixed missing placeholder label (regression)
    
    also, use an ellipsis mode for labels in the deskbar mode.

commit 2cb73e6d4175c5d693e91cc5357ac4564912e18f
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sat Apr 28 19:03:13 2012 +0900

    Moved button-related event handlers to buttons

commit c9785b9b7beb502e6b7bd03cbfbc6cd765040a29
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sat Apr 28 15:31:55 2012 +0900

    Refactored XfceIndicatorButton class
    
    Moved box-specific fields to XfceIndicatorBox and added
    a box-layout-changed signal to update all buttons at once.
    This may also be faster and less glitchy as signals
    are merged by the main loop.

commit 8af1dffe564bf937c61ff0d3381a1d543b628e5b
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sat Apr 28 01:25:19 2012 +0900

    compilation error fix

commit fb8b0c8d6ca2337d7e4187685ee98dbe5e8420a0
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Fri Apr 27 20:41:59 2012 +0900

    Added "align-left" property
    
    It also improves handling of button alignment
    (uses GtkAlignment instead of GtkArray).

commit 57b1394a49142a979d77f089819f9c45f49320ab
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Apr 8 23:59:25 2012 +0900

    Fixed panel 4.9 assert (widget not constructed)
    
    and some compilation warning fixes.

commit d0bef06d946defc9fb2ae3682b1498092906713e
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Apr 8 23:57:21 2012 +0900

    Cleaning some runtime GObject assert violations

commit 81aecb3bc340f90b460d73f61d2ddea443416075
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Mon Apr 2 11:00:42 2012 +0900

    bugfix: fixed label orientation.
    
    The error occurred in appmenu labels at switching the panel mode
    from vertical to e.g. deskbar. There was a race condition between
    setting the label and setting the button orientation.

commit c90af565ed597a79071ea2559451f2c781716cfd
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Apr 1 23:41:53 2012 +0900

    Reworked dialog UI.

commit e79f2b355ddb6600fbea0ebebb03ade066807842
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Apr 1 03:07:06 2012 +0900

    Added comments.

commit 44ef2fa54ba164b9b434b01d82ca739b4b49a9ce
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sun Apr 1 03:06:19 2012 +0900

    Experiment with preferences dialog.
    
    Added an XfceIndicatorDialog class based on GtkBuilder.
    Added dependency on libxfce4ui (v.4.8 - not checked if earlier revisions
    work)
    
    The UI file (stub) was copied from the systray plugin.

commit 02a4e03020680a20333035397f49f99186941635
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sat Mar 31 23:57:38 2012 +0900

    Reverted glade related change - not ready yet.

commit f84d012dc997211a43236325bca50dc7092ec3e3
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Sat Mar 31 21:57:43 2012 +0900

    Making the plugin a library and a subclass of XfcePanelPlugin
    
    The plugin is now installed as a library and to a different directory
    (following convention of other plugins).
    
    The plugin is now an object of IndicatorPlugin class, which extends
    XfcePanelPlugin. This is for making definition of properties and integration
    with xfconf easier.
    
    Conflicts:
    
    	panel-plugin/indicator.c

commit d59fbfc202bd55d0821037b250e89cb31100457e
Author: Andrzej <ndrwrdck at gmail.com>
Date:   Thu Mar 29 23:49:06 2012 +0900

    Reworked entry_removed handler

 configure.in.in                                    |    8 +
 panel-plugin/Makefile.am                           |   61 +-
 panel-plugin/indicator-box.c                       |  558 +++++++-------
 panel-plugin/indicator-box.h                       |   38 +-
 panel-plugin/indicator-button.c                    |  445 ++++++++---
 panel-plugin/indicator-button.h                    |   72 +-
 panel-plugin/indicator-config.c                    |  781 ++++++++++++++++++++
 panel-plugin/indicator-config.h                    |  103 +++
 panel-plugin/indicator-dialog.c                    |  602 +++++++++++++++
 panel-plugin/indicator-dialog.glade                |  442 +++++++++++
 panel-plugin/indicator-dialog.h                    |   44 ++
 panel-plugin/indicator.c                           |  480 ++++++-------
 ...ndicator.desktop.in.in => indicator.desktop.in} |    4 +-
 panel-plugin/indicator.h                           |   44 +-
 14 files changed, 2925 insertions(+), 757 deletions(-)

diff --git a/configure.in.in b/configure.in.in
index d2f88ca..fd7258c 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -30,6 +30,7 @@ dnl ***************************
 AM_INIT_AUTOMAKE([1.8 dist-bzip2 tar-ustar])
 AM_CONFIG_HEADER([config.h])
 AM_MAINTAINER_MODE()
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
 dnl ********************************
 dnl *** Check for basic programs ***
@@ -41,6 +42,12 @@ AC_PROG_INTLTOOL()
 LT_PREREQ([2.2.6])
 LT_INIT([disable-static])
 
+dnl **************************
+dnl *** Initialize libtool ***
+dnl **************************
+LT_PREREQ([2.2.6])
+LT_INIT([disable-static])
+
 dnl **********************************
 dnl *** Check for standard headers ***
 dnl **********************************
@@ -68,6 +75,7 @@ dnl ***********************************
 XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.14.0])
 XDT_CHECK_PACKAGE([EXO], [exo-1], [0.6.0])
 XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.3.99.2])
+XDT_CHECK_PACKAGE([LIBXFCE4UI], [libxfce4ui-1], [4.8.0])
 XDT_CHECK_PACKAGE([LIBXFCE4PANEL], [libxfce4panel-1.0], [4.3.99.2])
 XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [4.6.0])
 XDT_CHECK_PACKAGE([INDICATOR], [indicator], [0.3.0], [indicator_pkgname=indicator], [XDT_CHECK_PACKAGE([INDICATOR], [indicator-0.4], [0.3.90], [indicator_pkgname=indicator-0.4], [])])
diff --git a/panel-plugin/Makefile.am b/panel-plugin/Makefile.am
index c07a45c..fcec7f7 100644
--- a/panel-plugin/Makefile.am
+++ b/panel-plugin/Makefile.am
@@ -1,30 +1,40 @@
+
 INCLUDES =										\
 	-I$(top_srcdir)								\
-	-DG_LOG_DOMAIN=\"xfce4-indicator-plugin\"	\
+	-DG_LOG_DOMAIN=\"libindicator-plugin\"	\
 	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"		\
 	$(PLATFORM_CPPFLAGS)
 
 #
 # Indicator plugin
 #
-plugin_PROGRAMS =								\
-	xfce4-indicator-plugin
+plugindir = \
+	$(libdir)/xfce4/panel/plugins
+
+plugin_LTLIBRARIES = \
+	libindicator-plugin.la
 
-plugindir =										\
-	$(libexecdir)/xfce4/panel-plugins
+libindicator_built_sources = \
+	indicator-dialog_ui.h
 
-xfce4_indicator_plugin_SOURCES =				\
+libindicator_plugin_la_SOURCES = \
+	$(libindicator_built_sources) \
+	indicator-config.c									\
+	indicator-config.h									\
 	indicator-button.c									\
 	indicator-button.h									\
 	indicator-box.c									\
 	indicator-box.h									\
+	indicator-dialog.c \
+	indicator-dialog.h \
 	indicator.c									\
 	indicator.h									
 
-xfce4_indicator_plugin_CFLAGS =					\
+libindicator_plugin_la_CFLAGS = \
 	$(GTK_CFLAGS) \
 	$(EXO_CFLAGS) \
 	$(LIBXFCE4UTIL_CFLAGS)						\
+	$(LIBXFCE4UI_CFLAGS) \
 	$(LIBXFCE4PANEL_CFLAGS)						\
 	$(XFCONF_CFLAGS)					\
 	$(INDICATOR_CFLAGS)						\
@@ -33,11 +43,18 @@ xfce4_indicator_plugin_CFLAGS =					\
 	-DINDICATOR_ICONS_DIR=\""$(INDICATORICONSDIR)"\" \
 	-DINDICATOR_DIR=\""$(INDICATORDIR)"\"
 
+libindicator_plugin_la_LDFLAGS = \
+	-avoid-version \
+	-module \
+	-no-undefined \
+	-export-symbols-regex '^xfce_panel_module_(preinit|init|construct)' \
+	$(PLATFORM_LDFLAGS)
 
-xfce4_indicator_plugin_LDADD =					\
+libindicator_plugin_la_LIBADD = \
 	$(GTK_LIBS) \
 	$(EXO_LIBS) \
 	$(LIBXFCE4UTIL_LIBS)						\
+	$(LIBXFCE4UI_LIBS) \
 	$(LIBXFCE4PANEL_LIBS)						\
 	$(XFCONF_LIBS)						\
 	$(INDICATOR_LIBS)
@@ -46,16 +63,10 @@ xfce4_indicator_plugin_LDADD =					\
 # Desktop file
 #
 desktopdir =									\
-	$(datadir)/xfce4/panel-plugins
-
-desktop_in_in_files =							\
-	indicator.desktop.in.in
-
-desktop_in_files =								\
-	$(desktop_in_in_files:.desktop.in.in=.desktop.in)
+	$(datadir)/xfce4/panel/plugins
 
-%.desktop.in: %.desktop.in.in
-	sed -e "s,\@libexecdir\@,$(libexecdir),g" < $< > $@
+desktop_in_files = \
+	indicator.desktop.in
 
 desktop_DATA =									\
 	$(desktop_in_files:.desktop.in=.desktop)
@@ -63,10 +74,20 @@ desktop_DATA =									\
 @INTLTOOL_DESKTOP_RULE@
 
 EXTRA_DIST =									\
-	$(desktop_in_in_files)
+	$(desktop_in_files)
 
-CLEANFILES =									\
-	$(desktop_in_files)							\
+DISTCLEANFILES = \
 	$(desktop_DATA)
 
+if MAINTAINER_MODE
+BUILT_SOURCES = \
+	$(libindicator_built_sources)
+
+DISTCLEANFILES += \
+	$(libindicator_built_sources)
+
+indicator-dialog_ui.h: indicator-dialog.glade
+	$(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=indicator_dialog_ui $< >$@
+endif
+
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/panel-plugin/indicator-box.c b/panel-plugin/indicator-box.c
index 95376dd..c181009 100644
--- a/panel-plugin/indicator-box.c
+++ b/panel-plugin/indicator-box.c
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2012 Andrzej <ndrwrdck at gmail.com>
+/*  Copyright (c) 2012-2013 Andrzej <ndrwrdck at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -15,6 +15,15 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+
+
+/*
+ *  This file implements a container class for holding indicator buttons.
+ *
+ */
+
+
+
 #include <glib.h>
 #include <gtk/gtk.h>
 #include <exo/exo.h>
@@ -25,14 +34,8 @@
 #include "indicator-button.h"
 
 static void                 xfce_indicator_box_finalize       (GObject          *object);
-static void                 xfce_indicator_box_get_property   (GObject          *object,
-                                                               guint             prop_id,
-                                                               GValue           *value,
-                                                               GParamSpec       *pspec);
-static void                 xfce_indicator_box_set_property   (GObject          *object,
-                                                               guint             prop_id,
-                                                               const GValue     *value,
-                                                               GParamSpec       *pspec);
+static void                 xfce_indicator_box_list_changed   (XfceIndicatorBox *box,
+                                                               IndicatorConfig  *config);
 static void                 xfce_indicator_box_add            (GtkContainer     *container,
                                                                GtkWidget        *child);
 static void                 xfce_indicator_box_remove         (GtkContainer     *container,
@@ -46,15 +49,35 @@ static void                 xfce_indicator_box_size_request   (GtkWidget
                                                                GtkRequisition   *requisition);
 static void                 xfce_indicator_box_size_allocate  (GtkWidget        *widget,
                                                                GtkAllocation    *allocation);
-static gint                 xfce_indicator_box_get_row_size   (XfceIndicatorBox *box);
 
 
-enum
+struct _XfceIndicatorBox
 {
-  PROP_0,
-  PROP_ICON_SIZE_MAX
+  GtkContainer          __parent__;
+
+  IndicatorConfig      *config;
+
+  GHashTable           *children;
+
+  gint                  panel_size;
+  gint                  nrows;
+  gint                  icon_size_max;
+  gboolean              align_left;
+
+  GtkOrientation        panel_orientation;
+  GtkOrientation        orientation;
+
+  gulong                indicator_list_changed_id;
+};
+
+struct _XfceIndicatorBoxClass
+{
+  GtkContainerClass __parent__;
 };
 
+
+
+
 G_DEFINE_TYPE (XfceIndicatorBox, xfce_indicator_box, GTK_TYPE_CONTAINER)
 
 static void
@@ -66,8 +89,6 @@ xfce_indicator_box_class_init (XfceIndicatorBoxClass *klass)
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = xfce_indicator_box_finalize;
-  gobject_class->get_property = xfce_indicator_box_get_property;
-  gobject_class->set_property = xfce_indicator_box_set_property;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
   gtkwidget_class->size_request = xfce_indicator_box_size_request;
@@ -78,15 +99,6 @@ xfce_indicator_box_class_init (XfceIndicatorBoxClass *klass)
   gtkcontainer_class->remove = xfce_indicator_box_remove;
   gtkcontainer_class->forall = xfce_indicator_box_forall;
   gtkcontainer_class->child_type = xfce_indicator_box_child_type;
-
-  g_object_class_install_property (gobject_class,
-                                   PROP_ICON_SIZE_MAX,
-                                   g_param_spec_uint ("icon-size-max",
-                                                      NULL, NULL,
-                                                      1,
-                                                      128,
-                                                      24,
-                                                      EXO_PARAM_READWRITE));
 }
 
 
@@ -99,13 +111,8 @@ xfce_indicator_box_init (XfceIndicatorBox *box)
   gtk_widget_set_can_focus(GTK_WIDGET(box), TRUE);
   gtk_container_set_border_width(GTK_CONTAINER(box), 0);
 
-  box->children = NULL;
-
-  box->nrows = 1;
-  box->icon_size_max = 24;
-  box->panel_size = 16;
-  box->panel_orientation = GTK_ORIENTATION_HORIZONTAL;
-  box->orientation = GTK_ORIENTATION_HORIZONTAL;
+  /* todo: no deallocation function for values */
+  box->children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 }
 
 
@@ -115,159 +122,86 @@ xfce_indicator_box_finalize (GObject *object)
 {
   XfceIndicatorBox *box = XFCE_INDICATOR_BOX (object);
 
-  if (box->children != NULL)
+  if (box->indicator_list_changed_id != 0)
     {
-      g_slist_free (box->children);
-      g_debug ("Not all icons have been removed from the indicator icon box.");
+      g_signal_handler_disconnect (box->config, box->indicator_list_changed_id);
+      box->indicator_list_changed_id = 0;
     }
 
+  g_hash_table_destroy (box->children);
+
   G_OBJECT_CLASS (xfce_indicator_box_parent_class)->finalize (object);
 }
 
 
 
-static void
-xfce_indicator_box_get_property (GObject    *object,
-                                 guint       prop_id,
-                                 GValue     *value,
-                                 GParamSpec *pspec)
+GtkWidget *
+xfce_indicator_box_new (IndicatorConfig *config)
 {
-  XfceIndicatorBox *box = XFCE_INDICATOR_BOX (object);
-  GPtrArray        *array;
+  XfceIndicatorBox *box = g_object_new (XFCE_TYPE_INDICATOR_BOX, NULL);
 
-  switch (prop_id)
-    {
-    case PROP_ICON_SIZE_MAX:
-      g_value_set_uint (value, box->icon_size_max);
-      break;
+  box->config = config;
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
+  box->indicator_list_changed_id =
+    g_signal_connect_swapped (G_OBJECT (box->config), "indicator-list-changed",
+                              G_CALLBACK (xfce_indicator_box_list_changed), box);
+
+  return GTK_WIDGET (box);
 }
 
 
 
 static void
-xfce_indicator_box_set_property (GObject      *object,
-                                 guint         prop_id,
-                                 const GValue *value,
-                                 GParamSpec   *pspec)
+xfce_indicator_box_list_changed (XfceIndicatorBox *box,
+                                 IndicatorConfig  *config)
 {
-  XfceIndicatorBox     *box = XFCE_INDICATOR_BOX (object);
-  gint                  val;
-  gint                  size;
-  XfceIndicatorButton  *child;
-  GSList               *li;
-
-  switch (prop_id)
-    {
-    case PROP_ICON_SIZE_MAX:
-      val = g_value_get_uint (value);
-      if (box->icon_size_max != val)
-        {
-          box->icon_size_max = val;
-          size = xfce_indicator_box_get_row_size (box);
-          for (li = box->children; li != NULL; li = li->next)
-            {
-              child = XFCE_INDICATOR_BUTTON (li->data);
-              g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child));
-              xfce_indicator_button_set_size (child, box->panel_size, size);
-            }
-          gtk_widget_queue_resize (GTK_WIDGET (box));
-        }
-      break;
+  g_return_if_fail (XFCE_IS_INDICATOR_BOX (box));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
+  gtk_widget_queue_resize (GTK_WIDGET (box));
 }
 
 
 
-void
-xfce_indicator_box_set_orientation (XfceIndicatorBox *box,
-                                    GtkOrientation    panel_orientation,
-                                    GtkOrientation    orientation)
+static gint
+xfce_indicator_box_sort_buttons (gconstpointer a,
+                                 gconstpointer b)
 {
-  gboolean              needs_update = FALSE;
-  XfceIndicatorButton  *child;
-  GSList               *li;
+  XfceIndicatorButton *a0 = XFCE_INDICATOR_BUTTON (a);
+  XfceIndicatorButton *b0 = XFCE_INDICATOR_BUTTON (b);
+  guint                a1, b1;
+  const gchar         *a_io;
+  gint                 result = 0;
 
-  g_return_if_fail (XFCE_IS_INDICATOR_BOX (box));
+  a1 = xfce_indicator_button_get_pos (a0);
+  b1 = xfce_indicator_button_get_pos (b0);
 
-  if (box->orientation != orientation)
-    {
-      box->orientation = orientation;
-      needs_update = TRUE;
-    }
+  /* only need one */
+  a_io = xfce_indicator_button_get_io_name (a0);
 
-  if (box->panel_orientation != panel_orientation)
-    {
-      box->panel_orientation = panel_orientation;
-      needs_update = TRUE;
-    }
+  // printf ("=== %s, %s; %s, %s; %d, %d", xfce_indicator_button_get_io_name (a0), xfce_indicator_button_get_io_name (b0), xfce_indicator_button_get_entry (a0)->name_hint, xfce_indicator_button_get_entry (b0)->name_hint, a1, b1);
 
-  if (needs_update)
-    {
-      for (li = box->children; li != NULL; li = li->next)
-        {
-          child = XFCE_INDICATOR_BUTTON (li->data);
-          g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child));
-          xfce_indicator_button_set_orientation (child, panel_orientation, orientation);
-        }
-      gtk_widget_queue_resize (GTK_WIDGET (box));
-    }
-}
+  /* special case for Application indicators (unreliable ordering) */
+  /* always compare by name and ignore location field */
+  if (a_io != NULL && g_strcmp0 (a_io, "libapplication.so") == 0)
+    result = g_strcmp0 (xfce_indicator_button_get_entry(a0)->name_hint,
+                        xfce_indicator_button_get_entry(b0)->name_hint);
 
+  /* group all entries with location==0 at the beginning of the list
+   * but don't sort them (they may depend on insertion order) */
 
+  if (result == 0 && (a1 != 0 || b1 != 0))
+    result = a1-b1;
 
-void
-xfce_indicator_box_set_size (XfceIndicatorBox *box,
-                             gint              panel_size,
-                             gint              nrows)
-{
-  gboolean              needs_update = FALSE;
-  XfceIndicatorButton  *child;
-  GSList               *li;
-  gint                  size;
+  /* if there are two entries with the same non-zero location
+   * try to resolve their order by their name_hint */
 
-  g_return_if_fail (XFCE_IS_INDICATOR_BOX (box));
+  if (result == 0)
+    result =  g_strcmp0 (xfce_indicator_button_get_entry(a0)->name_hint,
+                         xfce_indicator_button_get_entry(b0)->name_hint);
 
-  if (box->nrows != nrows)
-    {
-      box->nrows = nrows;
-      needs_update = TRUE;
-    }
-
-  if (box->panel_size != panel_size)
-    {
-      box->panel_size = panel_size;
-      needs_update = TRUE;
-    }
-
-  if (needs_update)
-    {
-      size = xfce_indicator_box_get_row_size (box);
-      for (li = box->children; li != NULL; li = li->next)
-        {
-          child = XFCE_INDICATOR_BUTTON (li->data);
-          g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child));
-          xfce_indicator_button_set_size (child, panel_size, size);
-        }
-      gtk_widget_queue_resize (GTK_WIDGET (box));
-    }
-}
-
-
-
-GtkWidget *
-xfce_indicator_box_new ()
-{
-  XfceIndicatorBox *box = g_object_new (XFCE_TYPE_INDICATOR_BOX, NULL);
-  return GTK_WIDGET (box);
+  // printf (" -> %d\n", result);
+  return result;
 }
 
 
@@ -278,18 +212,25 @@ xfce_indicator_box_add (GtkContainer *container,
 {
   XfceIndicatorBox    *box = XFCE_INDICATOR_BOX (container);
   XfceIndicatorButton *button = XFCE_INDICATOR_BUTTON (child);
-  gint                 size;
+  GList               *li;
+  const gchar         *io_name;
 
   g_return_if_fail (XFCE_IS_INDICATOR_BOX (box));
-  g_return_if_fail (GTK_IS_WIDGET (child));
+  g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
   g_return_if_fail (child->parent == NULL);
 
-  box->children = g_slist_append (box->children, child);
+  io_name = xfce_indicator_button_get_io_name (button);
+  li = g_hash_table_lookup (box->children, io_name);
+  // printf ("   +++ %s %s\n", io_name, xfce_indicator_button_get_entry (button)->name_hint);
+  if (g_strcmp0 (io_name, "libapplication.so") != 0 &&
+      xfce_indicator_button_get_pos (button) == 0)
+    li = g_list_append (li, button);
+  else
+    li = g_list_insert_sorted (li, button, xfce_indicator_box_sort_buttons);
+
+  g_hash_table_replace (box->children, g_strdup (io_name), li);
 
   gtk_widget_set_parent (child, GTK_WIDGET (box));
-  xfce_indicator_button_set_orientation (button, box->panel_orientation, box->orientation);
-  size = xfce_indicator_box_get_row_size (box);
-  xfce_indicator_button_set_size (button, box->panel_size, size);
 
   gtk_widget_queue_resize (GTK_WIDGET (container));
 }
@@ -300,17 +241,22 @@ static void
 xfce_indicator_box_remove (GtkContainer *container,
                            GtkWidget    *child)
 {
-  XfceIndicatorBox *box = XFCE_INDICATOR_BOX (container);
-  GSList           *li;
+  XfceIndicatorBox    *box = XFCE_INDICATOR_BOX (container);
+  XfceIndicatorButton *button = XFCE_INDICATOR_BUTTON (child);
+  GList               *li, *li_tmp;
+  const gchar         *io_name;
 
   /* search the child */
-  li = g_slist_find (box->children, child);
-  if (G_LIKELY (li != NULL))
+  io_name = xfce_indicator_button_get_io_name (button);
+  li = g_hash_table_lookup (box->children, io_name);
+  li_tmp = g_list_find (li, child);
+  if (G_LIKELY (li_tmp != NULL))
     {
-      g_assert (GTK_WIDGET (li->data) == child);
+      g_assert (GTK_WIDGET (li_tmp->data) == child);
 
       /* unparent widget */
-      box->children = g_slist_remove_link (box->children, li);
+      li = g_list_remove_link (li, li_tmp);
+      g_hash_table_replace (box->children, g_strdup (io_name), li);
       gtk_widget_unparent (child);
 
       /* resize, so we update has-hidden */
@@ -327,13 +273,23 @@ xfce_indicator_box_forall (GtkContainer *container,
                            gpointer      callback_data)
 {
   XfceIndicatorBox *box = XFCE_INDICATOR_BOX (container);
-  GSList           *li, *lnext;
+  GList            *known_indicators;
+  GList            *li, *li_int, *li_tmp;
 
   /* run callback for all children */
-  for (li = box->children; li != NULL; li = lnext)
+  known_indicators = indicator_config_get_known_indicators (box->config);
+  for (li = known_indicators; li != NULL; li = li->next)
+    {
+      li_int = g_hash_table_lookup (box->children, li->data);
+      for (li_tmp = li_int; li_tmp != NULL; li_tmp = li_tmp->next)
+        {
+          (*callback) (GTK_WIDGET (li_tmp->data), callback_data);
+        }
+    }
+  li_int = g_hash_table_lookup (box->children, "<placeholder>");
+  for (li_tmp = li_int; li_tmp != NULL; li_tmp = li_tmp->next)
     {
-      lnext = li->next;
-      (*callback) (GTK_WIDGET (li->data), callback_data);
+      (*callback) (GTK_WIDGET (li_tmp->data), callback_data);
     }
 }
 
@@ -342,68 +298,96 @@ xfce_indicator_box_forall (GtkContainer *container,
 static GType
 xfce_indicator_box_child_type (GtkContainer *container)
 {
-  return GTK_TYPE_WIDGET;
+  return XFCE_TYPE_INDICATOR_BUTTON;
 }
 
 
 
+static gint
+xfce_indicator_box_get_row_size (XfceIndicatorBox *box)
+{
+  gint                 border_thickness;
+  GtkStyle            *style;
+
+  g_return_val_if_fail (XFCE_IS_INDICATOR_BOX (box), 24);
+
+  style = gtk_widget_get_style (GTK_WIDGET (box));
+  border_thickness = 2 * MAX (style->xthickness, style->ythickness) + 2;
+
+  return MIN (indicator_config_get_panel_size (box->config) /
+              indicator_config_get_nrows (box->config),
+              indicator_config_get_icon_size_max (box->config) + border_thickness);
+}
+
+
+
+
+
 static void
 xfce_indicator_box_size_request (GtkWidget      *widget,
                                  GtkRequisition *requisition)
 {
-  XfceIndicatorBox *box = XFCE_INDICATOR_BOX (widget);
-  GtkWidget        *child;
-  GtkRequisition    child_req;
-  GSList           *li;
-  gint              panel_size;
-  gint              length;
-  gint              row;
-  gint              nrows;
-  gint              x;
-  gboolean          has_label;
-
-  panel_size = box->panel_size;
+  XfceIndicatorBox    *box = XFCE_INDICATOR_BOX (widget);
+  XfceIndicatorButton *button;
+  GtkRequisition       child_req;
+  GList               *known_indicators, *li, *li_int, *li_tmp;
+  gint                 panel_size;
+  gint                 length;
+  gint                 row;
+  gint                 nrows;
+  gint                 x;
+  gboolean             has_label, rectangular_icon;
+  GtkOrientation       panel_orientation;
+
+  panel_size = indicator_config_get_panel_size (box->config);
+  panel_orientation = indicator_config_get_panel_orientation (box->config);
   row = 0;
   length = 0;
   x = 0;
-  //nrows = MAX (box->nrows,
-  //             box->panel_size / xfce_indicator_box_get_row_size (box));
-  nrows = box->panel_size / xfce_indicator_box_get_row_size (box);
+  nrows = panel_size / xfce_indicator_box_get_row_size (box);
 
-  for (li = box->children; li != NULL; li = li->next)
+  if (g_hash_table_lookup (box->children, "<placeholder>") != NULL)
+    known_indicators = g_list_append (NULL, "<placeholder>");
+  else
+    known_indicators = indicator_config_get_known_indicators (box->config);
+  for (li = known_indicators; li != NULL; li = li->next)
     {
-      child = GTK_WIDGET (li->data);
-      g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child));
+      li_int = g_hash_table_lookup (box->children, li->data);
+      for (li_tmp = li_int; li_tmp != NULL; li_tmp = li_tmp->next)
+        {
+          button = XFCE_INDICATOR_BUTTON (li_tmp->data);
 
-      gtk_widget_size_request (child, &child_req);
-      has_label = (xfce_indicator_button_get_label (XFCE_INDICATOR_BUTTON (child)) != NULL);
+          gtk_widget_size_request (GTK_WIDGET (button), &child_req);
+          has_label = (xfce_indicator_button_get_label (button) != NULL);
+          rectangular_icon = xfce_indicator_button_is_icon_rectangular (button);
 
-      /* wrap rows if column is overflowing or a label is encountered */
-      if (row > 0 && (has_label || row >= nrows))
-        {
-          x += length;
-          row = 0;
-          length = 0;
-        }
+          /* wrap rows if column is overflowing or a label is encountered */
+          if (row > 0 && (has_label || row >= nrows || rectangular_icon))
+            {
+              x += length;
+              row = 0;
+              length = 0;
+            }
 
-      length =
-        MAX (length, (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL) ? child_req.width :child_req.height);
+          length =
+            MAX (length, (panel_orientation == GTK_ORIENTATION_HORIZONTAL) ? child_req.width :child_req.height);
 
-      if (has_label || row >= nrows)
-        {
-          x += length;
-          row = 0;
-          length = 0;
-        }
-      else
-        {
-          row += 1;
+          if (has_label || row >= nrows || rectangular_icon)
+            {
+              x += length;
+              row = 0;
+              length = 0;
+            }
+          else
+            {
+              row += 1;
+            }
         }
     }
 
   x += length;
 
-  if (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL)
+  if (panel_orientation == GTK_ORIENTATION_HORIZONTAL)
     {
       requisition->width = x;
       requisition->height = panel_size;
@@ -422,18 +406,19 @@ static void
 xfce_indicator_box_size_allocate (GtkWidget     *widget,
                                   GtkAllocation *allocation)
 {
-  XfceIndicatorBox *box = XFCE_INDICATOR_BOX (widget);
-  GtkWidget        *child;
-  GtkAllocation     child_alloc;
-  GtkRequisition    child_req;
-  gint              panel_size, size;
-  gint              x, y;
-  gint              x0, y0;
-  GSList           *li;
-  gint              length, width;
-  gint              row;
-  gint              nrows;
-  gboolean          has_label;
+  XfceIndicatorBox    *box = XFCE_INDICATOR_BOX (widget);
+  XfceIndicatorButton *button;
+  GtkAllocation        child_alloc;
+  GtkRequisition       child_req;
+  gint                 panel_size, size;
+  gint                 x, y;
+  gint                 x0, y0;
+  GList               *known_indicators, *li, *li_int, *li_tmp;
+  gint                 length, width;
+  gint                 row;
+  gint                 nrows;
+  gboolean             has_label, rectangular_icon;
+  GtkOrientation       panel_orientation;
 
   row = 0;
   length = 0;
@@ -442,80 +427,101 @@ xfce_indicator_box_size_allocate (GtkWidget     *widget,
   x0 = allocation->x;
   y0 = allocation->y;
 
-  //nrows = MAX (box->nrows, box->panel_size / box->icon_size_max);
-  nrows = box->panel_size / xfce_indicator_box_get_row_size (box);
-  panel_size = box->panel_size;
+  panel_size = indicator_config_get_panel_size (box->config);
+  panel_orientation = indicator_config_get_panel_orientation (box->config);
+  nrows = panel_size / xfce_indicator_box_get_row_size (box);
   size = panel_size / nrows;
 
-  for (li = box->children; li != NULL; li = li->next)
+  if (g_hash_table_lookup (box->children, "<placeholder>") != NULL)
+    known_indicators = g_list_append (NULL, "<placeholder>");
+  else
+    known_indicators = indicator_config_get_known_indicators (box->config);
+  for (li = known_indicators; li != NULL; li = li->next)
     {
-      child = GTK_WIDGET (li->data);
-      g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (child));
+      li_int = g_hash_table_lookup (box->children, li->data);
+      for (li_tmp = li_int; li_tmp != NULL; li_tmp = li_tmp->next)
+        {
+          button = XFCE_INDICATOR_BUTTON (li_tmp->data);
 
-      gtk_widget_get_child_requisition (child, &child_req);
+          gtk_widget_get_child_requisition (GTK_WIDGET (button), &child_req);
 
-      has_label = (xfce_indicator_button_get_label (XFCE_INDICATOR_BUTTON (child)) != NULL);
+          has_label = (xfce_indicator_button_get_label (button) != NULL);
+          rectangular_icon = xfce_indicator_button_is_icon_rectangular (button);
 
-      /* wrap rows if column is overflowing or a label is encountered */
-      if (row > 0 && (has_label || row >= nrows))
-        {
-          x += length;
-          y = 0;
-          row = 0;
-          length = 0;
-        }
+          /* wrap rows if column is overflowing or a label is encountered */
+          if (row > 0 && (has_label || row >= nrows || rectangular_icon))
+            {
+              x += length;
+              y = 0;
+              row = 0;
+              length = 0;
+            }
 
-      width = (has_label) ? panel_size : size;
-      length = MAX (length,
-                    (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL) ? child_req.width :child_req.height);
+          width = (has_label || rectangular_icon) ? panel_size : size;
+          length = MAX (length,
+                        (panel_orientation == GTK_ORIENTATION_HORIZONTAL) ? child_req.width :child_req.height);
 
-      if (box->panel_orientation == GTK_ORIENTATION_HORIZONTAL)
-        {
-          child_alloc.x = x0 + x;
-          child_alloc.y = y0 + y;
-          child_alloc.width = length;
-          child_alloc.height = width;
-        }
-      else
-        {
-          child_alloc.x = x0 + y;
-          child_alloc.y = y0 + x;
-          child_alloc.width = width;
-          child_alloc.height = length;
-        }
+          if (panel_orientation == GTK_ORIENTATION_HORIZONTAL)
+            {
+              child_alloc.x = x0 + x;
+              child_alloc.y = y0 + y;
+              child_alloc.width = length;
+              child_alloc.height = width;
+            }
+          else
+            {
+              child_alloc.x = x0 + y;
+              child_alloc.y = y0 + x;
+              child_alloc.width = width;
+              child_alloc.height = length;
+            }
 
-      /* g_debug ("indicator-box size allocate: x=%d y=%d w=%d h=%d", */
-      /*          child_alloc.x, child_alloc.y, child_alloc.width, child_alloc.height); */
+          /* g_debug ("indicator-box size allocate: x=%d y=%d w=%d h=%d", */
+          /*          child_alloc.x, child_alloc.y, child_alloc.width, child_alloc.height); */
 
-      gtk_widget_size_allocate (child, &child_alloc);
+          gtk_widget_size_allocate (GTK_WIDGET (button), &child_alloc);
 
-      if (has_label || row >= nrows)
-        {
-          x += length;
-          y = 0;
-          row = 0;
-          length = 0;
-        }
-      else
-        {
-          row += 1;
-          y += size;
+          if (has_label || row >= nrows || rectangular_icon)
+            {
+              x += length;
+              y = 0;
+              row = 0;
+              length = 0;
+            }
+          else
+            {
+              row += 1;
+              y += size;
+            }
         }
     }
 }
 
 
 
-static gint
-xfce_indicator_box_get_row_size (XfceIndicatorBox *box)
+void
+xfce_indicator_box_remove_entry (XfceIndicatorBox     *box,
+                                 IndicatorObjectEntry *entry)
 {
-  gint                 border_thickness;
-  GtkStyle            *style;
-
-  g_return_val_if_fail (XFCE_IS_INDICATOR_BOX (box), 24);
+  GList               *known_indicators, *li, *li_int, *li_tmp;
+  XfceIndicatorButton *button;
 
-  style = gtk_widget_get_style (GTK_WIDGET (box));
-  border_thickness = 2 * MAX (style->xthickness, style->ythickness) + 2;
+  g_return_if_fail (XFCE_IS_INDICATOR_BOX (box));
 
-  return MIN (box->panel_size / box->nrows, box->icon_size_max + border_thickness);
+  known_indicators = indicator_config_get_known_indicators (box->config);
+  for (li = known_indicators; li != NULL; li = li->next)
+    {
+      li_int = g_hash_table_lookup (box->children, li->data);
+      for (li_tmp = li_int; li_tmp != NULL; li_tmp = li_tmp->next)
+        {
+          button = XFCE_INDICATOR_BUTTON (li_tmp->data);
+          if (xfce_indicator_button_get_entry (button) == entry)
+            {
+              xfce_indicator_button_disconnect_signals (button);
+              gtk_widget_destroy (GTK_WIDGET (button));
+              return;
+            }
+        }
+    }
 }
+
diff --git a/panel-plugin/indicator-box.h b/panel-plugin/indicator-box.h
index b28c9d2..8647e04 100644
--- a/panel-plugin/indicator-box.h
+++ b/panel-plugin/indicator-box.h
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2012 Andrzej <ndrwrdck at gmail.com>
+/*  Copyright (c) 2012-2013 Andrzej <ndrwrdck at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -18,6 +18,12 @@
 #ifndef __INDICATOR_BOX_H__
 #define __INDICATOR_BOX_H__
 
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libindicator/indicator-object.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include "indicator-config.h"
+
 G_BEGIN_DECLS
 
 GType xfce_indicator_box_get_type (void);
@@ -32,34 +38,10 @@ GType xfce_indicator_box_get_type (void);
 typedef struct _XfceIndicatorBox XfceIndicatorBox;
 typedef struct _XfceIndicatorBoxClass XfceIndicatorBoxClass;
 
-struct _XfceIndicatorBox
-{
-  GtkContainer          __parent__;
-
-  GSList               *children;
-
-  gint                  panel_size;
-  gint                  nrows;
-  gint                  icon_size_max;
-
-  GtkOrientation        panel_orientation;
-  GtkOrientation        orientation;
-};
-
-struct _XfceIndicatorBoxClass
-{
-  GtkContainerClass __parent__;
-};
-
-void xfce_indicator_box_set_orientation (XfceIndicatorBox *button,
-                                         GtkOrientation panel_orientation,
-                                         GtkOrientation orientation);
-
-void xfce_indicator_box_set_size (XfceIndicatorBox *button,
-                                  gint panel_size,
-                                  gint nrows);
+void xfce_indicator_box_remove_entry (XfceIndicatorBox     *box,
+                                      IndicatorObjectEntry *entry);
 
-GtkWidget *xfce_indicator_box_new ();
+GtkWidget       *xfce_indicator_box_new                       (IndicatorConfig        *config);
 
 G_END_DECLS
 
diff --git a/panel-plugin/indicator-button.c b/panel-plugin/indicator-button.c
index 6bca0c8..b24606a 100644
--- a/panel-plugin/indicator-button.c
+++ b/panel-plugin/indicator-button.c
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2012 Andrzej <ndrwrdck at gmail.com>
+/*  Copyright (c) 2012-2013 Andrzej <ndrwrdck at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -15,6 +15,16 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+
+
+/*
+ *  This file implements an indicator button class corresponding to
+ *  a single indicator object entry.
+ *
+ */
+
+
+
 #include <glib.h>
 #include <gtk/gtk.h>
 #include <libxfce4panel/libxfce4panel.h>
@@ -22,7 +32,53 @@
 
 #include "indicator-button.h"
 
-static void                 xfce_indicator_button_finalize     (GObject *object);
+
+#include <libindicator/indicator-object.h>
+//#ifndef INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED
+//#define INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED "scroll-entry"
+//#endif
+
+
+static void                 xfce_indicator_button_finalize        (GObject                *object);
+static gint                 xfce_indicator_button_get_icon_size   (XfceIndicatorButton    *button);
+static gboolean             xfce_indicator_button_button_press    (GtkWidget              *widget,
+                                                                   GdkEventButton         *event);
+static gboolean             xfce_indicator_button_scroll          (GtkWidget              *widget,
+                                                                   GdkEventScroll         *event);
+static void                 xfce_indicator_button_menu_deactivate (XfceIndicatorButton    *button,
+                                                                   GtkMenu                *menu);
+static gint                 xfce_indicator_button_get_size        (XfceIndicatorButton    *button);
+
+
+
+struct _XfceIndicatorButton
+{
+  GtkToggleButton       __parent__;
+
+  IndicatorObject      *io;
+  const gchar          *io_name;
+  IndicatorObjectEntry *entry;
+  GtkMenu              *menu;
+  XfcePanelPlugin      *plugin;
+  IndicatorConfig      *config;
+
+  GtkWidget            *align_box;
+  GtkWidget            *box;
+  GtkWidget            *label;
+  GtkWidget            *icon;
+  GtkWidget            *orig_icon;
+  gboolean              rectangular_icon;
+
+  gulong                orig_icon_changed_id;
+  gulong                configuration_changed_id;
+};
+
+struct _XfceIndicatorButtonClass
+{
+  GtkToggleButtonClass __parent__;
+};
+
+
 
 
 G_DEFINE_TYPE (XfceIndicatorButton, xfce_indicator_button, GTK_TYPE_TOGGLE_BUTTON)
@@ -30,10 +86,16 @@ G_DEFINE_TYPE (XfceIndicatorButton, xfce_indicator_button, GTK_TYPE_TOGGLE_BUTTO
 static void
 xfce_indicator_button_class_init (XfceIndicatorButtonClass *klass)
 {
-  GObjectClass   *gobject_class;
+  GObjectClass      *gobject_class;
+  GtkWidgetClass    *widget_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = xfce_indicator_button_finalize;
+
+  widget_class = GTK_WIDGET_CLASS (klass);
+  widget_class->button_press_event = xfce_indicator_button_button_press;
+  widget_class->scroll_event = xfce_indicator_button_scroll;
+
 }
 
 
@@ -41,8 +103,6 @@ xfce_indicator_button_class_init (XfceIndicatorButtonClass *klass)
 static void
 xfce_indicator_button_init (XfceIndicatorButton *button)
 {
-  GtkWidget   *outer_container;
-
   GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (button), GTK_CAN_DEFAULT | GTK_CAN_FOCUS);
   gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
   gtk_button_set_use_underline (GTK_BUTTON (button),TRUE);
@@ -51,27 +111,23 @@ xfce_indicator_button_init (XfceIndicatorButton *button)
 
   button->io = NULL;
   button->entry = NULL;
+  button->plugin = NULL;
+  button->config = NULL;
   button->menu = NULL;
 
   button->label = NULL;
   button->orig_icon = NULL;
   button->icon = NULL;
-  button->orig_icon_handler = 0;
-
-  button->size = 0;
-  button->panel_size = 0;
-  button->icon_size = 24;
-  button->panel_orientation = GTK_ORIENTATION_HORIZONTAL;
-  button->orientation = GTK_ORIENTATION_HORIZONTAL;
-
-  outer_container = gtk_table_new (1, 1, FALSE);
-  gtk_container_add (GTK_CONTAINER (button), outer_container);
-  gtk_widget_show (outer_container);
-
-  button->box = xfce_hvbox_new (button->orientation, FALSE, 1);
-  gtk_table_attach (GTK_TABLE (outer_container), button->box,
-                    0, 1, 0, 1,
-                    GTK_EXPAND | GTK_SHRINK, GTK_EXPAND | GTK_SHRINK, 0, 0);
+  button->orig_icon_changed_id = 0;
+  button->configuration_changed_id = 0;
+  button->rectangular_icon = FALSE;
+
+  button->align_box = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+  gtk_container_add (GTK_CONTAINER (button), button->align_box);
+  gtk_widget_show (button->align_box);
+
+  button->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 1);
+  gtk_container_add (GTK_CONTAINER (button->align_box), button->box);
   gtk_widget_show (button->box);
 }
 
@@ -82,6 +138,8 @@ xfce_indicator_button_finalize (GObject *object)
 {
   XfceIndicatorButton *button = XFCE_INDICATOR_BUTTON (object);
 
+  xfce_indicator_button_disconnect_signals (button);
+
   if (button->label != NULL)
     g_object_unref (G_OBJECT (button->label));
   if (button->orig_icon != NULL)
@@ -105,45 +163,78 @@ static void
 xfce_indicator_button_update_layout (XfceIndicatorButton *button)
 {
   GtkRequisition          label_size;
+  gfloat                  align_x;
 
   g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
 
-  if (button->icon != NULL && button->size != 0)
+  if (button->label != NULL)
+    gtk_label_set_ellipsize (GTK_LABEL (button->label), PANGO_ELLIPSIZE_NONE);
+
+  /* deskbar mode? */
+  if (button->label != NULL &&
+      indicator_config_get_panel_orientation (button->config) == GTK_ORIENTATION_VERTICAL &&
+      indicator_config_get_orientation (button->config) == GTK_ORIENTATION_HORIZONTAL)
     {
-      if (button->label != NULL &&
-          button->panel_orientation == GTK_ORIENTATION_VERTICAL &&
-          button->orientation == GTK_ORIENTATION_HORIZONTAL)
+      gtk_widget_size_request (button->label, &label_size);
+
+      /* check if icon and label fit side by side */
+      if (!indicator_config_get_align_left (button->config)
+          || (button->icon != NULL
+              && label_size.width >
+              indicator_config_get_panel_size (button->config)
+              - xfce_indicator_button_get_size (button)))
+        {
+          align_x = 0.5;
+          gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), GTK_ORIENTATION_VERTICAL);
+        }
+      else
         {
-          gtk_widget_size_request (button->label, &label_size);
-
-          /* put icon above the label if number of rows > 1 (they look better)
-             or if they don't fit when arranged horizontally */
-          if (button->panel_size != button->size ||
-              label_size.width > button->panel_size - button->size)
-            gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), GTK_ORIENTATION_VERTICAL);
-          else
-            gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), GTK_ORIENTATION_HORIZONTAL);
+          align_x = 0.0;
+          gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), GTK_ORIENTATION_HORIZONTAL);
         }
 
-      xfce_panel_image_set_size (XFCE_PANEL_IMAGE (button->icon), button->icon_size);
+      /* check if label alone fits in the panel */
+      if (label_size.width > indicator_config_get_panel_size (button->config) - 6)
+        {
+          gtk_alignment_set (GTK_ALIGNMENT (button->align_box), align_x, 0.5, 1.0, 0.0);
+          gtk_label_set_ellipsize (GTK_LABEL (button->label), PANGO_ELLIPSIZE_END);
+        }
+      else
+        {
+          gtk_alignment_set (GTK_ALIGNMENT (button->align_box), align_x, 0.5, 0.0, 0.0);
+        }
     }
+  else
+    {
+      gtk_alignment_set (GTK_ALIGNMENT (button->align_box), 0.5, 0.5, 0.0, 0.0);
+      gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box),
+                                      indicator_config_get_orientation (button->config));
+    }
+
+
+  if (button->label != NULL)
+    gtk_label_set_angle (GTK_LABEL (button->label),
+                         (indicator_config_get_orientation (button->config) == GTK_ORIENTATION_VERTICAL)
+                         ? -90 : 0);
 }
 
 
 
+
 static void
 xfce_indicator_button_update_icon (XfceIndicatorButton *button)
 {
   GdkPixbuf    *pixbuf_s, *pixbuf_d;
   gdouble       aspect;
-  gint          size;
+  gint          w, h, size;
+  gint          border_thickness;
+  GtkStyle     *style;
 
   g_return_if_fail (GTK_IS_IMAGE (button->orig_icon));
-  g_return_if_fail (XFCE_IS_PANEL_IMAGE (button->icon));
+  g_return_if_fail (GTK_IS_IMAGE (button->icon));
 
-  size = button->icon_size;
+  size = xfce_indicator_button_get_icon_size (button);
 
-  /* Copied from xfce_panel_image.c, try to snap to icon sizes, which minimize smoothing */
 #if 0
   if (size > 16 && size < 22)
     size = 16;
@@ -157,24 +248,44 @@ xfce_indicator_button_update_icon (XfceIndicatorButton *button)
 
   if (pixbuf_s != NULL)
     {
-      aspect = (gdouble) gdk_pixbuf_get_width (pixbuf_s) /
-        (gdouble) gdk_pixbuf_get_height (pixbuf_s);
-      if (aspect > 1.0)
-        pixbuf_d = gdk_pixbuf_scale_simple
-          (pixbuf_s, size, (gint) (size / aspect),
-           GDK_INTERP_BILINEAR);
+      w = gdk_pixbuf_get_width (pixbuf_s);
+      h = gdk_pixbuf_get_height (pixbuf_s);
+      aspect = (gdouble) w / (gdouble) h;
+
+      button->rectangular_icon = (w != h);
+
+      if (indicator_config_get_panel_orientation (button->config) == GTK_ORIENTATION_VERTICAL &&
+          size * aspect > indicator_config_get_panel_size (button->config))
+        {
+          style = gtk_widget_get_style (GTK_WIDGET (button->plugin));
+          border_thickness = 2 * MAX (style->xthickness, style->ythickness);
+          w = indicator_config_get_panel_size (button->config) - border_thickness;
+          h = (gint) (w / aspect);
+        }
       else
-        pixbuf_d = gdk_pixbuf_scale_simple
-          (pixbuf_s, (gint) (size * aspect), size,
-           GDK_INTERP_BILINEAR);
-      xfce_panel_image_set_from_pixbuf (XFCE_PANEL_IMAGE (button->icon), pixbuf_d);
+        {
+          h = size;
+          w = (gint) (h * aspect);
+        }
+      pixbuf_d = gdk_pixbuf_scale_simple (pixbuf_s, w, h, GDK_INTERP_BILINEAR);
+      gtk_image_set_from_pixbuf (GTK_IMAGE (button->icon), pixbuf_d);
+      g_object_unref (G_OBJECT (pixbuf_d));
     }
   else
     {
-      xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (button->icon), "image-missing");
+      gtk_image_set_from_icon_name (GTK_IMAGE (button->icon),
+                                    "image-missing", GTK_ICON_SIZE_MENU);
     }
+}
 
-  xfce_panel_image_set_size (XFCE_PANEL_IMAGE (button->icon), button->icon_size);
+
+
+static void
+xfce_indicator_button_label_changed (GtkLabel            *label,
+                                     GParamSpec          *pspec,
+                                     XfceIndicatorButton *button)
+{
+  xfce_indicator_button_update_layout (button);
 }
 
 
@@ -199,6 +310,7 @@ xfce_indicator_button_set_label (XfceIndicatorButton *button,
       gtk_label_set_angle (GTK_LABEL (button->label),
                            (button->orientation == GTK_ORIENTATION_VERTICAL) ? -90 : 0);
       gtk_box_pack_end (GTK_BOX (button->box), button->label, TRUE, FALSE, 1);
+      g_signal_connect(G_OBJECT(button->label), "notify::label", G_CALLBACK(xfce_indicator_button_label_changed), button);
     }
   xfce_indicator_button_update_layout (button);
 }
@@ -209,11 +321,9 @@ xfce_indicator_button_set_label (XfceIndicatorButton *button,
 static void
 on_pixbuf_changed (GtkImage *image, GParamSpec *pspec, XfceIndicatorButton *button)
 {
-  GdkPixbuf     *pixbuf;
-
   g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
   g_return_if_fail (GTK_IS_IMAGE (image));
-  g_return_if_fail (XFCE_IS_PANEL_IMAGE (button->icon));
+  g_return_if_fail (GTK_IS_IMAGE (button->icon));
 
   xfce_indicator_button_update_icon (button);
 }
@@ -224,8 +334,6 @@ void
 xfce_indicator_button_set_image (XfceIndicatorButton *button,
                                  GtkImage            *image)
 {
-  GdkPixbuf     *pixbuf;
-
   g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
   g_return_if_fail (GTK_IS_IMAGE (image));
 
@@ -235,8 +343,11 @@ xfce_indicator_button_set_image (XfceIndicatorButton *button,
     {
       if (button->orig_icon != NULL)
         {
-          g_signal_handler_disconnect
-            (G_OBJECT (button->orig_icon), button->orig_icon_handler);
+          if (button->orig_icon_changed_id != 0)
+            {
+              g_signal_handler_disconnect (G_OBJECT (button->orig_icon), button->orig_icon_changed_id);
+              button->orig_icon_changed_id = 0;
+            }
           g_object_unref (G_OBJECT (button->orig_icon));
         }
 
@@ -249,11 +360,10 @@ xfce_indicator_button_set_image (XfceIndicatorButton *button,
       button->orig_icon = GTK_WIDGET (image);
       g_object_ref (G_OBJECT (button->orig_icon));
 
-      button->orig_icon_handler = g_signal_connect
+      button->orig_icon_changed_id = g_signal_connect
         (G_OBJECT (image), "notify::pixbuf", G_CALLBACK (on_pixbuf_changed), button);
 
-
-      button->icon = xfce_panel_image_new ();
+      button->icon = gtk_image_new ();
       xfce_indicator_button_update_icon (button);
 
       gtk_box_pack_start (GTK_BOX (button->box), button->icon, TRUE, FALSE, 1);
@@ -278,6 +388,8 @@ xfce_indicator_button_set_menu (XfceIndicatorButton *button,
         g_object_unref (G_OBJECT (button->menu));
       button->menu = menu;
       g_object_ref (G_OBJECT (button->menu));
+      g_signal_connect_swapped (G_OBJECT (button->menu), "deactivate",
+                                G_CALLBACK (xfce_indicator_button_menu_deactivate), button);
       gtk_menu_attach_to_widget(menu, GTK_WIDGET (button), NULL);
     }
 }
@@ -324,6 +436,30 @@ xfce_indicator_button_get_io (XfceIndicatorButton *button)
 
 
 
+const gchar *
+xfce_indicator_button_get_io_name (XfceIndicatorButton *button)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_BUTTON (button), NULL);
+
+  return button->io_name;
+}
+
+
+
+guint
+xfce_indicator_button_get_pos (XfceIndicatorButton *button)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_BUTTON (button), 0);
+
+  return indicator_object_get_location (button->io, button->entry);
+}
+
+
+
+
+
+
+
 GtkMenu *
 xfce_indicator_button_get_menu (XfceIndicatorButton *button)
 {
@@ -334,92 +470,167 @@ xfce_indicator_button_get_menu (XfceIndicatorButton *button)
 
 
 
-void
-xfce_indicator_button_set_orientation (XfceIndicatorButton *button,
-                                       GtkOrientation       panel_orientation,
-                                       GtkOrientation       orientation)
+
+
+gboolean
+xfce_indicator_button_is_icon_rectangular (XfceIndicatorButton *button)
 {
-  gboolean    needs_update = FALSE;
+  g_return_val_if_fail (XFCE_IS_INDICATOR_BUTTON (button), FALSE);
 
-  g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
+  return button->rectangular_icon;
+}
 
-  if (button->orientation != orientation)
-    {
-      button->orientation = orientation;
 
-      if (button->label != NULL)
-        gtk_label_set_angle (GTK_LABEL (button->label),
-                             (orientation == GTK_ORIENTATION_VERTICAL) ? -90 : 0);
-      needs_update = TRUE;
-    }
 
-  if (button->panel_orientation != panel_orientation)
-    {
-      button->panel_orientation = panel_orientation;
-      needs_update = TRUE;
-    }
 
-  if (needs_update)
-    {
-      gtk_orientable_set_orientation (GTK_ORIENTABLE (button->box), orientation);
-      xfce_indicator_button_update_layout (button);
-    }
+static gint
+xfce_indicator_button_get_icon_size (XfceIndicatorButton *button)
+{
+  gint                 indicator_size;
+  gint                 border_thickness;
+  GtkStyle            *style;
+
+  g_return_val_if_fail (XFCE_IS_INDICATOR_BUTTON (button), 22);
+
+  indicator_size = xfce_indicator_button_get_size (button);
+
+  style = gtk_widget_get_style (GTK_WIDGET (button->plugin));
+  border_thickness = 2 * MAX (style->xthickness, style->ythickness);
+
+  return MIN (indicator_size - border_thickness,
+              indicator_config_get_icon_size_max (button->config));
 }
 
 
 
-void
-xfce_indicator_button_set_size (XfceIndicatorButton *button,
-                                gint                 panel_size,
-                                gint                 size)
+static gint
+xfce_indicator_button_get_size (XfceIndicatorButton *button)
 {
-  gboolean    needs_update = FALSE;
-  gint        border_thickness;
-  GtkStyle   *style;
-  gdouble     aspect;
+  gint                 border_thickness;
+  GtkStyle            *style;
 
-  g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
+  g_return_val_if_fail (XFCE_IS_INDICATOR_BUTTON (button), 24);
 
-  if (button->size != size)
-    {
-      button->size = size;
-      needs_update = TRUE;
-    }
+  style = gtk_widget_get_style (GTK_WIDGET (button->plugin));
+  border_thickness = 2 * MAX (style->xthickness, style->ythickness) ;
 
-  if (button->panel_size != panel_size)
-    {
-      button->panel_size = panel_size;
-      needs_update = TRUE;
-    }
+  return MIN (indicator_config_get_panel_size (button->config) /
+              indicator_config_get_nrows (button->config),
+              indicator_config_get_icon_size_max (button->config) + border_thickness);
+}
 
-  if (needs_update)
-    {
-      style = gtk_widget_get_style (GTK_WIDGET (button));
-      border_thickness = 2 * MAX (style->xthickness, style->ythickness) + 2;
-      button->icon_size = button->size - border_thickness;
 
-      if (button->orig_icon != NULL)
-        {
-          xfce_indicator_button_update_icon (button);
-          xfce_indicator_button_update_layout (button);
-        }
-    }
+
+
+static void
+xfce_indicator_configuration_changed (XfceIndicatorButton *button,
+                                      IndicatorConfig     *config)
+{
+  g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+  g_return_if_fail (GTK_WIDGET (button)->parent != NULL);
+
+  if (button->orig_icon != NULL)
+    xfce_indicator_button_update_icon (button);
+  xfce_indicator_button_update_layout (button);
 }
 
 
 
 GtkWidget *
-xfce_indicator_button_new (IndicatorObject *io,
-                           IndicatorObjectEntry *entry)
+xfce_indicator_button_new (IndicatorObject      *io,
+                           const gchar          *io_name,
+                           IndicatorObjectEntry *entry,
+                           XfcePanelPlugin      *plugin,
+                           IndicatorConfig      *config)
 {
   XfceIndicatorButton *button = g_object_new (XFCE_TYPE_INDICATOR_BUTTON, NULL);
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), NULL);
+  g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (plugin), NULL);
+
   button->io = io;
+  button->io_name = io_name;
   button->entry = entry;
+  button->plugin = plugin;
+  button->config = config;
+
   if (button->io != NULL)
     g_object_ref (G_OBJECT (button->io));
   /* IndicatorObjectEntry is not GObject */
   /* g_object_ref (G_OBJECT (button->entry)); */
+
+  button->configuration_changed_id =
+    g_signal_connect_swapped (G_OBJECT (button->config), "configuration-changed",
+                              G_CALLBACK (xfce_indicator_configuration_changed), button);
+
   return GTK_WIDGET (button);
 }
 
 
+
+void
+xfce_indicator_button_disconnect_signals (XfceIndicatorButton *button)
+{
+  g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
+
+  if (button->menu != 0)
+    {
+      gtk_menu_popdown (button->menu);
+    }
+
+  if (button->configuration_changed_id != 0)
+    {
+      g_signal_handler_disconnect (button->config, button->configuration_changed_id);
+      button->configuration_changed_id = 0;
+    }
+
+  if (button->orig_icon_changed_id != 0)
+    {
+      g_signal_handler_disconnect (G_OBJECT (button->orig_icon), button->orig_icon_changed_id);
+      button->orig_icon_changed_id = 0;
+    }
+
+}
+
+
+static gboolean
+xfce_indicator_button_button_press (GtkWidget      *widget,
+                                    GdkEventButton *event)
+{
+  XfceIndicatorButton *button = XFCE_INDICATOR_BUTTON (widget);
+
+  if(event->button == 1 && button->menu != NULL) /* left click only */
+    {
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),TRUE);
+      gtk_menu_reposition (GTK_MENU (button->menu));
+      gtk_menu_popup (button->menu, NULL, NULL,
+                      xfce_panel_plugin_position_menu, button->plugin,
+                      event->button, event->time);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+static gboolean
+xfce_indicator_button_scroll (GtkWidget *widget, GdkEventScroll *event)
+{
+  XfceIndicatorButton *button = XFCE_INDICATOR_BUTTON (widget);
+
+  g_signal_emit_by_name (button->io, INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED,
+                         button->entry, 1, event->direction);
+
+  return TRUE;
+}
+
+
+static void
+xfce_indicator_button_menu_deactivate (XfceIndicatorButton *button,
+                                       GtkMenu             *menu)
+{
+  g_return_if_fail (XFCE_IS_INDICATOR_BUTTON (button));
+  g_return_if_fail (GTK_IS_MENU (menu));
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+}
diff --git a/panel-plugin/indicator-button.h b/panel-plugin/indicator-button.h
index 80e93fb..427d1e6 100644
--- a/panel-plugin/indicator-button.h
+++ b/panel-plugin/indicator-button.h
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2012 Andrzej <ndrwrdck at gmail.com>
+/*  Copyright (c) 2012-2013 Andrzej <ndrwrdck at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -18,6 +18,13 @@
 #ifndef __INDICATOR_BUTTON_H__
 #define __INDICATOR_BUTTON_H__
 
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libindicator/indicator-object.h>
+
+#include "indicator-config.h"
+#include "indicator-box.h"
+
 G_BEGIN_DECLS
 
 GType xfce_indicator_button_get_type (void);
@@ -29,61 +36,42 @@ GType xfce_indicator_button_get_type (void);
 #define XFCE_IS_INDICATOR_BUTTON_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), XFCE_TYPE_INDICATOR_BUTTON))
 #define XFCE_INDICATOR_BUTTON_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), XFCE_TYPE_INDICATOR_BUTTON, XfceIndicatorButtonClass))
 
-typedef struct _XfceIndicatorButton XfceIndicatorButton;
-typedef struct _XfceIndicatorButtonClass XfceIndicatorButtonClass;
-
-struct _XfceIndicatorButton
-{
-  GtkToggleButton       __parent__;
-
-  IndicatorObject      *io;
-  IndicatorObjectEntry *entry;
-  GtkMenu              *menu;
-
-  GtkWidget            *box;
-  GtkWidget            *label;
-  GtkWidget            *icon;
-  GtkWidget            *orig_icon;
-  gulong                orig_icon_handler;
+typedef struct          _XfceIndicatorButton              XfceIndicatorButton;
+typedef struct          _XfceIndicatorButtonClass         XfceIndicatorButtonClass;
 
-  gint                  panel_size;
-  gint                  size;
-  gint                  icon_size;
 
-  GtkOrientation        panel_orientation;
-  GtkOrientation        orientation;
-};
+void                    xfce_indicator_button_set_label   (XfceIndicatorButton        *button,
+                                                           GtkLabel                   *label);
 
-struct _XfceIndicatorButtonClass
-{
-  GtkToggleButtonClass __parent__;
-};
+void                    xfce_indicator_button_set_image   (XfceIndicatorButton        *button,
+                                                           GtkImage                   *image);
 
-void xfce_indicator_button_set_label (XfceIndicatorButton *button, GtkLabel *label);
+void                    xfce_indicator_button_set_menu    (XfceIndicatorButton        *button,
+                                                           GtkMenu                    *menu);
 
-void xfce_indicator_button_set_image (XfceIndicatorButton *button, GtkImage *image);
+GtkWidget              *xfce_indicator_button_get_label   (XfceIndicatorButton        *button);
 
-void xfce_indicator_button_set_menu (XfceIndicatorButton *button, GtkMenu *menu);
+GtkWidget              *xfce_indicator_button_get_image   (XfceIndicatorButton        *button);
 
-GtkWidget *xfce_indicator_button_get_label (XfceIndicatorButton *button);
+IndicatorObjectEntry   *xfce_indicator_button_get_entry   (XfceIndicatorButton        *button);
 
-GtkWidget *xfce_indicator_button_get_image (XfceIndicatorButton *button);
+IndicatorObject        *xfce_indicator_button_get_io      (XfceIndicatorButton        *button);
 
-IndicatorObjectEntry *xfce_indicator_button_get_entry (XfceIndicatorButton *button);
+const gchar            *xfce_indicator_button_get_io_name (XfceIndicatorButton        *button);
 
-IndicatorObject *xfce_indicator_button_get_io (XfceIndicatorButton *button);
+guint                   xfce_indicator_button_get_pos     (XfceIndicatorButton        *button);
 
-GtkMenu *xfce_indicator_button_get_menu (XfceIndicatorButton *button);
+GtkMenu                *xfce_indicator_button_get_menu    (XfceIndicatorButton        *button);
 
-void xfce_indicator_button_set_orientation (XfceIndicatorButton *button,
-                                            GtkOrientation panel_orientation,
-                                            GtkOrientation orientation);
+gboolean                xfce_indicator_button_is_icon_rectangular (XfceIndicatorButton *button);
 
-void xfce_indicator_button_set_size (XfceIndicatorButton *button,
-                                     gint panel_size,
-                                     gint size);
+GtkWidget              *xfce_indicator_button_new         (IndicatorObject            *io,
+                                                           const gchar                *io_name,
+                                                           IndicatorObjectEntry       *entry,
+                                                           XfcePanelPlugin            *plugin,
+                                                           IndicatorConfig            *config);
 
-GtkWidget *xfce_indicator_button_new (IndicatorObject *io, IndicatorObjectEntry *entry);
+void                    xfce_indicator_button_disconnect_signals (XfceIndicatorButton *button);
 
 G_END_DECLS
 
diff --git a/panel-plugin/indicator-config.c b/panel-plugin/indicator-config.c
new file mode 100644
index 0000000..d5f5cda
--- /dev/null
+++ b/panel-plugin/indicator-config.c
@@ -0,0 +1,781 @@
+/*
+ *  Copyright (C) 2013 Andrzej <ndrwrdck at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/*
+ *  This file implements a configuration store. The class extends GObject.
+ *
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <xfconf/xfconf.h>
+#include <exo/exo.h>
+#include <libxfce4panel/xfce-panel-plugin.h>
+
+#include "indicator.h"
+#include "indicator-config.h"
+
+
+
+
+#define DEFAULT_ICON_SIZE_MAX      22
+#define DEFAULT_ALIGN_LEFT         FALSE
+#define DEFAULT_EXCLUDED_MODULES   NULL
+#define DEFAULT_ORIENTATION        GTK_ORIENTATION_HORIZONTAL
+#define DEFAULT_PANEL_ORIENTATION  GTK_ORIENTATION_HORIZONTAL
+#define DEFAULT_PANEL_SIZE         28
+#define DEFAULT_MODE_WHITELIST     FALSE
+
+
+
+
+static void                 indicator_config_finalize       (GObject          *object);
+static void                 indicator_config_get_property   (GObject          *object,
+                                                             guint             prop_id,
+                                                             GValue           *value,
+                                                             GParamSpec       *pspec);
+static void                 indicator_config_set_property   (GObject          *object,
+                                                             guint             prop_id,
+                                                             const GValue     *value,
+                                                             GParamSpec       *pspec);
+
+
+
+struct _IndicatorConfigClass
+{
+  GObjectClass      __parent__;
+};
+
+struct _IndicatorConfig
+{
+  GObject          __parent__;
+
+  gint             icon_size_max;
+  gboolean         align_left;
+  gboolean         mode_whitelist;
+  GHashTable      *blacklist;
+  GHashTable      *whitelist;
+  GList           *known_indicators;
+
+  gchar          **excluded_modules;
+
+  /* not xfconf properties but it is still convenient to have them here */
+  GtkOrientation   orientation;
+  GtkOrientation   panel_orientation;
+  gint             nrows;
+  gint             panel_size;
+};
+
+
+
+enum
+{
+  PROP_0,
+  PROP_ICON_SIZE_MAX,
+  PROP_ALIGN_LEFT,
+  PROP_MODE_WHITELIST,
+  PROP_BLACKLIST,
+  PROP_WHITELIST,
+  PROP_KNOWN_INDICATORS
+};
+
+enum
+{
+  CONFIGURATION_CHANGED,
+  INDICATOR_LIST_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint indicator_config_signals[LAST_SIGNAL] = { 0, };
+
+
+
+
+G_DEFINE_TYPE (IndicatorConfig, indicator_config, G_TYPE_OBJECT)
+
+
+
+
+GType
+indicator_config_value_array_get_type (void)
+{
+  static volatile gsize type__volatile = 0;
+  GType                 type;
+
+  if (g_once_init_enter (&type__volatile))
+    {
+      type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE);
+      g_once_init_leave (&type__volatile, type);
+    }
+
+  return type__volatile;
+}
+
+
+static void
+indicator_config_class_init (IndicatorConfigClass *klass)
+{
+  GObjectClass                 *gobject_class;
+
+  gobject_class               = G_OBJECT_CLASS (klass);
+  gobject_class->finalize     = indicator_config_finalize;
+  gobject_class->get_property = indicator_config_get_property;
+  gobject_class->set_property = indicator_config_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON_SIZE_MAX,
+                                   g_param_spec_uint ("icon-size-max",
+                                                      NULL, NULL,
+                                                      1,
+                                                      128,
+                                                      DEFAULT_ICON_SIZE_MAX,
+                                                      EXO_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                                   PROP_ALIGN_LEFT,
+                                   g_param_spec_boolean ("align-left", NULL, NULL,
+                                                         DEFAULT_ALIGN_LEFT,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_MODE_WHITELIST,
+                                   g_param_spec_boolean ("mode-whitelist", NULL, NULL,
+                                                         DEFAULT_MODE_WHITELIST,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_BLACKLIST,
+                                   g_param_spec_boxed ("blacklist",
+                                                       NULL, NULL,
+                                                       XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY,
+                                                       EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_WHITELIST,
+                                   g_param_spec_boxed ("whitelist",
+                                                       NULL, NULL,
+                                                       XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY,
+                                                       EXO_PARAM_READWRITE));
+
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_KNOWN_INDICATORS,
+                                   g_param_spec_boxed ("known-indicators",
+                                                       NULL, NULL,
+                                                       XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY,
+                                                       EXO_PARAM_READWRITE));
+
+
+  indicator_config_signals[CONFIGURATION_CHANGED] =
+    g_signal_new (g_intern_static_string ("configuration-changed"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  indicator_config_signals[INDICATOR_LIST_CHANGED] =
+    g_signal_new (g_intern_static_string ("indicator-list-changed"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
+
+
+static void
+indicator_config_init (IndicatorConfig *config)
+{
+  config->icon_size_max        = DEFAULT_ICON_SIZE_MAX;
+  config->align_left           = DEFAULT_ALIGN_LEFT;
+  config->mode_whitelist       = DEFAULT_MODE_WHITELIST;
+  config->blacklist            = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  config->whitelist            = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  config->known_indicators     = NULL;
+
+  config->orientation          = DEFAULT_ORIENTATION;
+  config->panel_orientation    = DEFAULT_PANEL_ORIENTATION;
+  config->nrows                = 1;
+  config->panel_size           = DEFAULT_PANEL_SIZE;
+}
+
+
+
+static void
+indicator_config_finalize (GObject *object)
+{
+  IndicatorConfig *config = XFCE_INDICATOR_CONFIG (object);
+
+  xfconf_shutdown();
+
+  g_hash_table_destroy (config->blacklist);
+  g_hash_table_destroy (config->whitelist);
+  g_list_foreach (config->known_indicators, (GFunc) g_free, NULL);
+  g_list_free (config->known_indicators);
+
+  G_OBJECT_CLASS (indicator_config_parent_class)->finalize (object);
+}
+
+
+
+static void
+indicator_config_collect_keys (gpointer key,
+                               gpointer value,
+                               gpointer array)
+{
+  GValue *tmp;
+
+  tmp = g_new0 (GValue, 1);
+  g_value_init (tmp, G_TYPE_STRING);
+  g_value_set_string (tmp, key);
+  g_ptr_array_add (array, tmp);
+}
+
+
+
+static void
+indicator_config_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  IndicatorConfig     *config = XFCE_INDICATOR_CONFIG (object);
+  GPtrArray           *array;
+  GList               *li;
+  GValue              *tmp;
+
+  switch (prop_id)
+    {
+    case PROP_ICON_SIZE_MAX:
+      g_value_set_uint (value, config->icon_size_max);
+      break;
+
+    case PROP_ALIGN_LEFT:
+      g_value_set_boolean (value, config->align_left);
+      break;
+
+    case PROP_MODE_WHITELIST:
+      g_value_set_boolean (value, config->mode_whitelist);
+      break;
+
+    case PROP_BLACKLIST:
+      array = g_ptr_array_new ();
+      g_hash_table_foreach (config->blacklist, indicator_config_collect_keys, array);
+      g_value_set_boxed (value, array);
+      xfconf_array_free (array);
+      break;
+
+    case PROP_WHITELIST:
+      array = g_ptr_array_new ();
+      g_hash_table_foreach (config->whitelist, indicator_config_collect_keys, array);
+      g_value_set_boxed (value, array);
+      xfconf_array_free (array);
+      break;
+
+    case PROP_KNOWN_INDICATORS:
+      array = g_ptr_array_new ();
+      for(li = config->known_indicators; li != NULL; li = li->next)
+        {
+          tmp = g_new0 (GValue, 1);
+          g_value_init (tmp, G_TYPE_STRING);
+          g_value_set_string (tmp, li->data);
+          g_ptr_array_add (array, tmp);
+        }
+      g_value_set_boxed (value, array);
+      xfconf_array_free (array);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+indicator_config_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  IndicatorConfig     *config = XFCE_INDICATOR_CONFIG (object);
+  gint                 val;
+  GPtrArray           *array;
+  const GValue        *tmp;
+  gchar               *name;
+  guint                i;
+
+  switch (prop_id)
+    {
+    case PROP_ICON_SIZE_MAX:
+      val = g_value_get_uint (value);
+      if (config->icon_size_max != val)
+        {
+          config->icon_size_max = val;
+          g_signal_emit (G_OBJECT (config), indicator_config_signals [CONFIGURATION_CHANGED], 0);
+        }
+      break;
+
+    case PROP_ALIGN_LEFT:
+      val = g_value_get_boolean (value);
+      if (config->align_left != val)
+        {
+          config->align_left = val;
+          g_signal_emit (G_OBJECT (config), indicator_config_signals [CONFIGURATION_CHANGED], 0);
+        }
+      break;
+
+    case PROP_MODE_WHITELIST:
+      val = g_value_get_boolean (value);
+      if (config->mode_whitelist != val)
+        {
+          config->mode_whitelist = val;
+          g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+        }
+      break;
+
+    case PROP_BLACKLIST:
+      g_hash_table_remove_all (config->blacklist);
+      array = g_value_get_boxed (value);
+      if (G_LIKELY (array != NULL))
+        {
+          for (i = 0; i < array->len; i++)
+            {
+              tmp = g_ptr_array_index (array, i);
+              g_assert (G_VALUE_HOLDS_STRING (tmp));
+              name = g_value_dup_string (tmp);
+              g_hash_table_replace (config->blacklist, name, name);
+            }
+        }
+      g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+      break;
+
+    case PROP_WHITELIST:
+      g_hash_table_remove_all (config->whitelist);
+      array = g_value_get_boxed (value);
+      if (G_LIKELY (array != NULL))
+        {
+          for (i = 0; i < array->len; i++)
+            {
+              tmp = g_ptr_array_index (array, i);
+              g_assert (G_VALUE_HOLDS_STRING (tmp));
+              name = g_value_dup_string (tmp);
+              g_hash_table_replace (config->whitelist, name, name);
+            }
+        }
+      g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+      break;
+
+    case PROP_KNOWN_INDICATORS:
+      g_list_foreach (config->known_indicators, (GFunc) g_free, NULL);
+      g_list_free (config->known_indicators);
+      config->known_indicators = NULL;
+      array = g_value_get_boxed (value);
+      if (G_LIKELY (array != NULL))
+        {
+          for (i = 0; i < array->len; i++)
+            {
+              tmp = g_ptr_array_index (array, i);
+              g_assert (G_VALUE_HOLDS_STRING (tmp));
+              name = g_value_dup_string (tmp);
+              config->known_indicators = g_list_append (config->known_indicators, name);
+            }
+        }
+      g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+
+gint
+indicator_config_get_icon_size_max (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), DEFAULT_ICON_SIZE_MAX);
+
+  return config->icon_size_max;
+}
+
+
+
+
+gboolean
+indicator_config_get_align_left (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), DEFAULT_ALIGN_LEFT);
+
+  return config->align_left;
+}
+
+
+
+
+void
+indicator_config_set_orientation (IndicatorConfig  *config,
+                                  GtkOrientation    panel_orientation,
+                                  GtkOrientation    orientation)
+{
+  gboolean              needs_update = FALSE;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+
+  if (config->orientation != orientation)
+    {
+      config->orientation = orientation;
+      needs_update = TRUE;
+    }
+
+  if (config->panel_orientation != panel_orientation)
+    {
+      config->panel_orientation = panel_orientation;
+      needs_update = TRUE;
+    }
+
+  if (needs_update)
+    g_signal_emit (G_OBJECT (config), indicator_config_signals[CONFIGURATION_CHANGED], 0);
+}
+
+
+
+GtkOrientation
+indicator_config_get_orientation (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), DEFAULT_ORIENTATION);
+
+  return config->orientation;
+}
+
+
+
+
+GtkOrientation
+indicator_config_get_panel_orientation (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), DEFAULT_PANEL_ORIENTATION);
+
+  return config->panel_orientation;
+}
+
+
+
+
+void
+indicator_config_set_size (IndicatorConfig  *config,
+                           gint              panel_size,
+                           gint              nrows)
+{
+  gboolean              needs_update = FALSE;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+
+  if (config->nrows != nrows)
+    {
+      config->nrows = nrows;
+      needs_update = TRUE;
+    }
+
+  if (config->panel_size != panel_size)
+    {
+      config->panel_size = panel_size;
+      needs_update = TRUE;
+    }
+
+  if (needs_update)
+    g_signal_emit (G_OBJECT (config), indicator_config_signals[CONFIGURATION_CHANGED], 0);
+}
+
+
+
+gint
+indicator_config_get_nrows (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), 1);
+
+  return config->nrows;
+}
+
+
+
+
+gint
+indicator_config_get_panel_size (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), DEFAULT_PANEL_SIZE);
+
+  return config->panel_size;
+}
+
+
+
+
+gchar**
+indicator_config_get_excluded_modules (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), DEFAULT_ALIGN_LEFT);
+
+  return config->excluded_modules;
+}
+
+
+
+
+gboolean
+indicator_config_get_mode_whitelist (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), FALSE);
+
+  return config->mode_whitelist;
+}
+
+
+
+
+gboolean
+indicator_config_is_blacklisted (IndicatorConfig *config,
+                                 const gchar     *name)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), FALSE);
+
+  return g_hash_table_lookup_extended (config->blacklist, name, NULL, NULL);
+}
+
+
+
+
+void
+indicator_config_blacklist_set (IndicatorConfig *config,
+                                const gchar     *name,
+                                gboolean         add)
+{
+  gchar *name_copy;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+  g_return_if_fail (!exo_str_is_empty (name));
+
+  if (add)
+    {
+      name_copy = g_strdup (name);
+      g_hash_table_replace (config->blacklist, name_copy, name_copy);
+    }
+  else
+    {
+      g_hash_table_remove (config->blacklist, name);
+    }
+  g_object_notify (G_OBJECT (config), "blacklist");
+  g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+}
+
+
+
+
+
+void
+indicator_config_whitelist_set (IndicatorConfig *config,
+                                const gchar     *name,
+                                gboolean         add)
+{
+  gchar *name_copy;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+  g_return_if_fail (!exo_str_is_empty (name));
+
+  if (add)
+    {
+      name_copy = g_strdup (name);
+      g_hash_table_replace (config->whitelist, name_copy, name_copy);
+    }
+  else
+    {
+      g_hash_table_remove (config->whitelist, name);
+    }
+  g_object_notify (G_OBJECT (config), "whitelist");
+  g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+}
+
+
+
+
+
+gboolean
+indicator_config_is_whitelisted (IndicatorConfig *config,
+                                 const gchar     *name)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), FALSE);
+
+  return g_hash_table_lookup_extended (config->whitelist, name, NULL, NULL);
+}
+
+
+
+
+GList*
+indicator_config_get_known_indicators (IndicatorConfig *config)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_CONFIG (config), NULL);
+
+  return config->known_indicators;
+}
+
+
+
+
+void
+indicator_config_add_known_indicator (IndicatorConfig *config,
+                                      const gchar     *name)
+{
+  GList    *li;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+  g_return_if_fail (!exo_str_is_empty (name));
+
+  /* check if the indicator is already known */
+  for(li = config->known_indicators; li != NULL; li = li->next)
+    if (g_strcmp0 (li->data, name) == 0)
+      return;
+
+  config->known_indicators = g_list_append (config->known_indicators, g_strdup (name));
+
+  g_object_notify (G_OBJECT (config), "known-indicators");
+  g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+}
+
+
+
+
+void
+indicator_config_swap_known_indicators (IndicatorConfig *config,
+                                        const gchar     *name1,
+                                        const gchar     *name2)
+{
+  GList       *li, *li_tmp;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+  g_return_if_fail (!exo_str_is_empty (name1));
+  g_return_if_fail (!exo_str_is_empty (name2));
+
+  for(li = config->known_indicators; li != NULL; li = li->next)
+    if (g_strcmp0 (li->data, name1) == 0)
+      break;
+
+  /* make sure that the list contains name1 followed by name2 */
+  if (li == NULL || li->next == NULL || g_strcmp0 (li->next->data, name2) != 0)
+    {
+      g_debug("Couldn't swap indicators: %s and %s\n", name1, name2);
+      return;
+    }
+
+  /* li_tmp will contain only the removed element (name2) */
+  li_tmp = li->next;
+  config->known_indicators = g_list_remove_link (config->known_indicators, li_tmp);
+
+  /* not strictly necessary (in testing the list contents was preserved)
+   * but searching for the index again should be safer */
+  for(li = config->known_indicators; li != NULL; li = li->next)
+    if (g_strcmp0 (li->data, name1) == 0)
+      break;
+
+  config->known_indicators = g_list_insert_before (config->known_indicators, li, li_tmp->data);
+  g_list_free (li_tmp);
+
+  g_object_notify (G_OBJECT (config), "known-indicators");
+  g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+}
+
+
+
+
+void
+indicator_config_names_clear (IndicatorConfig *config)
+{
+  g_list_foreach (config->known_indicators, (GFunc) g_free, NULL);
+  g_list_free (config->known_indicators);
+  config->known_indicators = NULL;
+  g_object_notify (G_OBJECT (config), "known-indicators");
+
+  g_hash_table_remove_all (config->blacklist);
+  g_object_notify (G_OBJECT (config), "blacklist");
+
+  g_hash_table_remove_all (config->whitelist);
+  g_object_notify (G_OBJECT (config), "whitelist");
+  g_signal_emit (G_OBJECT (config), indicator_config_signals [INDICATOR_LIST_CHANGED], 0);
+}
+
+
+
+
+IndicatorConfig *
+indicator_config_new (const gchar     *property_base)
+{
+  IndicatorConfig    *config;
+  XfconfChannel      *channel;
+  gchar              *property;
+
+  config = g_object_new (XFCE_TYPE_INDICATOR_CONFIG, NULL);
+
+  if (xfconf_init (NULL))
+    {
+      channel = xfconf_channel_get ("xfce4-panel");
+
+      property = g_strconcat (property_base, "/icon-size-max", NULL);
+      xfconf_g_property_bind (channel, property, G_TYPE_INT, config, "icon-size-max");
+      g_free (property);
+
+      property = g_strconcat (property_base, "/align-left", NULL);
+      xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "align-left");
+      g_free (property);
+
+      property = g_strconcat (property_base, "/mode-whitelist", NULL);
+      xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "mode-whitelist");
+      g_free (property);
+
+      property = g_strconcat (property_base, "/blacklist", NULL);
+      xfconf_g_property_bind (channel, property, XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY, config, "blacklist");
+      g_free (property);
+
+      property = g_strconcat (property_base, "/whitelist", NULL);
+      xfconf_g_property_bind (channel, property, XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY, config, "whitelist");
+      g_free (property);
+
+      property = g_strconcat (property_base, "/known-indicators", NULL);
+      xfconf_g_property_bind (channel, property, XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY, config, "known-indicators");
+      g_free (property);
+
+      g_signal_emit (G_OBJECT (config), indicator_config_signals[CONFIGURATION_CHANGED], 0);
+    }
+
+  return config;
+}
diff --git a/panel-plugin/indicator-config.h b/panel-plugin/indicator-config.h
new file mode 100644
index 0000000..8c820c2
--- /dev/null
+++ b/panel-plugin/indicator-config.h
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (C) 2013 Andrzej <ndrwrdck at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __INDICATOR_CONFIG_H__
+#define __INDICATOR_CONFIG_H__
+
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _IndicatorConfigClass IndicatorConfigClass;
+typedef struct _IndicatorConfig      IndicatorConfig;
+
+#define XFCE_TYPE_INDICATOR_CONFIG             (indicator_config_get_type ())
+#define XFCE_INDICATOR_CONFIG(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_INDICATOR_CONFIG, IndicatorConfig))
+#define XFCE_INDICATOR_CONFIG_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_INDICATOR_CONFIG, IndicatorConfigClass))
+#define XFCE_IS_INDICATOR_CONFIG(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_INDICATOR_CONFIG))
+#define XFCE_IS_INDICATOR_CONFIG_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_INDICATOR_CONFIG))
+#define XFCE_INDICATOR_CONFIG_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_INDICATOR_CONFIG, IndicatorConfigClass))
+
+#define XFCE_TYPE_INDICATOR_CONFIG_VALUE_ARRAY (indicator_config_value_array_get_type ())
+
+typedef struct _IncicatorConfigProperty IndicatorConfigProperty;
+struct _IndicatorConfigProperty
+{
+  const gchar     *property;
+  GType            type;
+};
+
+GType              indicator_config_value_array_get_type    (void) G_GNUC_CONST;
+
+GType              indicator_config_get_type                (void) G_GNUC_CONST;
+
+IndicatorConfig   *indicator_config_new                     (const gchar          *property_base);
+
+void               indicator_config_set_orientation         (IndicatorConfig      *config,
+                                                             GtkOrientation        panel_orientation,
+                                                             GtkOrientation        orientation);
+
+GtkOrientation     indicator_config_get_orientation         (IndicatorConfig      *config);
+
+GtkOrientation     indicator_config_get_panel_orientation   (IndicatorConfig      *config);
+
+void               indicator_config_set_size                (IndicatorConfig      *config,
+                                                             gint                  panel_size,
+                                                             gint                  nrows);
+
+gint               indicator_config_get_nrows               (IndicatorConfig      *config);
+
+gint               indicator_config_get_panel_size          (IndicatorConfig      *config);
+
+gint               indicator_config_get_icon_size_max       (IndicatorConfig      *config);
+
+gboolean           indicator_config_get_align_left          (IndicatorConfig      *config);
+
+gboolean           indicator_config_get_mode_whitelist      (IndicatorConfig      *config);
+
+gboolean           indicator_config_is_blacklisted          (IndicatorConfig      *config,
+                                                             const gchar          *name);
+
+void               indicator_config_blacklist_set           (IndicatorConfig      *config,
+                                                             const gchar          *name,
+                                                             gboolean              add);
+
+gboolean           indicator_config_is_whitelisted          (IndicatorConfig      *config,
+                                                             const gchar          *name);
+
+void               indicator_config_whitelist_set           (IndicatorConfig      *config,
+                                                             const gchar          *name,
+                                                             gboolean              add);
+
+gchar            **indicator_config_get_excluded_modules    (IndicatorConfig      *config);
+
+GList             *indicator_config_get_known_indicators    (IndicatorConfig      *config);
+
+void               indicator_config_add_known_indicator     (IndicatorConfig      *config,
+                                                             const gchar          *name);
+
+void               indicator_config_swap_known_indicators   (IndicatorConfig      *config,
+                                                             const gchar          *name1,
+                                                             const gchar          *name2);
+
+void               indicator_config_names_clear             (IndicatorConfig      *config);
+
+G_END_DECLS
+
+#endif /* !__INDICATOR_CONFIG_H__ */
diff --git a/panel-plugin/indicator-dialog.c b/panel-plugin/indicator-dialog.c
new file mode 100644
index 0000000..39280b5
--- /dev/null
+++ b/panel-plugin/indicator-dialog.c
@@ -0,0 +1,602 @@
+/*
+ *  Copyright (C) 2012-2013 Andrzej <ndrwrdck at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/*
+ *  This file implements a preferences dialog. The class extends GtkBuilder.
+ *
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <exo/exo.h>
+#include <libxfce4panel/xfce-panel-plugin.h>
+
+#include "indicator-dialog.h"
+#include "indicator-dialog_ui.h"
+
+#define PLUGIN_WEBSITE  "http://goodies.xfce.org/projects/panel-plugins/xfce4-indicator-plugin"
+
+#ifdef LIBXFCE4UI_CHECK_VERSION
+#if LIBXFCE4UI_CHECK_VERSION (4,9,0)
+#define HAS_ONLINE_HELP
+#endif
+#endif
+
+
+/* known indicator names */
+static const gchar *pretty_names[][3] =
+{
+  /* raw name,                  pretty name,                                 icon-name(?) */
+  { "libapplication.so",        N_("Application Indicators"),               "application-default-icon" },
+  { "libsoundmenu.so",          N_("Sound Menu"),                           "preferences-desktop-sound" },
+  { "libprintersmenu.so",       N_("Printers Menu"),                        "printer" },
+  { "libpower.so",              N_("Power Management"),                     NULL },
+  { "libappmenu.so",            N_("Application Menus (Global Menu)"),      "menu-editor" },
+  { "libsession.so",            N_("Session Management"),                   NULL },
+  { "libmessaging.so",          N_("Messaging Menu"),                       "indicator-messages" },
+  { "libdatetime.so",           N_("Date and Time"),                        "time-admin" },
+};
+
+
+#define ICON_SIZE     (22)
+
+static void              indicator_dialog_build                  (IndicatorDialog          *dialog);
+static void              indicator_dialog_close_button_clicked   (IndicatorDialog          *dialog,
+                                                                  GtkWidget                *button);
+
+static void              indicator_dialog_help_button_clicked    (IndicatorDialog          *dialog,
+                                                                  GtkWidget                *button);
+
+
+
+struct _IndicatorDialogClass
+{
+  GtkBuilderClass   __parent__;
+};
+
+struct _IndicatorDialog
+{
+  GtkBuilder        __parent__;
+
+  GObject          *dialog;
+  GObject          *store;
+  IndicatorConfig  *config;
+};
+
+
+
+enum
+{
+  COLUMN_PIXBUF,
+  COLUMN_TITLE,
+  COLUMN_HIDDEN,
+  COLUMN_VISIBLE,
+  COLUMN_TIP
+};
+
+
+
+G_DEFINE_TYPE (IndicatorDialog, indicator_dialog, GTK_TYPE_BUILDER)
+
+
+
+static void
+indicator_dialog_class_init (IndicatorDialogClass *klass)
+{
+}
+
+
+
+static void
+indicator_dialog_init (IndicatorDialog *dialog)
+{
+  dialog->dialog = NULL;
+  dialog->store  = NULL;
+  dialog->config = NULL;
+}
+
+
+
+
+static void
+indicator_dialog_add_indicator (IndicatorDialog *dialog,
+                                GdkPixbuf       *pixbuf,
+                                const gchar     *name,
+                                const gchar     *pretty_name,
+                                gboolean         hidden,
+                                gboolean         visible)
+{
+  GtkTreeIter   iter;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+  g_return_if_fail (name == NULL || g_utf8_validate (name, -1, NULL));
+
+  /* insert in the store */
+  gtk_list_store_append (GTK_LIST_STORE (dialog->store), &iter);
+  gtk_list_store_set (GTK_LIST_STORE (dialog->store), &iter,
+                      COLUMN_PIXBUF,  pixbuf,
+                      COLUMN_TITLE,   (pretty_name != NULL) ? pretty_name : name,
+                      COLUMN_HIDDEN,  hidden,
+                      COLUMN_VISIBLE, visible,
+                      COLUMN_TIP,     name,
+                      -1);
+}
+
+
+
+static void
+indicator_dialog_update_indicator_names (IndicatorDialog *dialog)
+{
+  GList        *li;
+  const gchar  *name;
+  const gchar  *pretty_name = NULL;
+  const gchar  *icon_name = NULL;
+  GdkPixbuf    *pixbuf = NULL;
+  guint         i;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (dialog->config));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  for(li = indicator_config_get_known_indicators (dialog->config); li != NULL; li = li->next)
+    {
+      name = li->data;
+
+      /* check if we have a better name for the application */
+      for (i = 0; i < G_N_ELEMENTS (pretty_names); i++)
+        {
+          if (strcmp (name, pretty_names[i][0]) == 0)
+            {
+              pretty_name = pretty_names[i][1];
+              icon_name = pretty_names[i][2];
+              break;
+            }
+        }
+
+      /* try to load the icon name */
+      if (icon_name != NULL)
+        pixbuf = xfce_panel_pixbuf_from_source (icon_name, NULL, ICON_SIZE);
+      else
+        pixbuf = NULL;
+
+      /* insert indicator in the store */
+      indicator_dialog_add_indicator
+        (dialog,
+         pixbuf,
+         name,
+         pretty_name,
+         indicator_config_is_blacklisted (dialog->config, name),
+         indicator_config_is_whitelisted (dialog->config, name));
+    }
+  if (pixbuf != NULL)
+    g_object_unref (G_OBJECT (pixbuf));
+}
+
+
+
+static void
+indicator_dialog_hidden_toggled (GtkCellRendererToggle *renderer,
+                                 const gchar           *path_string,
+                                 IndicatorDialog       *dialog)
+{
+  GtkTreeIter   iter;
+  gboolean      hidden;
+  gchar        *name;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (dialog->config));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dialog->store), &iter, path_string))
+    {
+      gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), &iter,
+                          COLUMN_HIDDEN, &hidden,
+                          COLUMN_TIP, &name, -1);
+
+      /* insert value (we need to update it) */
+      hidden = !hidden;
+
+      /* update box and store with new state */
+      indicator_config_blacklist_set (dialog->config, name, hidden);
+      gtk_list_store_set (GTK_LIST_STORE (dialog->store), &iter, COLUMN_HIDDEN, hidden, -1);
+
+      g_free (name);
+    }
+}
+
+
+
+static void
+indicator_dialog_visible_toggled (GtkCellRendererToggle *renderer,
+                                  const gchar           *path_string,
+                                  IndicatorDialog       *dialog)
+{
+  GtkTreeIter   iter;
+  gboolean      visible;
+  gchar        *name;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (dialog->config));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dialog->store), &iter, path_string))
+    {
+      gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), &iter,
+                          COLUMN_VISIBLE, &visible,
+                          COLUMN_TIP, &name, -1);
+
+      /* insert value (we need to update it) */
+      visible = !visible;
+
+      /* update box and store with new state */
+      indicator_config_whitelist_set (dialog->config, name, visible);
+      gtk_list_store_set (GTK_LIST_STORE (dialog->store), &iter, COLUMN_VISIBLE, visible, -1);
+
+      g_free (name);
+    }
+}
+
+
+
+
+static void
+indicator_dialog_mode_whitelist_toggled (GtkCheckButton        *check_box,
+                                         IndicatorDialog       *dialog)
+{
+  GtkTreeViewColumn *column_visible, *column_hidden;
+  GObject           *treeview;
+  gboolean           mode_whitelist;
+
+  g_return_if_fail (GTK_IS_CHECK_BUTTON (check_box));
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+
+  mode_whitelist = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_box));
+
+  treeview = gtk_builder_get_object (GTK_BUILDER (dialog), "indicators-treeview");
+  g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
+
+  column_visible = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), COLUMN_VISIBLE);
+  column_hidden  = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), COLUMN_HIDDEN);
+
+  gtk_tree_view_column_set_visible (column_visible,  mode_whitelist);
+  gtk_tree_view_column_set_visible (column_hidden,  !mode_whitelist);
+}
+
+
+
+
+static void
+indicator_dialog_swap_rows (IndicatorDialog  *dialog,
+                            GtkTreeIter      *iter_prev,
+                            GtkTreeIter      *iter)
+{
+  GdkPixbuf    *pixbuf1, *pixbuf2;
+  gchar        *name1, *name2;
+  gboolean      hidden1, hidden2;
+  gboolean      visible1, visible2;
+  gchar        *tip1, *tip2;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (dialog->config));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), iter_prev,
+                      COLUMN_PIXBUF,  &pixbuf1,
+                      COLUMN_TITLE,   &name1,
+                      COLUMN_HIDDEN,  &hidden1,
+                      COLUMN_VISIBLE, &visible1,
+                      COLUMN_TIP,     &tip1, -1);
+  gtk_tree_model_get (GTK_TREE_MODEL (dialog->store), iter,
+                      COLUMN_PIXBUF,  &pixbuf2,
+                      COLUMN_TITLE,   &name2,
+                      COLUMN_HIDDEN,  &hidden2,
+                      COLUMN_VISIBLE, &visible2,
+                      COLUMN_TIP,     &tip2, -1);
+  gtk_list_store_set (GTK_LIST_STORE (dialog->store), iter_prev,
+                      COLUMN_PIXBUF,  pixbuf2,
+                      COLUMN_TITLE,   name2,
+                      COLUMN_HIDDEN,  hidden2,
+                      COLUMN_VISIBLE, visible2,
+                      COLUMN_TIP,     tip2, -1);
+  gtk_list_store_set (GTK_LIST_STORE (dialog->store), iter,
+                      COLUMN_PIXBUF,  pixbuf1,
+                      COLUMN_TITLE,   name1,
+                      COLUMN_HIDDEN,  hidden1,
+                      COLUMN_VISIBLE, visible1,
+                      COLUMN_TIP,     tip1, -1);
+
+  /* do a matching operation on IndicatorConfig */
+  indicator_config_swap_known_indicators (dialog->config, tip1, tip2);
+}
+
+
+
+
+
+static gboolean
+indicator_dialog_iter_equal (GtkTreeIter *iter1,
+                             GtkTreeIter *iter2)
+{
+  return (iter1->user_data  == iter2->user_data  &&
+          iter1->user_data2 == iter2->user_data2 &&
+          iter1->user_data3 == iter2->user_data3);
+}
+
+
+
+
+
+static void
+indicator_dialog_item_up_clicked (GtkWidget       *button,
+                                  IndicatorDialog *dialog)
+{
+  GObject            *treeview;
+  GtkTreeSelection   *selection;
+  GtkTreeIter         iter, iter_prev, iter_tmp;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  treeview = gtk_builder_get_object (GTK_BUILDER (dialog), "indicators-treeview");
+  g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+  if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+    return;
+
+  /* gtk_tree_model_iter_previous available from Gtk3 */
+  /* so we have to search for it starting from the first iter */
+  if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->store), &iter_prev))
+    return;
+
+  iter_tmp = iter_prev;
+  while (!indicator_dialog_iter_equal (&iter_tmp, &iter))
+    {
+      iter_prev = iter_tmp;
+      if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->store), &iter_tmp))
+        return;
+    }
+
+  indicator_dialog_swap_rows (dialog, &iter_prev, &iter);
+  gtk_tree_selection_select_iter (selection, &iter_prev);
+}
+
+
+
+
+
+static void
+indicator_dialog_item_down_clicked (GtkWidget       *button,
+                                    IndicatorDialog *dialog)
+{
+  GObject            *treeview;
+  GtkTreeSelection   *selection;
+  GtkTreeIter         iter, iter_next;
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  treeview = gtk_builder_get_object (GTK_BUILDER (dialog), "indicators-treeview");
+  g_return_if_fail (GTK_IS_TREE_VIEW (treeview));
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+  if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+    return;
+
+  iter_next = iter;
+  if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->store), &iter_next))
+    return;
+
+  indicator_dialog_swap_rows (dialog, &iter, &iter_next);
+  gtk_tree_selection_select_iter (selection, &iter_next);
+}
+
+
+
+
+
+static void
+indicator_dialog_clear_clicked (GtkWidget       *button,
+                                IndicatorDialog *dialog)
+{
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (dialog->config));
+  g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+
+  if (xfce_dialog_confirm (GTK_WINDOW (gtk_widget_get_toplevel (button)),
+                           GTK_STOCK_CLEAR, NULL, NULL,
+                           _("Are you sure you want to clear the list of "
+                             "known indicators?")))
+    {
+      gtk_list_store_clear (GTK_LIST_STORE (dialog->store));
+
+      indicator_config_names_clear (dialog->config);
+    }
+}
+
+
+
+
+
+static void
+indicator_dialog_build (IndicatorDialog *dialog)
+{
+  GtkBuilder  *builder = GTK_BUILDER (dialog);
+  GObject     *object;
+  GError      *error = NULL;
+
+  if (xfce_titled_dialog_get_type () == 0)
+    return;
+
+  /* load the builder data into the object */
+  if (gtk_builder_add_from_string (builder, indicator_dialog_ui,
+                                   indicator_dialog_ui_length, &error))
+    {
+
+      dialog->dialog = gtk_builder_get_object (builder, "dialog");
+      g_return_if_fail (XFCE_IS_TITLED_DIALOG (dialog->dialog));
+
+      object = gtk_builder_get_object (builder, "close-button");
+      g_return_if_fail (GTK_IS_BUTTON (object));
+      g_signal_connect_swapped (G_OBJECT (object), "clicked",
+                                G_CALLBACK (indicator_dialog_close_button_clicked),
+                                dialog);
+
+      object = gtk_builder_get_object (builder, "help-button");
+      g_return_if_fail (GTK_IS_BUTTON (object));
+      g_signal_connect_swapped (G_OBJECT (object), "clicked",
+                                G_CALLBACK (indicator_dialog_help_button_clicked),
+                                dialog);
+
+      object = gtk_builder_get_object (builder, "size-max");
+      g_return_if_fail (GTK_IS_WIDGET (object));
+      exo_mutual_binding_new (G_OBJECT (dialog->config), "icon-size-max",
+                              G_OBJECT (object), "value");
+
+      object = gtk_builder_get_object (builder, "checkbutton-align-left");
+      g_return_if_fail (GTK_IS_WIDGET (object));
+      exo_mutual_binding_new (G_OBJECT (dialog->config), "align-left",
+                              G_OBJECT (object), "active");
+
+      object = gtk_builder_get_object (builder, "checkbutton-whitelist");
+      g_return_if_fail (GTK_IS_WIDGET (object));
+      exo_mutual_binding_new (G_OBJECT (dialog->config), "mode-whitelist",
+                              G_OBJECT (object), "active");
+      g_signal_connect (G_OBJECT (object), "toggled",
+                        G_CALLBACK (indicator_dialog_mode_whitelist_toggled), dialog);
+      indicator_dialog_mode_whitelist_toggled (GTK_CHECK_BUTTON (object), dialog);
+
+      dialog->store = gtk_builder_get_object (builder, "indicators-store");
+      g_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
+      indicator_dialog_update_indicator_names (dialog);
+
+      object = gtk_builder_get_object (GTK_BUILDER (dialog), "indicators-treeview");
+      g_return_if_fail (GTK_IS_TREE_VIEW (object));
+      gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (object), COLUMN_TIP);
+
+      object = gtk_builder_get_object (builder, "hidden-toggle");
+      g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (object));
+      g_signal_connect (G_OBJECT (object), "toggled",
+                        G_CALLBACK (indicator_dialog_hidden_toggled), dialog);
+
+      object = gtk_builder_get_object (builder, "visible-toggle");
+      g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (object));
+      g_signal_connect (G_OBJECT (object), "toggled",
+                        G_CALLBACK (indicator_dialog_visible_toggled), dialog);
+
+      object = gtk_builder_get_object (builder, "item-up");
+      g_return_if_fail (GTK_IS_BUTTON (object));
+      g_signal_connect (G_OBJECT (object), "clicked",
+                        G_CALLBACK (indicator_dialog_item_up_clicked), dialog);
+
+      object = gtk_builder_get_object (builder, "item-down");
+      g_return_if_fail (GTK_IS_BUTTON (object));
+      g_signal_connect (G_OBJECT (object), "clicked",
+                        G_CALLBACK (indicator_dialog_item_down_clicked), dialog);
+
+      object = gtk_builder_get_object (builder, "indicators-clear");
+      g_return_if_fail (GTK_IS_BUTTON (object));
+      g_signal_connect (G_OBJECT (object), "clicked",
+                        G_CALLBACK (indicator_dialog_clear_clicked), dialog);
+    }
+  else
+    {
+      g_critical ("Faild to construct the builder: %s.",
+                  error->message);
+      g_error_free (error);
+    }
+}
+
+
+static void
+indicator_dialog_close_button_clicked (IndicatorDialog *dialog,
+                                       GtkWidget       *button)
+{
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (GTK_IS_BUTTON (button));
+  g_return_if_fail (GTK_IS_WINDOW (dialog->dialog));
+
+  gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
+  g_object_unref (G_OBJECT (dialog));
+}
+
+
+static void
+indicator_dialog_help_button_clicked (IndicatorDialog *dialog,
+                                      GtkWidget       *button)
+{
+  //#ifndef HAS_ONLINE_HELP
+  gboolean result;
+  //#endif
+
+  g_return_if_fail (XFCE_IS_INDICATOR_DIALOG (dialog));
+  g_return_if_fail (GTK_IS_BUTTON (button));
+  g_return_if_fail (GTK_IS_WINDOW (dialog->dialog));
+
+  /* Doesn't seem to work */
+  //#ifdef HAS_ONLINE_HELP
+  //xfce_dialog_show_help (GTK_WINDOW (dialog->dialog), "xfce4-indicator", "dialog", NULL);
+  //#else
+
+  result = g_spawn_command_line_async ("exo-open --launch WebBrowser " PLUGIN_WEBSITE, NULL);
+
+  if (G_UNLIKELY (result == FALSE))
+    g_warning (_("Unable to open the following url: %s"), PLUGIN_WEBSITE);
+
+  //#endif
+}
+
+
+
+void
+indicator_dialog_show (GdkScreen       *screen,
+                       IndicatorConfig *config)
+{
+  static IndicatorDialog *dialog = NULL;
+
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (XFCE_IS_INDICATOR_CONFIG (config));
+
+  if (dialog == NULL)
+    {
+      dialog = g_object_new (XFCE_TYPE_INDICATOR_DIALOG, NULL);
+      g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &dialog);
+      dialog->config = config;
+      indicator_dialog_build (XFCE_INDICATOR_DIALOG (dialog));
+      gtk_widget_show (GTK_WIDGET (dialog->dialog));
+    }
+  else
+    {
+      gtk_window_present (GTK_WINDOW (dialog->dialog));
+    }
+
+  gtk_window_set_screen (GTK_WINDOW (dialog->dialog), screen);
+}
diff --git a/panel-plugin/indicator-dialog.glade b/panel-plugin/indicator-dialog.glade
new file mode 100644
index 0000000..69b0f9d
--- /dev/null
+++ b/panel-plugin/indicator-dialog.glade
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.14"/>
+  <!-- interface-requires libxfce4ui 0.0 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="XfceTitledDialog" id="dialog">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Indicators</property>
+    <property name="default_width">425</property>
+    <property name="default_height">525</property>
+    <property name="icon_name">gtk-properties</property>
+    <property name="type_hint">normal</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox2">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="close-button">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="help-button">
+                <property name="label">gtk-help</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">6</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkFrame" id="frame3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="border_width">6</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkHBox" id="hbox1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="spacing">12</property>
+                            <child>
+                              <object class="GtkLabel" id="label2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">_Maximum icon size (px):</property>
+                                <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">size-max</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSpinButton" id="size-max">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip_text" translatable="yes">Icons are scaled to fit a single row of the panel. Use this option to restrict the maximum size of the icon.</property>
+                                <property name="primary_icon_activatable">False</property>
+                                <property name="secondary_icon_activatable">False</property>
+                                <property name="primary_icon_sensitive">True</property>
+                                <property name="secondary_icon_sensitive">True</property>
+                                <property name="adjustment">size-adjustment</property>
+                                <property name="numeric">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="checkbutton-align-left">
+                            <property name="label" translatable="yes">Align left in deskbar mode</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="tooltip_text" translatable="yes">Controls the indicator button layout when the panel is in a Deskbar mode. Possible choices are "centered" or "aligned left".</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Appearance</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="border_width">6</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkCheckButton" id="checkbutton-whitelist">
+                            <property name="label" translatable="yes">Hide indicators by default</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="tooltip_text" translatable="yes">When enabled, only indicators marked "Visible" are shown. Otherwise, all indicators not marked "Hidden" are displayed.</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="hbox2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="hscrollbar_policy">automatic</property>
+                                <property name="vscrollbar_policy">automatic</property>
+                                <property name="shadow_type">in</property>
+                                <child>
+                                  <object class="GtkTreeView" id="indicators-treeview">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="model">indicators-store</property>
+                                    <property name="headers_clickable">False</property>
+                                    <property name="rules_hint">True</property>
+                                    <property name="enable_search">False</property>
+                                    <child>
+                                      <object class="GtkTreeViewColumn" id="treeviewcolumn-icon">
+                                        <property name="min_width">24</property>
+                                        <child>
+                                          <object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1"/>
+                                          <attributes>
+                                            <attribute name="pixbuf">0</attribute>
+                                          </attributes>
+                                        </child>
+                                      </object>
+                                    </child>
+                                    <child>
+                                      <object class="GtkTreeViewColumn" id="treeviewcolumn-name">
+                                        <property name="title">Indicator</property>
+                                        <property name="expand">True</property>
+                                        <child>
+                                          <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                                          <attributes>
+                                            <attribute name="text">1</attribute>
+                                          </attributes>
+                                        </child>
+                                      </object>
+                                    </child>
+                                    <child>
+                                      <object class="GtkTreeViewColumn" id="treeviewcolumn-blacklist">
+                                        <property name="title">Hidden</property>
+                                        <child>
+                                          <object class="GtkCellRendererToggle" id="hidden-toggle"/>
+                                          <attributes>
+                                            <attribute name="active">2</attribute>
+                                          </attributes>
+                                        </child>
+                                      </object>
+                                    </child>
+                                    <child>
+                                      <object class="GtkTreeViewColumn" id="treeviewcolumn-whitelist">
+                                        <property name="title">Visible</property>
+                                        <child>
+                                          <object class="GtkCellRendererToggle" id="visible-toggle"/>
+                                          <attributes>
+                                            <attribute name="active">3</attribute>
+                                          </attributes>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkVBox" id="vbox4">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="spacing">6</property>
+                                <child>
+                                  <object class="GtkButton" id="item-up">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <property name="tooltip_text" translatable="yes">Move the selected indicator one row up.</property>
+                                    <property name="use_action_appearance">False</property>
+                                    <child>
+                                      <object class="GtkImage" id="image2">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="stock">gtk-go-up</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkButton" id="item-down">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <property name="tooltip_text" translatable="yes">Move the selected indicator one row down.</property>
+                                    <property name="use_action_appearance">False</property>
+                                    <child>
+                                      <object class="GtkImage" id="image3">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="stock">gtk-go-down</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="xalign">0</property>
+                            <property name="xpad">20</property>
+                            <property name="ypad">6</property>
+                            <property name="label" translatable="yes"><i>Please restart the panel for visibility changes to take effect.</i></property>
+                            <property name="use_markup">True</property>
+                            <property name="wrap">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHButtonBox" id="hbuttonbox1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="layout_style">start</property>
+                            <child>
+                              <object class="GtkButton" id="indicators-clear">
+                                <property name="label" translatable="yes">C_lear known indicators</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="tooltip_text" translatable="yes">Resets the list of indicators and their visibility settings.</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="image">image1</property>
+                                <property name="use_underline">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Known Indicators</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">close-button</action-widget>
+      <action-widget response="0">help-button</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkImage" id="image1">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="stock">gtk-clear</property>
+  </object>
+  <object class="GtkListStore" id="indicators-store">
+    <columns>
+      <!-- column-name icon -->
+      <column type="GdkPixbuf"/>
+      <!-- column-name title -->
+      <column type="gchararray"/>
+      <!-- column-name hidden -->
+      <column type="gboolean"/>
+      <!-- column-name visible -->
+      <column type="gboolean"/>
+      <!-- column-name tooltip -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkAdjustment" id="size-adjustment">
+    <property name="lower">12</property>
+    <property name="upper">64</property>
+    <property name="value">32</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">2</property>
+  </object>
+</interface>
diff --git a/panel-plugin/indicator-dialog.h b/panel-plugin/indicator-dialog.h
new file mode 100644
index 0000000..6117860
--- /dev/null
+++ b/panel-plugin/indicator-dialog.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2012-2013 Andrzej <ndrwrdck at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __INDICATOR_DIALOG_H__
+#define __INDICATOR_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include "indicator-config.h"
+
+G_BEGIN_DECLS
+
+typedef struct _IndicatorDialogClass IndicatorDialogClass;
+typedef struct _IndicatorDialog      IndicatorDialog;
+
+#define XFCE_TYPE_INDICATOR_DIALOG            (indicator_dialog_get_type ())
+#define XFCE_INDICATOR_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_INDICATOR_DIALOG, IndicatorDialog))
+#define XFCE_INDICATOR_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_INDICATOR_DIALOG, IndicatorDialogClass))
+#define XFCE_IS_INDICATOR_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_INDICATOR_DIALOG))
+#define XFCE_IS_INDICATOR_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_INDICATOR_DIALOG))
+#define XFCE_INDICATOR_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_INDICATOR_DIALOG, IndicatorDialogClass))
+
+GType indicator_dialog_get_type (void) G_GNUC_CONST;
+
+void  indicator_dialog_show     (GdkScreen        *screen,
+                                 IndicatorConfig  *config);
+
+G_END_DECLS
+
+#endif /* !__INDICATOR_DIALOG_H__ */
diff --git a/panel-plugin/indicator.c b/panel-plugin/indicator.c
index e0b2551..26d0ebb 100644
--- a/panel-plugin/indicator.c
+++ b/panel-plugin/indicator.c
@@ -1,4 +1,5 @@
-/*  Copyright (c) 2009 Mark Trompell <mark at foresightlinux.org>
+/*  Copyright (c) 2009      Mark Trompell <mark at foresightlinux.org>
+ *  Copyright (c) 2012-2013 Andrzej <ndrwrdck at gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -15,6 +16,15 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+
+
+/*
+ *  This file implements the main plugin class.
+ *
+ */
+
+
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -26,13 +36,11 @@
 #include <libxfce4util/libxfce4util.h>
 #include <libxfce4panel/xfce-panel-plugin.h>
 #include <libindicator/indicator-object.h>
-#include <xfconf/xfconf.h>
 
 #include "indicator.h"
 #include "indicator-box.h"
 #include "indicator-button.h"
-
-#define DEFAULT_EXCLUDED_MODULES NULL
+#include "indicator-dialog.h"
 
 #ifdef LIBXFCE4PANEL_CHECK_VERSION
 #if LIBXFCE4PANEL_CHECK_VERSION (4,9,0)
@@ -41,189 +49,148 @@
 #endif
 
 /* prototypes */
-static void
-indicator_construct (XfcePanelPlugin *plugin);
-
-static gboolean
-load_module (const gchar * name, IndicatorPlugin * indicator);
-
-static gboolean
-indicator_size_changed (XfcePanelPlugin *plugin, gint size, IndicatorPlugin *indicator);
-
+static void             indicator_construct                        (XfcePanelPlugin       *plugin);
+static void             indicator_free                             (XfcePanelPlugin       *plugin);
+static gboolean         load_module                                (const gchar           *name,
+                                                                    IndicatorPlugin       *indicator);
+static void             indicator_show_about                       (XfcePanelPlugin       *plugin);
+static void             indicator_configure_plugin                 (XfcePanelPlugin       *plugin);
+static gboolean         indicator_size_changed                     (XfcePanelPlugin       *plugin,
+                                                                    gint                   size);
 #ifdef HAS_PANEL_49
-static void
-indicator_mode_changed (XfcePanelPlugin *plugin, XfcePanelPluginMode mode, IndicatorPlugin *indicator);
+static void             indicator_mode_changed                     (XfcePanelPlugin       *plugin,
+                                                                    XfcePanelPluginMode    mode);
 #else
-static void
-indicator_orientation_changed (XfcePanelPlugin *plugin, GtkOrientation orientation, IndicatorPlugin *indicator);
+static void             indicator_orientation_changed              (XfcePanelPlugin       *plugin,
+                                                                    GtkOrientation         orientation);
 #endif
 
 
-/* register the plugin */
-XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL (indicator_construct);
+struct _IndicatorPluginClass
+{
+  XfcePanelPluginClass __parent__;
+};
 
-#if 0
-void
-indicator_save (XfcePanelPlugin *plugin,
-             IndicatorPlugin    *indicator)
+/* plugin structure */
+struct _IndicatorPlugin
 {
-  XfceRc *rc;
-  gchar  *file;
+  XfcePanelPlugin __parent__;
 
-  /* get the config file location */
-  file = xfce_panel_plugin_save_location (plugin, TRUE);
+  /* panel widgets */
+  GtkWidget       *item;
+  GtkWidget       *buttonbox;
 
-  if (G_UNLIKELY (file == NULL))
-    {
-       DBG ("Failed to open config file");
-       return;
-    }
+  /* indicator settings */
+  IndicatorConfig *config;
+};
+
+
+/* define the plugin */
+XFCE_PANEL_DEFINE_PLUGIN (IndicatorPlugin, indicator)
 
-  /* open the config file, read/write */
-  rc = xfce_rc_simple_open (file, FALSE);
-  g_free (file);
 
-  if (G_LIKELY (rc != NULL))
-    {
-      /* save the settings */
-      DBG(".");
-      if (indicator->excluded_modules)
-        xfce_rc_write_list_entry (rc, "Exclude",
-                                  indicator->excluded_modules, NULL);
-
-      /* close the rc file */
-      xfce_rc_close (rc);
-    }
-}
-#endif
 
 
 static void
-indicator_read (IndicatorPlugin *indicator)
+indicator_class_init (IndicatorPluginClass *klass)
 {
-  XfconfChannel * channel = xfconf_channel_get ("xfce4-panel");
-  gchar * property = g_strconcat (xfce_panel_plugin_get_property_base(indicator->plugin),"/blacklist",NULL);
-  indicator->excluded_modules = xfconf_channel_get_string_list(channel, property);
-  g_free (property);
-  property = g_strconcat (xfce_panel_plugin_get_property_base(indicator->plugin),"/icon-size-max",NULL);
-  xfconf_g_property_bind (channel, property, G_TYPE_INT, indicator->buttonbox, "icon-size-max");
-  g_free (property);
-  /* something went wrong, apply default values */
-  /*
-  DBG ("Applying default settings");
-  indicator->excluded_modules = DEFAULT_EXCLUDED_MODULES;
-  */
+  XfcePanelPluginClass *plugin_class;
+
+  plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
+  plugin_class->construct = indicator_construct;
+  plugin_class->free_data = indicator_free;
+  plugin_class->size_changed = indicator_size_changed;
+  plugin_class->about = indicator_show_about;
+  plugin_class->configure_plugin = indicator_configure_plugin;
+#ifdef HAS_PANEL_49
+  plugin_class->mode_changed = indicator_mode_changed;
+#else
+  plugin_class->orientation_changed = indicator_orientation_changed;
+#endif
 }
 
-static IndicatorPlugin *
-indicator_new (XfcePanelPlugin *plugin)
-{
-  IndicatorPlugin   *indicator;
-  GtkOrientation  orientation;
-  gint indicators_loaded = 0;
 
-  /* allocate memory for the plugin structure */
-  indicator = panel_slice_new0 (IndicatorPlugin);
 
-  /* pointer to plugin */
-  indicator->plugin = plugin;
+static void
+indicator_init (IndicatorPlugin *indicator)
+{
+  /* Indicators print a lot of warnings. By default, "wrapper"
+     makes them critical, so the plugin "crashes" when run as an external
+     plugin but not internal one (loaded by "xfce4-panel" itself).
+     The following lines makes only g_error critical. */
+  g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
+}
+
 
-  /* get the current orientation */
-  orientation = xfce_panel_plugin_get_orientation (plugin);
 
-  /* Init some theme/icon stuff */
-  gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
-                                  INDICATOR_ICONS_DIR);
-  /*gtk_widget_set_name(GTK_WIDGET (indicator->plugin), "indicator-plugin");*/
-  
-  indicator->buttonbox = xfce_indicator_box_new ();;
-  /* initialize xfconf */
-  if (xfconf_init(NULL)){
-    /* get the list of excluded modules */
-    indicator_read (indicator);
-  }
-  /* load 'em */
-  if (g_file_test(INDICATOR_DIR, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
-    GDir * dir = g_dir_open(INDICATOR_DIR, 0, NULL);
+static void
+indicator_free (XfcePanelPlugin *plugin)
+{
+  GtkWidget *dialog;
 
-    const gchar * name;
-    guint i, length;
-    gboolean match = FALSE;
- 
-    length = (indicator->excluded_modules != NULL) ? g_strv_length (indicator->excluded_modules) : 0;
-    while ((name = g_dir_read_name(dir)) != NULL) {
-      for (i = 0; i < length; ++i) {
-        if (match = (g_strcmp0 (name, indicator->excluded_modules[i]) == 0))
-          break;
-      }
+  /* check if the dialog is still open. if so, destroy it */
+  dialog = g_object_get_data (G_OBJECT (plugin), "dialog");
+  if (G_UNLIKELY (dialog != NULL))
+    gtk_widget_destroy (dialog);
+}
 
-      if (G_UNLIKELY (match)) {
-        g_debug ("Excluding module: %s", name);
-        continue;
-      }
 
-      if (load_module(name, indicator))
-        indicators_loaded++;
-    }
-    g_dir_close (dir);
-  }
 
-  if (indicators_loaded == 0) {
-    /* A label to allow for click through */
-    indicator->item = xfce_indicator_button_new(NULL, NULL);
-    xfce_indicator_button_set_label(XFCE_INDICATOR_BUTTON(indicator->item),
-                                    GTK_LABEL (gtk_label_new(_("No Indicators"))));
-    gtk_container_add (GTK_CONTAINER (plugin), indicator->item);
-    gtk_widget_show(indicator->item);  
-    /* show the panel's right-click menu on this menu */
-    xfce_panel_plugin_add_action_widget (plugin, indicator->item);
-  } else {
-    indicator->ebox = gtk_event_box_new();
-    gtk_widget_set_can_focus(GTK_WIDGET(indicator->ebox), TRUE);
-    gtk_container_add (GTK_CONTAINER (indicator->ebox), GTK_WIDGET(indicator->buttonbox));
-    gtk_container_add (GTK_CONTAINER (plugin), GTK_WIDGET(indicator->ebox));
-    gtk_widget_show(GTK_WIDGET(indicator->buttonbox));
-    gtk_widget_show(GTK_WIDGET(indicator->ebox));
-    /* show the panel's right-click menu on this menu */
-    xfce_panel_plugin_add_action_widget (plugin, indicator->ebox);
-  }
-  return indicator;
+static void
+indicator_show_about (XfcePanelPlugin *plugin)
+{
+   GdkPixbuf *icon;
+
+   const gchar *auth[] = {
+     "Mark Trompell <mark at foresightlinux.org>", "Andrzej Radecki <ndrwrdck at gmail.com>",
+     "Lionel Le Folgoc <lionel at lefolgoc.net>", "Jason Conti <jconti at launchpad.net>",
+     "Nick Schermer <nick at xfce.org>", "Evgeni Golov <evgeni at debian.org>", NULL };
+
+   g_return_if_fail (XFCE_IS_INDICATOR_PLUGIN (plugin));
+
+   icon = xfce_panel_pixbuf_from_source("xfce4-indicator-plugin", NULL, 32);
+   gtk_show_about_dialog(NULL,
+                         "logo", icon,
+                         "license", xfce_get_license_text (XFCE_LICENSE_TEXT_GPL),
+                         "version", PACKAGE_VERSION,
+                         "program-name", PACKAGE_NAME,
+                         "comments", _("An indicator of something that needs your attention on the desktop"),
+                         "website", "http://goodies.xfce.org/projects/panel-plugins/xfce4-indicator-plugin",
+                         "copyright", _("Copyright (c) 2009-2013\n"),
+                         "authors", auth, NULL);
+
+   if(icon)
+     g_object_unref(G_OBJECT(icon));
 }
 
 
 
 static void
-indicator_free (XfcePanelPlugin *plugin,
-             IndicatorPlugin    *indicator)
+indicator_configure_plugin (XfcePanelPlugin *plugin)
 {
-  GtkWidget *dialog;
+  IndicatorPlugin *indicator = XFCE_INDICATOR_PLUGIN (plugin);
 
-  /* check if the dialog is still open. if so, destroy it */
-  dialog = g_object_get_data (G_OBJECT (plugin), "dialog");
-  if (G_UNLIKELY (dialog != NULL))
-    gtk_widget_destroy (dialog);
-  xfconf_shutdown();
-  /* free the plugin structure */
-  panel_slice_free (IndicatorPlugin, indicator);
+  indicator_dialog_show (gtk_widget_get_screen (GTK_WIDGET (plugin)), indicator->config);
 }
 
 
 
+
 #ifdef HAS_PANEL_49
 static void
 indicator_mode_changed (XfcePanelPlugin     *plugin,
-                        XfcePanelPluginMode  mode,
-                        IndicatorPlugin     *indicator)
+                        XfcePanelPluginMode  mode)
 {
-  GtkOrientation orientation;
-  GtkOrientation panel_orientation = xfce_panel_plugin_get_orientation (plugin);
+  GtkOrientation   orientation;
+  GtkOrientation   panel_orientation = xfce_panel_plugin_get_orientation (plugin);
+  IndicatorPlugin *indicator = XFCE_INDICATOR_PLUGIN (plugin);
 
   orientation = (mode == XFCE_PANEL_PLUGIN_MODE_VERTICAL) ?
     GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
 
-  xfce_indicator_box_set_orientation (XFCE_INDICATOR_BOX (indicator->buttonbox), panel_orientation, orientation);
+  indicator_config_set_orientation (indicator->config, panel_orientation, orientation);
 
-  indicator_size_changed (plugin, xfce_panel_plugin_get_size (plugin), indicator);
+  indicator_size_changed (plugin, xfce_panel_plugin_get_size (plugin));
 }
 
 
@@ -231,109 +198,122 @@ indicator_mode_changed (XfcePanelPlugin     *plugin,
 #else
 static void
 indicator_orientation_changed (XfcePanelPlugin *plugin,
-                            GtkOrientation   orientation,
-                            IndicatorPlugin    *indicator)
+                               GtkOrientation   orientation)
 {
-  xfce_indicator_box_set_orientation (XFCE_INDICATOR_BOX (indicator->buttonbox), orientation, GTK_ORIENTATION_HORIZONTAL);
+  IndicatorPlugin *indicator = XFCE_INDICATOR_PLUGIN (plugin);
+
+  indicator_config_set_orientation (indicator->config, orientation, GTK_ORIENTATION_HORIZONTAL);
 
-  indicator_size_changed (plugin, xfce_panel_plugin_get_size (plugin), indicator);
+  indicator_size_changed (plugin, xfce_panel_plugin_get_size (plugin));
 }
 #endif
 
 
 static gboolean
 indicator_size_changed (XfcePanelPlugin *plugin,
-                     gint             size,
-                     IndicatorPlugin    *indicator)
+                        gint             size)
 {
+  IndicatorPlugin *indicator = XFCE_INDICATOR_PLUGIN (plugin);
+
 #ifdef HAS_PANEL_49
-  xfce_indicator_box_set_size (XFCE_INDICATOR_BOX (indicator->buttonbox),
-                               size, xfce_panel_plugin_get_nrows (plugin));
+  indicator_config_set_size (indicator->config, size, xfce_panel_plugin_get_nrows (plugin));
 #else
-  xfce_indicator_box_set_size (XFCE_INDICATOR_BOX (indicator->buttonbox),
-                               size, 1);
+  indicator_config_set_size (indicator->config, size, 1);
 #endif
 
   return TRUE;
 }
 
 
-
-static gboolean
-on_button_press (GtkWidget *widget, GdkEventButton *event, IndicatorPlugin *indicator)
-{
-  if (indicator != NULL)
-  {
-    if( event->button == 1) /* left click only */
-    {
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),TRUE);
-      gtk_menu_popup (xfce_indicator_button_get_menu (XFCE_INDICATOR_BUTTON(widget)), NULL, NULL,
-                      xfce_panel_plugin_position_menu,
-                      indicator->plugin, 1, gtk_get_current_event_time ());
-      
-      return TRUE;
-    }
-    /* event doesn't make it to the ebox, so I just push it. */
-    gtk_widget_event (indicator->ebox, (GdkEvent*)event);
-  }
-  return FALSE;
-}
-
-static void
-menu_deactivate (GtkMenu *menu,
-                 gpointer      user_data)
-{
-  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_menu_get_attach_widget (menu)), FALSE);
-}
-
 static void
 indicator_construct (XfcePanelPlugin *plugin)
 {
-  IndicatorPlugin *indicator;
+  IndicatorPlugin  *indicator = XFCE_INDICATOR_PLUGIN (plugin);
+  gint              indicators_loaded = 0;
+  GtkWidget        *label;
+
+  xfce_panel_plugin_menu_show_configure (plugin);
+  xfce_panel_plugin_menu_show_about (plugin);
 
   /* setup transation domain */
   xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
 
-  /* create the plugin */
-  indicator = indicator_new (plugin);
-
-  /* connect plugin signals */
-  g_signal_connect (G_OBJECT (plugin), "free-data",
-                    G_CALLBACK (indicator_free), indicator);
-
-  g_signal_connect (G_OBJECT (plugin), "size-changed",
-                    G_CALLBACK (indicator_size_changed), indicator);
+  /* Init some theme/icon stuff */
+  gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
+                                  INDICATOR_ICONS_DIR);
+  /*gtk_widget_set_name(GTK_WIDGET (indicator->plugin), "indicator-plugin");*/
 
-#ifdef HAS_PANEL_49
-  g_signal_connect (G_OBJECT (plugin), "mode-changed",
-                    G_CALLBACK (indicator_mode_changed), indicator);
-#else
-  g_signal_connect (G_OBJECT (plugin), "orientation-changed",
-                    G_CALLBACK (indicator_orientation_changed), indicator);
-#endif
-}
+  /* initialize xfconf */
+  indicator->config = indicator_config_new (xfce_panel_plugin_get_property_base (plugin));
 
+  /* instantiate a button box */
+  indicator->buttonbox = xfce_indicator_box_new (indicator->config);
+  gtk_container_add (GTK_CONTAINER (plugin), GTK_WIDGET(indicator->buttonbox));
+  gtk_widget_show(GTK_WIDGET(indicator->buttonbox));
 
-static gboolean
-entry_scrolled (GtkWidget *menuitem, GdkEventScroll *event, IndicatorPlugin *indicator)
-{
-  IndicatorObject *io = xfce_indicator_button_get_io (XFCE_INDICATOR_BUTTON (menuitem));
-  IndicatorObjectEntry *entry = xfce_indicator_button_get_entry (XFCE_INDICATOR_BUTTON (menuitem));
+  /* load 'em */
+  if (g_file_test(INDICATOR_DIR, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
+    GDir * dir = g_dir_open(INDICATOR_DIR, 0, NULL);
 
-  g_return_val_if_fail(INDICATOR_IS_OBJECT(io), FALSE);
-  g_return_val_if_fail(indicator != NULL, FALSE);
+    const gchar * name;
+    if (indicator_config_get_mode_whitelist (indicator->config))
+      {
+        while ((name = g_dir_read_name (dir)) != NULL)
+          if (indicator_config_is_whitelisted (indicator->config, name))
+            {
+              g_debug ("Loading whitelisted module: %s", name);
+              if (load_module(name, indicator))
+                indicators_loaded++;
+            }
+      }
+    else
+      {
+        while ((name = g_dir_read_name (dir)) != NULL)
+          if (indicator_config_is_blacklisted (indicator->config, name))
+            g_debug ("Excluding blacklisted module: %s", name);
+          else if (load_module(name, indicator))
+            indicators_loaded++;
+      }
 
-  g_signal_emit_by_name (io, INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, entry, 1, event->direction);
+    g_dir_close (dir);
+  }
 
-  return TRUE;
+  if (indicators_loaded == 0) {
+    /* A label to allow for click through */
+    indicator->item = xfce_indicator_button_new (NULL,
+                                                 "<placeholder>",
+                                                 NULL,
+                                                 plugin,
+                                                 indicator->config);
+    label = gtk_label_new ( _("No Indicators"));
+    xfce_indicator_button_set_label (XFCE_INDICATOR_BUTTON (indicator->item), GTK_LABEL (label));
+    gtk_container_add (GTK_CONTAINER (indicator->buttonbox), indicator->item);
+    gtk_widget_show (label);
+    gtk_widget_show (indicator->item);
+  }
 }
 
 
 static void
 entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data)
 {
-  XfcePanelPlugin *plugin = ((IndicatorPlugin *) user_data)->plugin;
-  GtkWidget * button = xfce_indicator_button_new (io, entry);
+  XfcePanelPlugin *plugin = XFCE_PANEL_PLUGIN (user_data);
+  IndicatorPlugin *indicator = XFCE_INDICATOR_PLUGIN (plugin);
+  const gchar     *io_name = g_object_get_data (G_OBJECT (io), "io-name");
+  GtkWidget       *button = xfce_indicator_button_new (io,
+                                                       io_name,
+                                                       entry,
+                                                       plugin,
+                                                       indicator->config);
+
+  /* remove placeholder item when there are real entries to be added */
+  if (indicator->item != NULL)
+    {
+      xfce_indicator_button_disconnect_signals (XFCE_INDICATOR_BUTTON (indicator->item));
+      gtk_widget_destroy (GTK_WIDGET (indicator->item));
+      indicator->item = NULL;
+    }
+
   gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
   gtk_button_set_use_underline(GTK_BUTTON (button),TRUE);
   gtk_widget_set_name(GTK_WIDGET (button), "indicator-button");
@@ -345,69 +325,67 @@ entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_d
     xfce_indicator_button_set_label(XFCE_INDICATOR_BUTTON(button), entry->label);
 
   if (entry->menu != NULL)
-  {
     xfce_indicator_button_set_menu (XFCE_INDICATOR_BUTTON(button), entry->menu);
-    g_signal_connect(G_OBJECT(entry->menu), "deactivate", G_CALLBACK(menu_deactivate),NULL);
-  }
-
-  g_signal_connect(button, "button-press-event", G_CALLBACK(on_button_press),
-                   user_data);
-  g_signal_connect(button, "scroll-event", G_CALLBACK(entry_scrolled),
-                   user_data);
 
-  gtk_container_add(GTK_CONTAINER (((IndicatorPlugin *)user_data)->buttonbox), button);
+  gtk_container_add(GTK_CONTAINER (indicator->buttonbox), button);
   gtk_widget_show(button);
 }
 
 
 static void
-entry_removed_cb (GtkWidget * widget, gpointer userdata)
-{
-  gpointer data = (gpointer) xfce_indicator_button_get_entry (XFCE_INDICATOR_BUTTON (widget));
-
-  if (data != userdata)
-    return;
-    
-  gtk_widget_destroy(widget);
-}
-
-
-static void
 entry_removed (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data)
 {
-  gtk_container_foreach(GTK_CONTAINER(user_data), entry_removed_cb, entry);
+  xfce_indicator_box_remove_entry (XFCE_INDICATOR_BOX (user_data), entry);
 }
 
 
 static gboolean
 load_module (const gchar * name, IndicatorPlugin * indicator)
 {
-	g_debug("Looking at Module: %s", name);
-	g_return_val_if_fail(name != NULL, FALSE);
+  gchar                *fullpath;
+  IndicatorObject      *io;
+  GList                *entries, *entry;
+  IndicatorObjectEntry *entrydata;
+
+  g_debug("Looking at Module: %s", name);
+  g_return_val_if_fail(name != NULL, FALSE);
+
+  if (!g_str_has_suffix(name,G_MODULE_SUFFIX))
+    return FALSE;
 
-    if (!g_str_has_suffix(name,G_MODULE_SUFFIX))
-        return FALSE;
+  g_debug("Loading Module: %s", name);
 
-	g_debug("Loading Module: %s", name);
+  indicator_config_add_known_indicator (indicator->config, name);
 
-	gchar * fullpath = g_build_filename(INDICATOR_DIR, name, NULL);
-	IndicatorObject * io = indicator_object_new_from_file(fullpath);
-	g_free(fullpath);
+  fullpath = g_build_filename(INDICATOR_DIR, name, NULL);
+  io = indicator_object_new_from_file(fullpath);
+  g_free(fullpath);
+  g_object_set_data (G_OBJECT (io), "io-name", g_strdup (name));
 
-    g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
-                     G_CALLBACK(entry_added), indicator);
-    g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,
-                     G_CALLBACK(entry_removed), indicator->buttonbox);
+  g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
+                   G_CALLBACK(entry_added), indicator);
+  g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,
+                   G_CALLBACK(entry_removed), indicator->buttonbox);
 
-	GList * entries = indicator_object_get_entries(io);
-	GList * entry = NULL;
+  entries = indicator_object_get_entries(io);
+  entry = NULL;
 
-	for (entry = entries; entry != NULL; entry = g_list_next(entry)) {
-		IndicatorObjectEntry * entrydata = (IndicatorObjectEntry *)entry->data;
-		entry_added(io, entrydata, indicator);
-	}
+  for (entry = entries; entry != NULL; entry = g_list_next(entry))
+    {
+      entrydata = (IndicatorObjectEntry *)entry->data;
+      entry_added(io, entrydata, indicator);
+    }
+
+  g_list_free(entries);
+
+  return TRUE;
+}
 
-	g_list_free(entries);
 
-	return TRUE;
+XfceIndicatorBox *
+indicator_get_buttonbox (IndicatorPlugin *plugin)
+{
+  g_return_val_if_fail (XFCE_IS_INDICATOR_PLUGIN (plugin), NULL);
+
+  return XFCE_INDICATOR_BOX (plugin->buttonbox);
 }
diff --git a/panel-plugin/indicator.desktop.in.in b/panel-plugin/indicator.desktop.in
similarity index 67%
rename from panel-plugin/indicator.desktop.in.in
rename to panel-plugin/indicator.desktop.in
index 3f686cd..b0a757d 100644
--- a/panel-plugin/indicator.desktop.in.in
+++ b/panel-plugin/indicator.desktop.in
@@ -4,5 +4,5 @@ Encoding=UTF-8
 _Name=Indicator Plugin
 _Comment=An indicator of something that needs your attention on the desktop
 Icon=xfce4-indicator-plugin
-X-XFCE-Exec=@libexecdir@/xfce4/panel-plugins/xfce4-indicator-plugin
-#X-XFCE-Unique=true
+X-XFCE-Module=indicator-plugin
+X-XFCE-Internal=FALSE
diff --git a/panel-plugin/indicator.h b/panel-plugin/indicator.h
index 8b3393c..488bb5f 100644
--- a/panel-plugin/indicator.h
+++ b/panel-plugin/indicator.h
@@ -18,28 +18,30 @@
 #ifndef __INDICATOR_H__
 #define __INDICATOR_H__
 
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include "indicator-box.h"
+
 G_BEGIN_DECLS
-#ifndef INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED
-#define INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED "scroll-entry"
-#endif
-/* plugin structure */
-typedef struct
-{
-    XfcePanelPlugin *plugin;
-
-    /* panel widgets */ 
-    GtkWidget       *item;
-    GtkWidget       *buttonbox;
-    GtkWidget       *ebox;
-
-    /* indicator settings */
-    gchar          **excluded_modules;
-}
-IndicatorPlugin;
-
-void
-indicator_save (XfcePanelPlugin *plugin,
-             IndicatorPlugin    *indicator);
+typedef struct _IndicatorPluginClass IndicatorPluginClass;
+typedef struct _IndicatorPlugin      IndicatorPlugin;
+
+#define XFCE_TYPE_INDICATOR_PLUGIN            (indicator_get_type ())
+#define XFCE_INDICATOR_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_INDICATOR_PLUGIN, IndicatorPlugin))
+#define XFCE_INDICATOR_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_INDICATOR_PLUGIN, IndicatorPluginClass))
+#define XFCE_IS_INDICATOR_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_INDICATOR_PLUGIN))
+#define XFCE_IS_INDICATOR_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_INDICATOR_PLUGIN))
+#define XFCE_INDICATOR_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_INDICATOR_PLUGIN, IndicatorPluginClass))
+
+GType indicator_get_type      (void) G_GNUC_CONST;
+
+void  indicator_register_type (XfcePanelTypeModule *type_module);
+
+void                indicator_save             (XfcePanelPlugin    *plugin,
+                                                IndicatorPlugin    *indicator);
+
+XfceIndicatorBox   *indicator_get_buttonbox    (IndicatorPlugin    *plugin);
 
 G_END_DECLS
 


More information about the Xfce4-commits mailing list