Convert IconGrid into GtkContainer derived class PanelIconGrid.
authorAndriy Grytsenko <andrej@rep.kiev.ua>
Wed, 13 Aug 2014 00:29:13 +0000 (03:29 +0300)
committerAndriy Grytsenko <andrej@rep.kiev.ua>
Sat, 16 Aug 2014 16:23:38 +0000 (19:23 +0300)
This way we can simpify its handling, use it as direct plugin widget,
and use all the GTK+ APIs for GtkContainer and GtkOrientable.

src/Makefile.am
src/icon-grid-old.c [new file with mode: 0644]
src/icon-grid-old.h [new file with mode: 0644]
src/icon-grid.c
src/icon-grid.h
src/plugins/kbled/kbled.c
src/plugins/launchtaskbar.c
src/plugins/tray.c

index f1db119..01a9fba 100644 (file)
@@ -25,14 +25,14 @@ endif
 
 lxpanel_SOURCES = \
        misc.c \
-       bg.c bg.h  \
+       bg.c \
        configurator.c \
-       dbg.c dbg.h \
-       ev.c ev.h \
+       dbg.c \
+       ev.c \
+       icon-grid-old.c \
        icon-grid.c \
        panel.c \
        plugin.c \
-       private.h \
        conf.c \
        $(MENU_SOURCES)
 
@@ -59,4 +59,8 @@ lxpanelctl_SOURCES = lxpanelctl.c lxpanelctl.h
 lxpanelctl_LDADD = $(X11_LIBS) $(INTLLIBS)
 
 EXTRA_DIST = \
-       plugins/icon.xpm
+       bg.h \
+       dbg.h \
+       ev.h \
+       icon-grid-old.h \
+       private.h
diff --git a/src/icon-grid-old.c b/src/icon-grid-old.c
new file mode 100644 (file)
index 0000000..39fdad3
--- /dev/null
@@ -0,0 +1,477 @@
+/**
+ * Copyright (c) 2009 LxDE Developers, see the file AUTHORS for details.
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include "icon-grid-old.h"
+#include "private.h"
+
+static gboolean icon_grid_placement(IconGrid * ig);
+static void icon_grid_geometry(IconGrid * ig, gboolean layout);
+static void icon_grid_element_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGridElement * ige);
+static void icon_grid_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGrid * ig);
+static void icon_grid_size_allocate(GtkWidget * widget, GtkAllocation * allocation, IconGrid * ig);
+static void icon_grid_demand_resize(IconGrid * ig);
+
+/* Establish the widget placement of an icon grid. */
+static gboolean icon_grid_placement(IconGrid * ig)
+{
+    GtkAllocation allocation;
+
+    if (ig->widget == NULL)
+        return FALSE;
+
+    /* Make sure the container is visible. */
+    gtk_widget_show(ig->container);
+
+    /* Erase the window. */
+    GdkWindow * window = gtk_widget_get_window(ig->widget);
+    if (window != NULL)
+        panel_determine_background_pixmap(ig->panel, ig->widget, window);
+
+    /* Get and save the desired container geometry. */
+    gtk_widget_get_allocation(ig->container, &allocation);
+    ig->container_width = allocation.width;
+    ig->container_height = allocation.height;
+    int child_width = ig->child_width;
+    int child_height = ig->child_height;
+
+    /* Get the required container geometry if all elements get the client's desired allocation. */
+    int container_width_needed = (ig->columns * (child_width + ig->spacing)) - ig->spacing;
+    int container_height_needed = (ig->rows * (child_height + ig->spacing)) - ig->spacing;
+
+    /* Get the constrained child geometry if the allocated geometry is insufficient.
+     * All children are still the same size and share equally in the deficit. */
+    ig->constrained_child_width = ig->child_width;
+    if ((ig->columns != 0) && (ig->rows != 0) && (ig->container_width > 1))
+    {
+        if (container_width_needed > ig->container_width)
+            ig->constrained_child_width = child_width = (ig->container_width - ((ig->columns - 1) * ig->spacing)) / ig->columns;
+        if (container_height_needed > ig->container_height)
+            child_height = (ig->container_height - ((ig->rows - 1) * ig->spacing)) / ig->rows;
+    }
+
+    /* Initialize parameters to control repositioning each visible child. */
+    GtkTextDirection direction = gtk_widget_get_direction(ig->container);
+    int limit = ig->border + ((ig->orientation == GTK_ORIENTATION_HORIZONTAL)
+        ?  (ig->rows * (child_height + ig->spacing))
+        :  (ig->columns * (child_width + ig->spacing)));
+    int x_initial = ((direction == GTK_TEXT_DIR_RTL)
+        ? allocation.width - child_width - ig->border
+        : ig->border);
+    int x_delta = child_width + ig->spacing;
+    if (direction == GTK_TEXT_DIR_RTL) x_delta = - x_delta;
+
+    /* Reposition each visible child. */
+    int x = x_initial;
+    int y = ig->border;
+    gboolean contains_sockets = FALSE;
+    IconGridElement * ige;
+    for (ige = ig->child_list; ige != NULL; ige = ige->flink)
+    {
+        if (ige->visible)
+        {
+            /* Do necessary operations on the child. */
+            gtk_widget_show(ige->widget);
+            gtk_widget_get_allocation(ige->widget, &allocation);
+            if (((child_width != allocation.width) || (child_height != allocation.height))
+            && (child_width > 0) && (child_height > 0))
+                {
+                GtkAllocation alloc;
+                alloc.x = x;
+                alloc.y = y;
+                alloc.width = child_width;
+                alloc.height = child_height;
+                gtk_widget_size_allocate(ige->widget, &alloc);
+                gtk_widget_queue_resize(ige->widget);          /* Get labels to redraw ellipsized */
+                }
+            gtk_fixed_move(GTK_FIXED(ig->widget), ige->widget, x, y);
+            gtk_widget_queue_draw(ige->widget);
+
+            /* Note if a socket is placed. */
+            if (GTK_IS_SOCKET(ige->widget))
+                contains_sockets = TRUE;
+
+            /* Advance to the next grid position. */
+            if (ig->orientation == GTK_ORIENTATION_HORIZONTAL)
+            {
+                y += child_height + ig->spacing;
+                if (y >= limit)
+                {
+                    y = ig->border;
+                    x += x_delta;
+                }
+            }
+            else
+            {
+                x += x_delta;
+                if ((direction == GTK_TEXT_DIR_RTL) ? (x <= 0) : (x >= limit))
+                {
+                    x = x_initial;
+                    y += child_height + ig->spacing;
+                }
+            }
+        }
+    }
+
+    /* Redraw the container. */
+    if (window != NULL)
+        gdk_window_invalidate_rect(window, NULL, TRUE);
+    gtk_widget_queue_draw(ig->container);
+
+    /* If the icon grid contains sockets, do special handling to get the background erased. */
+    if (contains_sockets)
+        plugin_widget_set_background(ig->widget, ig->panel);
+    return FALSE;
+}
+
+/* Establish the geometry of an icon grid. */
+static void icon_grid_geometry(IconGrid * ig, gboolean layout)
+{
+    /* Count visible children. */
+    int visible_children = 0;
+    IconGridElement * ige;
+    GtkAllocation allocation;
+
+    for (ige = ig->child_list; ige != NULL; ige = ige->flink)
+        if (ige->visible)
+            visible_children += 1;
+
+   int original_rows = ig->rows;
+   int original_columns = ig->columns;
+   int target_dimension = ig->target_dimension;
+   gtk_widget_get_allocation(ig->container, &allocation);
+   if (ig->orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+        /* In horizontal orientation, fit as many rows into the available height as possible.
+         * Then allocate as many columns as necessary.  Guard against zerodivides. */
+        if (allocation.height > 1)
+            target_dimension = allocation.height;
+        ig->rows = 0;
+        if ((ig->child_height + ig->spacing) != 0)
+            ig->rows = (target_dimension + ig->spacing - ig->border * 2) / (ig->child_height + ig->spacing);
+        if (ig->rows == 0)
+            ig->rows = 1;
+        ig->columns = (visible_children + (ig->rows - 1)) / ig->rows;
+        if ((ig->columns == 1) && (ig->rows > visible_children))
+            ig->rows = visible_children;
+    }
+    else
+    {
+        /* In vertical orientation, fit as many columns into the available width as possible.
+         * Then allocate as many rows as necessary.  Guard against zerodivides. */
+        if (allocation.width > 1)
+            target_dimension = allocation.width;
+        ig->columns = 0;
+        if ((ig->child_width + ig->spacing) != 0)
+            ig->columns = (target_dimension + ig->spacing - ig->border * 2) / (ig->child_width + ig->spacing);
+        if (ig->columns == 0)
+            ig->columns = 1;
+        ig->rows = (visible_children + (ig->columns - 1)) / ig->columns;
+        if ((ig->rows == 1) && (ig->columns > visible_children))
+            ig->columns = visible_children;
+    }
+
+    /* If the table geometry or child composition changed, redo the placement of children in table cells.
+     * This is gated by having a valid table allocation and by the "layout" parameter, which prevents a recursive loop.
+     * We do the placement later, also to prevent a recursive loop. */
+    if ((layout)
+    && (( ! ig->actual_dimension)
+      || (ig->rows != original_rows)
+      || (ig->columns != original_columns)
+      || (ig->container_width != allocation.width)
+      || (ig->container_height != allocation.height)
+      || (ig->children_changed)))
+        {
+        ig->actual_dimension = TRUE;
+        ig->children_changed = FALSE;
+        g_idle_add((GSourceFunc) icon_grid_placement, ig);
+        }
+}
+
+/* Handler for "size-request" event on the icon grid element. */
+static void icon_grid_element_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGridElement * ige)
+{
+    /* This is our opportunity to request space for the element. */
+    IconGrid * ig = ige->ig;
+    requisition->width = ig->child_width;
+    if ((ig->constrain_width) && (ig->actual_dimension) && (ig->constrained_child_width > 1))
+        requisition->width = ig->constrained_child_width;
+    requisition->height = ig->child_height;
+}
+
+/* Handler for "size-request" event on the icon grid's container. */
+static void icon_grid_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGrid * ig)
+{
+    /* This is our opportunity to request space for the layout container.
+     * Compute the geometry.  Do not lay out children at this time to avoid a recursive loop. */
+    icon_grid_geometry(ig, FALSE);
+
+    /* Compute the requisition. */
+    if ((ig->columns == 0) || (ig->rows == 0))
+    {
+        requisition->width = 1;
+        requisition->height = 1;
+        gtk_widget_hide(ig->widget);   /* Necessary to get the plugin to disappear */
+    }
+    else
+    {
+        int column_spaces = ig->columns - 1;
+        int row_spaces = ig->rows - 1;
+        if (column_spaces < 0) column_spaces = 0;
+        if (row_spaces < 0) row_spaces = 0;
+        requisition->width = ig->child_width * ig->columns + column_spaces * ig->spacing + 2 * ig->border;
+        requisition->height = ig->child_height * ig->rows + row_spaces * ig->spacing + 2 * ig->border;
+        gtk_widget_show(ig->widget);
+    }
+}
+
+/* Handler for "size-allocate" event on the icon grid's container. */
+static void icon_grid_size_allocate(GtkWidget * widget, GtkAllocation * allocation, IconGrid * ig)
+{
+    /* This is our notification that there is a resize of the entire panel.
+     * Compute the geometry and recompute layout if the geometry changed. */
+    icon_grid_geometry(ig, TRUE);
+}
+
+/* Initiate a resize. */
+static void icon_grid_demand_resize(IconGrid * ig)
+{
+    ig->children_changed = TRUE;
+    GtkRequisition req;
+    icon_grid_size_request(NULL, &req, ig);
+
+    if ((ig->rows != 0) || (ig->columns != 0))
+        icon_grid_placement(ig);
+}
+
+/* Establish an icon grid in a specified container widget.
+ * The icon grid manages the contents of the container.
+ * The orientation, geometry of the elements, and spacing can be varied.  All elements are the same size. */
+IconGrid * icon_grid_new(
+    Panel * panel, GtkWidget * container,
+    GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension)
+{
+    /* Create a structure representing the icon grid and collect the parameters. */
+    IconGrid * ig = g_new0(IconGrid, 1);
+    ig->panel = panel;
+    ig->container = container;
+    ig->orientation = orientation;
+    ig->child_width = child_width;
+    ig->constrained_child_width = child_width;
+    ig->child_height = child_height;
+    ig->spacing = spacing;
+    ig->border = border;
+    ig->target_dimension = target_dimension;
+
+    /* Create a layout container. */
+    ig->widget = gtk_fixed_new();
+    g_object_add_weak_pointer(G_OBJECT(ig->widget), (gpointer*)&ig->widget);
+    gtk_widget_set_has_window(ig->widget, FALSE);
+    gtk_widget_set_redraw_on_allocate(ig->widget, FALSE);
+    gtk_container_add(GTK_CONTAINER(ig->container), ig->widget);
+    gtk_widget_show(ig->widget);
+
+    /* Connect signals. */
+    g_signal_connect(G_OBJECT(ig->widget), "size-request", G_CALLBACK(icon_grid_size_request), (gpointer) ig);
+    g_signal_connect(G_OBJECT(container), "size-request", G_CALLBACK(icon_grid_size_request), (gpointer) ig);
+    g_signal_connect(G_OBJECT(container), "size-allocate", G_CALLBACK(icon_grid_size_allocate), (gpointer) ig);
+    return ig;
+}
+
+/* Add an icon grid element and establish its initial visibility. */
+void icon_grid_add(IconGrid * ig, GtkWidget * child, gboolean visible)
+{
+    /* Create and initialize a structure representing the child. */
+    IconGridElement * ige = g_new0(IconGridElement, 1);
+    ige->ig = ig;
+    ige->widget = child;
+    ige->visible = visible;
+
+    /* Insert at the tail of the child list.  This keeps the graphics in the order they were added. */
+    if (ig->child_list == NULL)
+        ig->child_list = ige;
+    else
+    {
+        IconGridElement * ige_cursor;
+        for (ige_cursor = ig->child_list; ige_cursor->flink != NULL; ige_cursor = ige_cursor->flink) ;
+        ige_cursor->flink = ige;
+    }
+
+    /* Add the widget to the layout container. */
+    if (visible)
+        gtk_widget_show(ige->widget);
+    gtk_fixed_put(GTK_FIXED(ig->widget), ige->widget, 0, 0);
+    g_signal_connect(G_OBJECT(child), "size-request", G_CALLBACK(icon_grid_element_size_request), (gpointer) ige);
+
+    /* Do a relayout. */
+    icon_grid_demand_resize(ig);
+}
+
+extern void icon_grid_set_constrain_width(IconGrid * ig, gboolean constrain_width)
+{
+    ig->constrain_width = constrain_width;
+}
+
+/* Remove an icon grid element. */
+void icon_grid_remove(IconGrid * ig, GtkWidget * child)
+{
+    IconGridElement * ige_pred = NULL;
+    IconGridElement * ige;
+    for (ige = ig->child_list; ige != NULL; ige_pred = ige, ige = ige->flink)
+    {
+        if (ige->widget == child)
+        {
+            /* The child is found.  Remove from child list and layout container. */
+            gtk_widget_hide(ige->widget);
+            gtk_container_remove(GTK_CONTAINER(ig->widget), ige->widget);
+
+            if (ige_pred == NULL)
+                ig->child_list = ige->flink;
+            else
+                ige_pred->flink = ige->flink;
+
+            /* Do a relayout. */
+            icon_grid_demand_resize(ig);
+            break;
+        }
+    }
+}
+
+/* Get the index of an icon grid element. */
+extern gint icon_grid_get_child_position(IconGrid * ig, GtkWidget * child)
+{
+    gint i;
+    IconGridElement * ige;
+    for (ige = ig->child_list, i = 0; ige != NULL; ige = ige->flink, i++)
+    {
+        if (ige->widget == child)
+        {
+            return i;
+            break;
+        }
+    }
+
+    return -1;
+}
+
+/* Reorder an icon grid element. */
+extern void icon_grid_reorder_child(IconGrid * ig, GtkWidget * child, gint position)
+{
+    /* Remove the child from its current position. */
+    IconGridElement * ige_pred = NULL;
+    IconGridElement * ige;
+    for (ige = ig->child_list; ige != NULL; ige_pred = ige, ige = ige->flink)
+    {
+        if (ige->widget == child)
+        {
+            if (ige_pred == NULL)
+                ig->child_list = ige->flink;
+            else
+                ige_pred->flink = ige->flink;
+            break;
+        }
+    }
+
+    /* If the child was found, insert it at the new position. */
+    if (ige != NULL)
+    {
+        if (ig->child_list == NULL)
+        {
+            ige->flink = NULL;
+            ig->child_list = ige;
+        }
+        else if (position == 0)
+        {
+            ige->flink = ig->child_list;
+            ig->child_list = ige;
+        }
+        else
+            {
+            int local_position = position - 1;
+            IconGridElement * ige_pred;
+            for (
+              ige_pred = ig->child_list;
+              ((ige_pred != NULL) && (local_position > 0));
+              local_position -= 1, ige_pred = ige_pred->flink) ;
+            ige->flink = ige_pred->flink;
+            ige_pred->flink = ige;
+            }
+
+        /* Do a relayout. */
+        if (ige->visible)
+            icon_grid_demand_resize(ig);
+    }
+}
+
+/* Change the geometry of an icon grid. */
+void icon_grid_set_geometry(IconGrid * ig,
+    GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension)
+{
+    ig->orientation = orientation;
+    ig->child_width = child_width;
+    ig->constrained_child_width = child_width;
+    ig->child_height = child_height;
+    ig->spacing = spacing;
+    ig->border = border;
+    ig->target_dimension = target_dimension;
+    icon_grid_demand_resize(ig);
+}
+
+/* Change the visibility of an icon grid element. */
+void icon_grid_set_visible(IconGrid * ig, GtkWidget * child, gboolean visible)
+{
+    IconGridElement * ige;
+    for (ige = ig->child_list; ige != NULL; ige = ige->flink)
+    {
+        if (ige->widget == child)
+        {
+            if (ige->visible != visible)
+            {
+                /* Found, and the visibility changed.  Do a relayout. */
+                ige->visible = visible;
+                if ( ! ige->visible)
+                    gtk_widget_hide(ige->widget);
+                icon_grid_demand_resize(ig);
+            }
+            break;
+        }
+    }
+}
+
+/* Deallocate the icon grid structures. */
+void icon_grid_free(IconGrid * ig)
+{
+    /* Hide the layout container. */
+    if (ig->widget != NULL)
+    {
+        g_object_remove_weak_pointer(G_OBJECT(ig->widget), (gpointer*)&ig->widget);
+        gtk_widget_hide(ig->widget);
+    }
+
+    /* Free all memory. */
+    IconGridElement * ige = ig->child_list;
+    while (ige != NULL)
+    {
+        IconGridElement * ige_succ = ige->flink;
+        g_free(ige);
+        ige = ige_succ;
+    }
+    g_free(ig);
+}
diff --git a/src/icon-grid-old.h b/src/icon-grid-old.h
new file mode 100644 (file)
index 0000000..aeb673c
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2009 LxDE Developers, see the file AUTHORS for details.
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef ICON_GRID_H
+#define ICON_GRID_H
+
+#include <gtk/gtk.h>
+
+#include "panel.h"
+
+struct _icon_grid_element;
+struct _icon_grid;
+
+/* Representative of an icon grid element.  This is a widget to be packed into a rectangular grid whose size adapts to conditions. */
+typedef struct _icon_grid_element {
+    struct _icon_grid_element * flink;         /* Forward link */
+    struct _icon_grid * ig;                    /* Back pointer to IconGrid */
+    GtkWidget * widget;                                /* Customer's widget */
+    gboolean visible;                          /* True if widget is visible */
+} IconGridElement;
+
+/* Representative of an icon grid.  This is a manager that packs widgets into a rectangular grid whose size adapts to conditions. */
+typedef struct _icon_grid {
+    IconGridElement * child_list;              /* List of icon grid elements */
+    Panel * panel;                             /* Back pointer to panel */
+    GtkWidget * container;                     /* Container widget */
+    GtkOrientation orientation;                        /* Desired orientation */
+    gint child_width;                          /* Desired child width */
+    gint child_height;                         /* Desired child height */
+    gint spacing;                              /* Desired spacing between grid elements */
+    gint border;                               /* Desired border around grid elements */
+    gint target_dimension;                     /* Desired dimension perpendicular to orientation */
+    gboolean constrain_width;                  /* True if width should be constrained by allocated space */
+    gboolean actual_dimension;                 /* True if container has been allocated space */
+    gboolean children_changed;                 /* True if icon grid element list changed */
+    GtkWidget * widget;                                /* Layout widget we use for packing */
+    int rows;                                  /* Computed layout rows */
+    int columns;                               /* Computed layout columns */
+    int container_width;                       /* Container's allocated width */
+    int container_height;                      /* Container's allocated height */
+    int constrained_child_width;               /* Child width constrained by allocation */
+} IconGrid;
+
+extern IconGrid * icon_grid_new(
+    Panel * panel, GtkWidget * container,
+    GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension);
+                                               /* Create an icon grid */
+extern void icon_grid_set_constrain_width(IconGrid * ig, gboolean constrain_width);
+                                               /* Set the constrain-width property */
+extern void icon_grid_set_geometry(IconGrid * ig,
+    GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension);
+                                               /* Change the geometry of an icon grid */
+extern void icon_grid_add(IconGrid * ig, GtkWidget * child, gboolean visible);
+                                               /* Add a child to the icon grid */
+extern void icon_grid_remove(IconGrid * ig, GtkWidget * child);
+                                               /* Remove a child from the icon grid */
+extern gint icon_grid_get_child_position(IconGrid * ig, GtkWidget * child);
+                                               /* Get the index of an icon grid element. */
+extern void icon_grid_reorder_child(IconGrid * ig, GtkWidget * child, gint position);
+                                               /* Reorder the position of a child in the icon grid */
+extern void icon_grid_set_visible(IconGrid * ig, GtkWidget * child, gboolean visible);
+                                               /* Set the visibility of a child in the icon grid */
+extern void icon_grid_free(IconGrid * ig);     /* Free the icon grid */
+
+#endif
index 61eee02..5f2dc45 100644 (file)
 #include <string.h>
 
 #include "icon-grid.h"
-#include "private.h"
 
-static gboolean icon_grid_placement(IconGrid * ig);
-static void icon_grid_geometry(IconGrid * ig, gboolean layout);
-static void icon_grid_element_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGridElement * ige);
-static void icon_grid_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGrid * ig);
-static void icon_grid_size_allocate(GtkWidget * widget, GtkAllocation * allocation, IconGrid * ig);
-static void icon_grid_demand_resize(IconGrid * ig);
+/* Properties */
+enum {
+  PROP_0,
+  PROP_ORIENTATION,
+  PROP_SPACING,
+  PROP_CONSTRAIN_WIDTH
+};
 
-/* Establish the widget placement of an icon grid. */
-static gboolean icon_grid_placement(IconGrid * ig)
+/* Representative of an icon grid.  This is a manager that packs widgets into a rectangular grid whose size adapts to conditions. */
+struct _PanelIconGrid
 {
-    GtkAllocation allocation;
-
-    if (ig->widget == NULL)
-        return FALSE;
-
-    /* Make sure the container is visible. */
-    gtk_widget_show(ig->container);
+    GtkContainer container;                    /* Parent widget */
+    GList * children;                          /* List of icon grid elements */
+    GtkOrientation orientation;                        /* Desired orientation */
+    gint child_width;                          /* Desired child width */
+    gint child_height;                         /* Desired child height */
+    gint spacing;                              /* Desired spacing between grid elements */
+    gint border;                               /* Desired border around grid elements */
+    gint target_dimension;                     /* Desired dimension perpendicular to orientation */
+    gboolean constrain_width;                  /* True if width should be constrained by allocated space */
+    int rows;                                  /* Computed layout rows */
+    int columns;                               /* Computed layout columns */
+    int constrained_child_width;               /* Child width constrained by allocation */
+};
+
+struct _PanelIconGridClass
+{
+    GtkContainerClass parent_class;
+};
 
-    /* Erase the window. */
-    GdkWindow * window = gtk_widget_get_window(ig->widget);
-    if (window != NULL)
-        panel_determine_background_pixmap(ig->panel, ig->widget, window);
+/* Establish the widget placement of an icon grid. */
+static void panel_icon_grid_size_allocate(GtkWidget *widget,
+                                          GtkAllocation *allocation)
+{
+    PanelIconGrid *ig = PANEL_ICON_GRID(widget);
+    GtkRequisition req;
+    GtkAllocation child_allocation;
+    int child_width;
+    int child_height;
+    GtkTextDirection direction;
+    int limit;
+    int x_initial;
+    int x_delta;
+    int x, y;
+    GList *ige;
+    GtkWidget *child;
+
+    /* Calculate required size without borders */
+    gtk_widget_size_request(widget, &req);
+    req.width -= 2 * ig->border;
+    req.height -= 2 * ig->border;
 
     /* Get and save the desired container geometry. */
-    gtk_widget_get_allocation(ig->container, &allocation);
-    ig->container_width = allocation.width;
-    ig->container_height = allocation.height;
-    int child_width = ig->child_width;
-    int child_height = ig->child_height;
-
-    /* Get the required container geometry if all elements get the client's desired allocation. */
-    int container_width_needed = (ig->columns * (child_width + ig->spacing)) - ig->spacing;
-    int container_height_needed = (ig->rows * (child_height + ig->spacing)) - ig->spacing;
+    child_width = ig->child_width;
+    child_height = ig->child_height;
 
     /* Get the constrained child geometry if the allocated geometry is insufficient.
      * All children are still the same size and share equally in the deficit. */
     ig->constrained_child_width = ig->child_width;
-    if ((ig->columns != 0) && (ig->rows != 0) && (ig->container_width > 1))
+    if ((ig->columns != 0) && (ig->rows != 0) && (allocation->width > 1))
     {
-        if (container_width_needed > ig->container_width)
-            ig->constrained_child_width = child_width = (ig->container_width - ((ig->columns - 1) * ig->spacing)) / ig->columns;
-        if (container_height_needed > ig->container_height)
-            child_height = (ig->container_height - ((ig->rows - 1) * ig->spacing)) / ig->rows;
+        if (req.width > allocation->width)
+            ig->constrained_child_width = child_width = (allocation->width - ((ig->columns - 1) * ig->spacing)) / ig->columns;
+        if (req.height > allocation->height)
+            child_height = (allocation->height - ((ig->rows - 1) * ig->spacing)) / ig->rows;
     }
 
     /* Initialize parameters to control repositioning each visible child. */
-    GtkTextDirection direction = gtk_widget_get_direction(ig->container);
-    int limit = ig->border + ((ig->orientation == GTK_ORIENTATION_HORIZONTAL)
+    direction = gtk_widget_get_direction(widget);
+    limit = ig->border + ((ig->orientation == GTK_ORIENTATION_HORIZONTAL)
         ?  (ig->rows * (child_height + ig->spacing))
         :  (ig->columns * (child_width + ig->spacing)));
-    int x_initial = ((direction == GTK_TEXT_DIR_RTL)
-        ? allocation.width - child_width - ig->border
+    x_initial = ((direction == GTK_TEXT_DIR_RTL)
+        ? allocation->width - child_width - ig->border
         : ig->border);
-    int x_delta = child_width + ig->spacing;
+    x_delta = child_width + ig->spacing;
     if (direction == GTK_TEXT_DIR_RTL) x_delta = - x_delta;
 
     /* Reposition each visible child. */
-    int x = x_initial;
-    int y = ig->border;
-    gboolean contains_sockets = FALSE;
-    IconGridElement * ige;
-    for (ige = ig->child_list; ige != NULL; ige = ige->flink)
+    x = x_initial;
+    y = ig->border;
+    for (ige = ig->children; ige != NULL; ige = ige->next)
     {
-        if (ige->visible)
+        child = ige->data;
+        if (gtk_widget_get_visible(child))
         {
             /* Do necessary operations on the child. */
-            gtk_widget_show(ige->widget);
-            gtk_widget_get_allocation(ige->widget, &allocation);
-            if (((child_width != allocation.width) || (child_height != allocation.height))
-            && (child_width > 0) && (child_height > 0))
-                {
-                GtkAllocation alloc;
-                alloc.x = x;
-                alloc.y = y;
-                alloc.width = child_width;
-                alloc.height = child_height;
-                gtk_widget_size_allocate(ige->widget, &alloc);
-                gtk_widget_queue_resize(ige->widget);          /* Get labels to redraw ellipsized */
-                }
-            gtk_fixed_move(GTK_FIXED(ig->widget), ige->widget, x, y);
-            gtk_widget_queue_draw(ige->widget);
-
-            /* Note if a socket is placed. */
-            if (GTK_IS_SOCKET(ige->widget))
-                contains_sockets = TRUE;
+            gtk_widget_size_request(child, &req);
+            child_allocation.x = x;
+            child_allocation.y = y;
+            child_allocation.width = child_width;
+            child_allocation.height = child_height;
+            if (!gtk_widget_get_has_window (widget))
+            {
+                child_allocation.x += allocation->x;
+                child_allocation.y += allocation->y;
+            }
+            gtk_widget_size_allocate(child, &child_allocation);
 
             /* Advance to the next grid position. */
             if (ig->orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -129,40 +141,26 @@ static gboolean icon_grid_placement(IconGrid * ig)
             }
         }
     }
-
-    /* Redraw the container. */
-    if (window != NULL)
-        gdk_window_invalidate_rect(window, NULL, TRUE);
-    gtk_widget_queue_draw(ig->container);
-
-    /* If the icon grid contains sockets, do special handling to get the background erased. */
-    if (contains_sockets)
-        plugin_widget_set_background(ig->widget, ig->panel);
-    return FALSE;
 }
 
 /* Establish the geometry of an icon grid. */
-static void icon_grid_geometry(IconGrid * ig, gboolean layout)
+static void panel_icon_grid_size_request(GtkWidget *widget,
+                                         GtkRequisition *requisition)
 {
-    /* Count visible children. */
+    PanelIconGrid *ig = PANEL_ICON_GRID(widget);
     int visible_children = 0;
-    IconGridElement * ige;
-    GtkAllocation allocation;
+    GList *ige;
+    int target_dimension = ig->target_dimension;
 
-    for (ige = ig->child_list; ige != NULL; ige = ige->flink)
-        if (ige->visible)
+    /* Count visible children. */
+    for (ige = ig->children; ige != NULL; ige = ige->next)
+        if (gtk_widget_get_visible(ige->data))
             visible_children += 1;
 
-   int original_rows = ig->rows;
-   int original_columns = ig->columns;
-   int target_dimension = ig->target_dimension;
-   gtk_widget_get_allocation(ig->container, &allocation);
-   if (ig->orientation == GTK_ORIENTATION_HORIZONTAL)
+    if (ig->orientation == GTK_ORIENTATION_HORIZONTAL)
     {
         /* In horizontal orientation, fit as many rows into the available height as possible.
          * Then allocate as many columns as necessary.  Guard against zerodivides. */
-        if (allocation.height > 1)
-            target_dimension = allocation.height;
         ig->rows = 0;
         if ((ig->child_height + ig->spacing) != 0)
             ig->rows = (target_dimension + ig->spacing - ig->border * 2) / (ig->child_height + ig->spacing);
@@ -176,8 +174,6 @@ static void icon_grid_geometry(IconGrid * ig, gboolean layout)
     {
         /* In vertical orientation, fit as many columns into the available width as possible.
          * Then allocate as many rows as necessary.  Guard against zerodivides. */
-        if (allocation.width > 1)
-            target_dimension = allocation.width;
         ig->columns = 0;
         if ((ig->child_width + ig->spacing) != 0)
             ig->columns = (target_dimension + ig->spacing - ig->border * 2) / (ig->child_width + ig->spacing);
@@ -188,47 +184,12 @@ static void icon_grid_geometry(IconGrid * ig, gboolean layout)
             ig->columns = visible_children;
     }
 
-    /* If the table geometry or child composition changed, redo the placement of children in table cells.
-     * This is gated by having a valid table allocation and by the "layout" parameter, which prevents a recursive loop.
-     * We do the placement later, also to prevent a recursive loop. */
-    if ((layout)
-    && (( ! ig->actual_dimension)
-      || (ig->rows != original_rows)
-      || (ig->columns != original_columns)
-      || (ig->container_width != allocation.width)
-      || (ig->container_height != allocation.height)
-      || (ig->children_changed)))
-        {
-        ig->actual_dimension = TRUE;
-        ig->children_changed = FALSE;
-        g_idle_add((GSourceFunc) icon_grid_placement, ig);
-        }
-}
-
-/* Handler for "size-request" event on the icon grid element. */
-static void icon_grid_element_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGridElement * ige)
-{
-    /* This is our opportunity to request space for the element. */
-    IconGrid * ig = ige->ig;
-    requisition->width = ig->child_width;
-    if ((ig->constrain_width) && (ig->actual_dimension) && (ig->constrained_child_width > 1))
-        requisition->width = ig->constrained_child_width;
-    requisition->height = ig->child_height;
-}
-
-/* Handler for "size-request" event on the icon grid's container. */
-static void icon_grid_size_request(GtkWidget * widget, GtkRequisition * requisition, IconGrid * ig)
-{
-    /* This is our opportunity to request space for the layout container.
-     * Compute the geometry.  Do not lay out children at this time to avoid a recursive loop. */
-    icon_grid_geometry(ig, FALSE);
-
     /* Compute the requisition. */
     if ((ig->columns == 0) || (ig->rows == 0))
     {
         requisition->width = 1;
         requisition->height = 1;
-        gtk_widget_hide(ig->widget);   /* Necessary to get the plugin to disappear */
+        gtk_widget_hide(widget);       /* Necessary to get the plugin to disappear */
     }
     else
     {
@@ -238,190 +199,118 @@ static void icon_grid_size_request(GtkWidget * widget, GtkRequisition * requisit
         if (row_spaces < 0) row_spaces = 0;
         requisition->width = ig->child_width * ig->columns + column_spaces * ig->spacing + 2 * ig->border;
         requisition->height = ig->child_height * ig->rows + row_spaces * ig->spacing + 2 * ig->border;
-        gtk_widget_show(ig->widget);
+        gtk_widget_show(widget);
     }
 }
 
-/* Handler for "size-allocate" event on the icon grid's container. */
-static void icon_grid_size_allocate(GtkWidget * widget, GtkAllocation * allocation, IconGrid * ig)
-{
-    /* This is our notification that there is a resize of the entire panel.
-     * Compute the geometry and recompute layout if the geometry changed. */
-    icon_grid_geometry(ig, TRUE);
-}
-
-/* Initiate a resize. */
-static void icon_grid_demand_resize(IconGrid * ig)
-{
-    ig->children_changed = TRUE;
-    GtkRequisition req;
-    icon_grid_size_request(NULL, &req, ig);
-
-    if ((ig->rows != 0) || (ig->columns != 0))
-        icon_grid_placement(ig);
-}
-
-/* Establish an icon grid in a specified container widget.
- * The icon grid manages the contents of the container.
- * The orientation, geometry of the elements, and spacing can be varied.  All elements are the same size. */
-IconGrid * icon_grid_new(
-    Panel * panel, GtkWidget * container,
-    GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension)
+/* Handler for "size-request" event on the icon grid element. */
+static void icon_grid_element_size_request(GtkWidget * widget, GtkRequisition * requisition, PanelIconGrid * ig)
 {
-    /* Create a structure representing the icon grid and collect the parameters. */
-    IconGrid * ig = g_new0(IconGrid, 1);
-    ig->panel = panel;
-    ig->container = container;
-    ig->orientation = orientation;
-    ig->child_width = child_width;
-    ig->constrained_child_width = child_width;
-    ig->child_height = child_height;
-    ig->spacing = spacing;
-    ig->border = border;
-    ig->target_dimension = target_dimension;
-
-    /* Create a layout container. */
-    ig->widget = gtk_fixed_new();
-    g_object_add_weak_pointer(G_OBJECT(ig->widget), (gpointer*)&ig->widget);
-    gtk_widget_set_has_window(ig->widget, FALSE);
-    gtk_widget_set_redraw_on_allocate(ig->widget, FALSE);
-    gtk_container_add(GTK_CONTAINER(ig->container), ig->widget);
-    gtk_widget_show(ig->widget);
-
-    /* Connect signals. */
-    g_signal_connect(G_OBJECT(ig->widget), "size-request", G_CALLBACK(icon_grid_size_request), (gpointer) ig);
-    g_signal_connect(G_OBJECT(container), "size-request", G_CALLBACK(icon_grid_size_request), (gpointer) ig);
-    g_signal_connect(G_OBJECT(container), "size-allocate", G_CALLBACK(icon_grid_size_allocate), (gpointer) ig);
-    return ig;
+    /* This is our opportunity to request space for the element. */
+    requisition->width = ig->child_width;
+    if ((ig->constrain_width) && (ig->constrained_child_width > 1))
+        requisition->width = ig->constrained_child_width;
+    requisition->height = ig->child_height;
 }
 
 /* Add an icon grid element and establish its initial visibility. */
-void icon_grid_add(IconGrid * ig, GtkWidget * child, gboolean visible)
+static void panel_icon_grid_add(GtkContainer *container, GtkWidget *widget)
 {
-    /* Create and initialize a structure representing the child. */
-    IconGridElement * ige = g_new0(IconGridElement, 1);
-    ige->ig = ig;
-    ige->widget = child;
-    ige->visible = visible;
+    PanelIconGrid *ig = PANEL_ICON_GRID(container);
 
     /* Insert at the tail of the child list.  This keeps the graphics in the order they were added. */
-    if (ig->child_list == NULL)
-        ig->child_list = ige;
-    else
-    {
-        IconGridElement * ige_cursor;
-        for (ige_cursor = ig->child_list; ige_cursor->flink != NULL; ige_cursor = ige_cursor->flink) ;
-        ige_cursor->flink = ige;
-    }
+    ig->children = g_list_append(ig->children, widget);
 
     /* Add the widget to the layout container. */
-    if (visible)
-        gtk_widget_show(ige->widget);
-    gtk_fixed_put(GTK_FIXED(ig->widget), ige->widget, 0, 0);
-    g_signal_connect(G_OBJECT(child), "size-request", G_CALLBACK(icon_grid_element_size_request), (gpointer) ige);
-
-    /* Do a relayout. */
-    icon_grid_demand_resize(ig);
+    g_signal_connect(G_OBJECT(widget), "size-request",
+                     G_CALLBACK(icon_grid_element_size_request), container);
+    gtk_widget_set_parent(widget, GTK_WIDGET(container));
+    gtk_widget_queue_resize(GTK_WIDGET(container));
 }
 
-extern void icon_grid_set_constrain_width(IconGrid * ig, gboolean constrain_width)
+void panel_icon_grid_set_constrain_width(PanelIconGrid * ig, gboolean constrain_width)
 {
     ig->constrain_width = constrain_width;
 }
 
 /* Remove an icon grid element. */
-void icon_grid_remove(IconGrid * ig, GtkWidget * child)
+static void panel_icon_grid_remove(GtkContainer *container, GtkWidget *widget)
 {
-    IconGridElement * ige_pred = NULL;
-    IconGridElement * ige;
-    for (ige = ig->child_list; ige != NULL; ige_pred = ige, ige = ige->flink)
+    PanelIconGrid *ig = PANEL_ICON_GRID(container);
+    GList *children = ig->children;
+    GtkWidget *child;
+
+    while (children)
     {
-        if (ige->widget == child)
+        child = children->data;
+        if (widget == child)
         {
-            /* The child is found.  Remove from child list and layout container. */
-            gtk_widget_hide(ige->widget);
-            gtk_container_remove(GTK_CONTAINER(ig->widget), ige->widget);
+            gboolean was_visible = gtk_widget_get_visible(widget);
 
-            if (ige_pred == NULL)
-                ig->child_list = ige->flink;
-            else
-                ige_pred->flink = ige->flink;
+            /* The child is found.  Remove from child list and layout container. */
+            gtk_widget_unparent (widget);
+            ig->children = g_list_remove_link(ig->children, children);
+            g_list_free(children);
 
-            /* Do a relayout. */
-            icon_grid_demand_resize(ig);
+            /* Do a relayout if needed. */
+            if (was_visible)
+                gtk_widget_queue_resize(GTK_WIDGET(ig));
             break;
         }
+        children = children->next;
     }
 }
 
 /* Get the index of an icon grid element. */
-extern gint icon_grid_get_child_position(IconGrid * ig, GtkWidget * child)
+gint panel_icon_grid_get_child_position(PanelIconGrid * ig, GtkWidget * child)
 {
-    gint i;
-    IconGridElement * ige;
-    for (ige = ig->child_list, i = 0; ige != NULL; ige = ige->flink, i++)
-    {
-        if (ige->widget == child)
-        {
-            return i;
-            break;
-        }
-    }
+    g_return_val_if_fail(PANEL_IS_ICON_GRID(ig), -1);
 
-    return -1;
+    return g_list_index(ig->children, child);
 }
 
 /* Reorder an icon grid element. */
-extern void icon_grid_reorder_child(IconGrid * ig, GtkWidget * child, gint position)
+void panel_icon_grid_reorder_child(PanelIconGrid * ig, GtkWidget * child, gint position)
 {
-    /* Remove the child from its current position. */
-    IconGridElement * ige_pred = NULL;
-    IconGridElement * ige;
-    for (ige = ig->child_list; ige != NULL; ige_pred = ige, ige = ige->flink)
+    GList *old_link;
+    GList *new_link;
+    gint old_position;
+
+    g_return_if_fail(PANEL_IS_ICON_GRID(ig));
+    g_return_if_fail(GTK_IS_WIDGET(child));
+
+    old_link = ig->children;
+    old_position = 0;
+    while (old_link)
     {
-        if (ige->widget == child)
-        {
-            if (ige_pred == NULL)
-                ig->child_list = ige->flink;
-            else
-                ige_pred->flink = ige->flink;
+        if (old_link->data == child)
             break;
-        }
+        old_link = old_link->next;
+        old_position++;
     }
 
+    g_return_if_fail(old_link != NULL);
+
+    if (position == old_position)
+        return;
+
+    /* Remove the child from its current position. */
+    ig->children = g_list_delete_link(ig->children, old_link);
+    if (position < 0)
+        new_link = NULL;
+    else
+        new_link = g_list_nth(ig->children, position);
+
     /* If the child was found, insert it at the new position. */
-    if (ige != NULL)
-    {
-        if (ig->child_list == NULL)
-        {
-            ige->flink = NULL;
-            ig->child_list = ige;
-        }
-        else if (position == 0)
-        {
-            ige->flink = ig->child_list;
-            ig->child_list = ige;
-        }
-        else
-            {
-            int local_position = position - 1;
-            IconGridElement * ige_pred;
-            for (
-              ige_pred = ig->child_list;
-              ((ige_pred != NULL) && (local_position > 0));
-              local_position -= 1, ige_pred = ige_pred->flink) ;
-            ige->flink = ige_pred->flink;
-            ige_pred->flink = ige;
-            }
+    ig->children = g_list_insert_before(ig->children, new_link, child);
 
-        /* Do a relayout. */
-        if (ige->visible)
-            icon_grid_demand_resize(ig);
-    }
+    /* Do a relayout. */
+    if (gtk_widget_get_visible(child) && gtk_widget_get_visible(GTK_WIDGET(ig)))
+        gtk_widget_queue_resize(child);
 }
 
 /* Change the geometry of an icon grid. */
-void icon_grid_set_geometry(IconGrid * ig,
+void panel_icon_grid_set_geometry(PanelIconGrid * ig,
     GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension)
 {
     ig->orientation = orientation;
@@ -431,47 +320,147 @@ void icon_grid_set_geometry(IconGrid * ig,
     ig->spacing = spacing;
     ig->border = border;
     ig->target_dimension = target_dimension;
-    icon_grid_demand_resize(ig);
+    gtk_widget_queue_resize(GTK_WIDGET(ig));
 }
 
-/* Change the visibility of an icon grid element. */
-void icon_grid_set_visible(IconGrid * ig, GtkWidget * child, gboolean visible)
+G_DEFINE_TYPE_WITH_CODE(PanelIconGrid, panel_icon_grid, GTK_TYPE_CONTAINER,
+                        G_IMPLEMENT_INTERFACE(GTK_TYPE_ORIENTABLE, NULL));
+
+static void panel_icon_grid_set_property(GObject *object, guint prop_id,
+                                         const GValue *value, GParamSpec *pspec)
 {
-    IconGridElement * ige;
-    for (ige = ig->child_list; ige != NULL; ige = ige->flink)
+    PanelIconGrid *ig = PANEL_ICON_GRID(object);
+    gint spacing;
+
+    switch (prop_id)
     {
-        if (ige->widget == child)
+    case PROP_ORIENTATION:
+        ig->orientation = g_value_get_enum(value);
+        gtk_widget_queue_resize(GTK_WIDGET(ig));
+        break;
+    case PROP_SPACING:
+        spacing = g_value_get_int(value);
+        if (spacing != ig->spacing)
         {
-            if (ige->visible != visible)
-            {
-                /* Found, and the visibility changed.  Do a relayout. */
-                ige->visible = visible;
-                if ( ! ige->visible)
-                    gtk_widget_hide(ige->widget);
-                icon_grid_demand_resize(ig);
-            }
-            break;
+            ig->spacing = spacing;
+            g_object_notify(object, "spacing");
+            gtk_widget_queue_resize(GTK_WIDGET(ig));
         }
+        break;
+    case PROP_CONSTRAIN_WIDTH:
+        panel_icon_grid_set_constrain_width(ig, g_value_get_boolean(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
     }
 }
 
-/* Deallocate the icon grid structures. */
-void icon_grid_free(IconGrid * ig)
+static void panel_icon_grid_get_property(GObject *object, guint prop_id,
+                                         GValue *value, GParamSpec *pspec)
 {
-    /* Hide the layout container. */
-    if (ig->widget != NULL)
+    PanelIconGrid *ig = PANEL_ICON_GRID(object);
+
+    switch (prop_id)
     {
-        g_object_remove_weak_pointer(G_OBJECT(ig->widget), (gpointer*)&ig->widget);
-        gtk_widget_hide(ig->widget);
+    case PROP_ORIENTATION:
+        g_value_set_enum(value, ig->orientation);
+        break;
+    case PROP_SPACING:
+        g_value_set_int(value, ig->spacing);
+        break;
+    case PROP_CONSTRAIN_WIDTH:
+        g_value_set_boolean(value, ig->constrain_width);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
     }
+}
 
-    /* Free all memory. */
-    IconGridElement * ige = ig->child_list;
-    while (ige != NULL)
+static void panel_icon_grid_forall(GtkContainer *container,
+                                   gboolean      include_internals,
+                                   GtkCallback   callback,
+                                   gpointer      callback_data)
+{
+    PanelIconGrid *ig = PANEL_ICON_GRID(container);
+    GList *children = ig->children;
+    GtkWidget *child;
+
+    while (children)
     {
-        IconGridElement * ige_succ = ige->flink;
-        g_free(ige);
-        ige = ige_succ;
+        child = children->data;
+        children = children->next;
+        (* callback)(child, callback_data);
     }
-    g_free(ig);
+}
+
+static GType panel_icon_grid_child_type(GtkContainer *container)
+{
+    return GTK_TYPE_WIDGET;
+}
+
+static void panel_icon_grid_class_init(PanelIconGridClass *class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(class);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class);
+    GtkContainerClass *container_class = GTK_CONTAINER_CLASS(class);
+
+    object_class->set_property = panel_icon_grid_set_property;
+    object_class->get_property = panel_icon_grid_get_property;
+
+    widget_class->size_request = panel_icon_grid_size_request;
+    widget_class->size_allocate = panel_icon_grid_size_allocate;
+
+    container_class->add = panel_icon_grid_add;
+    container_class->remove = panel_icon_grid_remove;
+    container_class->forall = panel_icon_grid_forall;
+    container_class->child_type = panel_icon_grid_child_type;
+
+    g_object_class_override_property(object_class,
+                                     PROP_ORIENTATION,
+                                     "orientation");
+    g_object_class_install_property(object_class,
+                                    PROP_SPACING,
+                                    g_param_spec_int("spacing",
+                                                     "Spacing",
+                                                     "The amount of space between children",
+                                                     0,
+                                                     G_MAXINT,
+                                                     0,
+                                                     G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_CONSTRAIN_WIDTH,
+                                    g_param_spec_boolean("constrain-width",
+                                                         "Constrain width",
+                                                         "Whether to constrain width by allocated space",
+                                                         FALSE, G_PARAM_READWRITE));
+}
+
+static void panel_icon_grid_init(PanelIconGrid *ig)
+{
+    gtk_widget_set_has_window(GTK_WIDGET(ig), FALSE);
+    gtk_widget_set_redraw_on_allocate(GTK_WIDGET(ig), FALSE);
+
+    ig->orientation = GTK_ORIENTATION_HORIZONTAL;
+}
+
+/* Establish an icon grid in a specified container widget.
+ * The icon grid manages the contents of the container.
+ * The orientation, geometry of the elements, and spacing can be varied.  All elements are the same size. */
+GtkWidget * panel_icon_grid_new(
+    GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension)
+{
+    /* Create a structure representing the icon grid and collect the parameters. */
+    PanelIconGrid * ig = g_object_new(PANEL_TYPE_ICON_GRID,
+                                      "orientation", orientation,
+                                      "spacing", spacing, NULL);
+
+    ig->child_width = child_width;
+    ig->constrained_child_width = child_width;
+    ig->child_height = child_height;
+    ig->border = border;
+    ig->target_dimension = target_dimension;
+
+    return (GtkWidget *)ig;
 }
index aeb673c..a12ce22 100644 (file)
 
 #include <gtk/gtk.h>
 
-#include "panel.h"
-
-struct _icon_grid_element;
-struct _icon_grid;
-
-/* Representative of an icon grid element.  This is a widget to be packed into a rectangular grid whose size adapts to conditions. */
-typedef struct _icon_grid_element {
-    struct _icon_grid_element * flink;         /* Forward link */
-    struct _icon_grid * ig;                    /* Back pointer to IconGrid */
-    GtkWidget * widget;                                /* Customer's widget */
-    gboolean visible;                          /* True if widget is visible */
-} IconGridElement;
-
-/* Representative of an icon grid.  This is a manager that packs widgets into a rectangular grid whose size adapts to conditions. */
-typedef struct _icon_grid {
-    IconGridElement * child_list;              /* List of icon grid elements */
-    Panel * panel;                             /* Back pointer to panel */
-    GtkWidget * container;                     /* Container widget */
-    GtkOrientation orientation;                        /* Desired orientation */
-    gint child_width;                          /* Desired child width */
-    gint child_height;                         /* Desired child height */
-    gint spacing;                              /* Desired spacing between grid elements */
-    gint border;                               /* Desired border around grid elements */
-    gint target_dimension;                     /* Desired dimension perpendicular to orientation */
-    gboolean constrain_width;                  /* True if width should be constrained by allocated space */
-    gboolean actual_dimension;                 /* True if container has been allocated space */
-    gboolean children_changed;                 /* True if icon grid element list changed */
-    GtkWidget * widget;                                /* Layout widget we use for packing */
-    int rows;                                  /* Computed layout rows */
-    int columns;                               /* Computed layout columns */
-    int container_width;                       /* Container's allocated width */
-    int container_height;                      /* Container's allocated height */
-    int constrained_child_width;               /* Child width constrained by allocation */
-} IconGrid;
-
-extern IconGrid * icon_grid_new(
-    Panel * panel, GtkWidget * container,
+#define PANEL_TYPE_ICON_GRID               (panel_icon_grid_get_type())
+#define PANEL_ICON_GRID(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+                                            PANEL_TYPE_ICON_GRID, PanelIconGrid))
+#define PANEL_ICON_GRID_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), \
+                                            PANEL_TYPE_ICON_GRID, PanelIconGridClass))
+#define PANEL_IS_ICON_GRID(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                                            PANEL_TYPE_ICON_GRID))
+#define PANEL_IS_ICON_GRID_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+                                            PANEL_TYPE_ICON_GRID), PanelIconGrid)
+
+extern GType panel_icon_grid_get_type   (void) G_GNUC_CONST;
+
+typedef struct _PanelIconGrid           PanelIconGrid;
+typedef struct _PanelIconGridClass      PanelIconGridClass;
+
+extern GtkWidget * panel_icon_grid_new(
     GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension);
                                                /* Create an icon grid */
-extern void icon_grid_set_constrain_width(IconGrid * ig, gboolean constrain_width);
+extern void panel_icon_grid_set_constrain_width(PanelIconGrid * ig, gboolean constrain_width);
                                                /* Set the constrain-width property */
-extern void icon_grid_set_geometry(IconGrid * ig,
+extern void panel_icon_grid_set_geometry(PanelIconGrid * ig,
     GtkOrientation orientation, gint child_width, gint child_height, gint spacing, gint border, gint target_dimension);
                                                /* Change the geometry of an icon grid */
-extern void icon_grid_add(IconGrid * ig, GtkWidget * child, gboolean visible);
-                                               /* Add a child to the icon grid */
-extern void icon_grid_remove(IconGrid * ig, GtkWidget * child);
-                                               /* Remove a child from the icon grid */
-extern gint icon_grid_get_child_position(IconGrid * ig, GtkWidget * child);
+extern gint panel_icon_grid_get_child_position(PanelIconGrid * ig, GtkWidget * child);
                                                /* Get the index of an icon grid element. */
-extern void icon_grid_reorder_child(IconGrid * ig, GtkWidget * child, gint position);
+extern void panel_icon_grid_reorder_child(PanelIconGrid * ig, GtkWidget * child, gint position);
                                                /* Reorder the position of a child in the icon grid */
-extern void icon_grid_set_visible(IconGrid * ig, GtkWidget * child, gboolean visible);
-                                               /* Set the visibility of a child in the icon grid */
-extern void icon_grid_free(IconGrid * ig);     /* Free the icon grid */
 
 #endif
index b7e69ce..bd60e01 100644 (file)
@@ -65,7 +65,6 @@ static int xkb_error_base = 0;
 typedef struct {
     Panel * panel;                             /* Back pointer to panel */
     config_setting_t *settings;
-    IconGrid * icon_grid;                      /* Icon grid manager */
     GtkWidget *indicator_image[3];             /* Image for each indicator */
     unsigned int current_state;                        /* Current LED state, bit encoded */
     gboolean visible[3];                       /* True if control is visible (per user configuration) */
@@ -154,21 +153,20 @@ static GtkWidget *kbled_constructor(Panel *panel, config_setting_t *settings)
         kl->visible[2] = i != 0;
 
     /* Allocate top level widget and set into Plugin widget pointer. */
-    p = gtk_event_box_new();
+    p = panel_icon_grid_new(panel_get_orientation(panel),
+                            panel_get_icon_size(panel),
+                            panel_get_icon_size(panel),
+                            0, 0, panel_get_height(panel));
     lxpanel_plugin_set_data(p, kl, kbled_destructor);
     gtk_widget_add_events(p, GDK_BUTTON_PRESS_MASK);
     g_signal_connect(panel_get_icon_theme(panel), "changed", G_CALLBACK(kbled_theme_changed), kl);
 
-    /* Allocate an icon grid manager to manage the container.
-     * Then allocate three images for the three indications, but make them visible only when the configuration requests. */
-    kl->icon_grid = icon_grid_new(panel, p, panel_get_orientation(panel),
-                                  panel_get_icon_size(panel),
-                                  panel_get_icon_size(panel),
-                                  0, 0, panel_get_height(panel));
+    /* Then allocate three images for the three indications, but make them visible only when the configuration requests. */
     for (i = 0; i < 3; i++)
     {
         kl->indicator_image[i] = gtk_image_new();
-        icon_grid_add(kl->icon_grid, kl->indicator_image[i], kl->visible[i]);
+        gtk_container_add(GTK_CONTAINER(p), kl->indicator_image[i]);
+        gtk_widget_set_visible(kl->indicator_image[i], kl->visible[i]);
     }
 
     /* Initialize Xkb extension if not yet done. */
@@ -207,7 +205,6 @@ static void kbled_destructor(gpointer user_data)
     gdk_window_remove_filter(NULL, (GdkFilterFunc) kbled_event_filter, kl);
     g_signal_handlers_disconnect_by_func(panel_get_icon_theme(kl->panel),
                                          kbled_theme_changed, kl);
-    icon_grid_free(kl->icon_grid);
     g_free(kl);
 }
 
@@ -218,7 +215,7 @@ static gboolean kbled_apply_configuration(gpointer user_data)
     int i;
 
     for (i = 0; i < 3; i++)
-        icon_grid_set_visible(kl->icon_grid, kl->indicator_image[i], kl->visible[i]);
+        gtk_widget_set_visible(kl->indicator_image[i], kl->visible[i]);
     config_group_set_int(kl->settings, "ShowCapsLock", kl->visible[0]);
     config_group_set_int(kl->settings, "ShowNumLock", kl->visible[1]);
     config_group_set_int(kl->settings, "ShowScrollLock", kl->visible[2]);
@@ -245,9 +242,10 @@ static void kbled_panel_configuration_changed(Panel *panel, GtkWidget *p)
     /* Set orientation into the icon grid. */
     KeyboardLEDPlugin * kl = lxpanel_plugin_get_data(p);
 
-    icon_grid_set_geometry(kl->icon_grid, panel_get_orientation(panel),
-                           panel_get_icon_size(panel), panel_get_icon_size(panel),
-                           0, 0, panel_get_height(panel));
+    panel_icon_grid_set_geometry(PANEL_ICON_GRID(p), panel_get_orientation(panel),
+                                 panel_get_icon_size(panel),
+                                 panel_get_icon_size(panel),
+                                 0, 0, panel_get_height(panel));
 
     /* Do a full redraw. */
     int current_state = kl->current_state;
index 9c06406..f95b06e 100644 (file)
@@ -135,7 +135,7 @@ typedef struct {
 /* Private context for taskbar plugin. */
 struct LaunchTaskBarPlugin {
     /* LAUNCHBAR */
-    IconGrid      *lb_icon_grid;     /* Icon grid managing the container */
+    GtkWidget *lb_icon_grid;         /* Icon grid managing the container */
     GSList        *buttons;          /* Launchbar buttons */
     LaunchButton  *bootstrap_button; /* Bootstrapping button for empty launchtaskbar */
     FmIcon * add_icon;                  /* Icon for bootstrap_button */
@@ -143,7 +143,7 @@ struct LaunchTaskBarPlugin {
     /* TASKBAR */
     Task * p_task_list;            /* List of tasks to be displayed in taskbar */
     TaskClass * p_taskclass_list;  /* Window class list */
-    IconGrid * tb_icon_grid;       /* Manager for taskbar buttons */
+    GtkWidget * tb_icon_grid;      /* Manager for taskbar buttons */
     GtkWidget * menu;              /* Popup menu for task control (Close, Raise, etc.) */
     GtkWidget * group_menu;        /* Popup menu for grouping selection */
     GtkWidget * workspace_menu0;   /* "Workspace 1" menu item */
@@ -178,8 +178,6 @@ struct LaunchTaskBarPlugin {
     Panel * panel;                      /* Back pointer to panel */
     config_setting_t * settings;
     GdkScreen       *screen;
-    GtkWidget       *p_evbox_launchbar;
-    GtkWidget       *p_evbox_taskbar;
     GtkWidget       *config_dlg;        /* Configuration dialog */
     GtkNotebook     *p_notebook;
     GtkWidget       *p_notebook_page_launch;
@@ -399,10 +397,11 @@ static void launchbutton_build_bootstrap(LaunchTaskBarPlugin *lb)
         gtk_container_add(GTK_CONTAINER(event_box), lb->bootstrap_button->image_widget);
 
         /* Add the bootstrap button to the icon grid.  By policy it is empty at this point. */
-        icon_grid_add(lb->lb_icon_grid, event_box, TRUE);
+        gtk_container_add(GTK_CONTAINER(lb->lb_icon_grid), event_box);
+        gtk_widget_show(event_box);
     }
     else
-        icon_grid_set_visible(lb->lb_icon_grid, lb->bootstrap_button->widget, TRUE);
+        gtk_widget_show(lb->bootstrap_button->widget);
 }
 
 #ifndef DISABLE_MENU
@@ -504,7 +503,8 @@ static LaunchButton *launchbutton_for_file_info(LaunchTaskBarPlugin * lb, FmFile
     gtk_widget_set_tooltip_text(button, fm_file_info_get_disp_name(fi));
 
     /* Add the button to the icon grid. */
-    icon_grid_add(lb->lb_icon_grid, button, TRUE);
+    gtk_container_add(GTK_CONTAINER(lb->lb_icon_grid), button);
+    gtk_widget_show(button);
 
     /* Drag and drop support. */
     btn->dd = fm_dnd_dest_new_with_handlers(button);
@@ -515,7 +515,7 @@ static LaunchButton *launchbutton_for_file_info(LaunchTaskBarPlugin * lb, FmFile
 
     /* If the list goes from null to non-null, remove the bootstrap button. */
     if ((lb->buttons == NULL) && (lb->bootstrap_button != NULL))
-        icon_grid_set_visible(lb->lb_icon_grid, lb->bootstrap_button->widget, FALSE);
+        gtk_widget_show(lb->bootstrap_button->widget);
 
     /* Append at end of list to preserve configured order. */
     lb->buttons = g_slist_append(lb->buttons, btn);
@@ -666,15 +666,6 @@ static void launchtaskbar_constructor_launch(LaunchTaskBarPlugin *ltbp, gboolean
     if(!ltbp->lb_built)
     {
         ltbp->lb_built = TRUE;
-        if(ltbp->lb_icon_grid == NULL)
-        {
-            /* Allocate an icon grid manager to manage the container. */
-            ltbp->lb_icon_grid = icon_grid_new(ltbp->panel, ltbp->p_evbox_launchbar,
-                                               panel_get_orientation(ltbp->panel),
-                                               ltbp->icon_size, ltbp->icon_size,
-                                               3, 0,
-                                               panel_get_height(ltbp->panel));
-        }
         /* Read parameters from the configuration file. */
         settings = config_setting_get_member(ltbp->settings, "");
         if (settings && config_setting_is_list(settings))
@@ -707,10 +698,7 @@ static void launchtaskbar_constructor_launch(LaunchTaskBarPlugin *ltbp, gboolean
                 launchbutton_build_bootstrap(ltbp);
         }
     }
-    else
-    {
-        gtk_widget_set_visible(ltbp->p_evbox_launchbar, TRUE);
-    }
+    gtk_widget_set_visible(ltbp->lb_icon_grid, TRUE);
 }
 
 static void launchtaskbar_constructor_task(LaunchTaskBarPlugin *ltbp)
@@ -743,12 +731,13 @@ static void launchtaskbar_constructor_task(LaunchTaskBarPlugin *ltbp)
             ltbp->grouped_tasks = (tmp_int != 0);
 
         /* Make container for task buttons as a child of top level widget. */
-        ltbp->tb_icon_grid = icon_grid_new(ltbp->panel, ltbp->p_evbox_taskbar,
-                                           panel_get_orientation(ltbp->panel),
-                                           ltbp->task_width_max, ltbp->icon_size,
-                                           ltbp->spacing, 0,
-                                           panel_get_height(ltbp->panel));
-        icon_grid_set_constrain_width(ltbp->tb_icon_grid, TRUE);
+        ltbp->tb_icon_grid = panel_icon_grid_new(panel_get_orientation(ltbp->panel),
+                                                 ltbp->task_width_max,
+                                                 ltbp->icon_size, ltbp->spacing, 0,
+                                                 panel_get_height(ltbp->panel));
+        panel_icon_grid_set_constrain_width(PANEL_ICON_GRID(ltbp->tb_icon_grid), TRUE);
+        gtk_box_pack_start(GTK_BOX(ltbp->plugin), ltbp->tb_icon_grid, TRUE, TRUE, 0);
+        gtk_container_set_border_width(GTK_CONTAINER(ltbp->tb_icon_grid), 0);
         taskbar_update_style(ltbp);
 
         /* Add GDK event filter. */
@@ -774,10 +763,7 @@ static void launchtaskbar_constructor_task(LaunchTaskBarPlugin *ltbp)
         taskbar_net_client_list(NULL, ltbp);
         taskbar_net_active_window(NULL, ltbp);
     }
-    else
-    {
-        gtk_widget_set_visible(ltbp->p_evbox_taskbar, TRUE);
-    }
+    gtk_widget_set_visible(ltbp->tb_icon_grid, TRUE);
 }
 
 /* Plugin constructor. */
@@ -828,14 +814,14 @@ static GtkWidget *_launchtaskbar_constructor(Panel *panel, config_setting_t *set
     /* Allocate top level widget and set into Plugin widget pointer. */
     ltbp->plugin = p = panel_box_new(panel, FALSE, 5);
     lxpanel_plugin_set_data(p, ltbp, launchtaskbar_destructor);
-    ltbp->p_evbox_launchbar = gtk_event_box_new();
-    ltbp->p_evbox_taskbar = gtk_event_box_new();
-    gtk_box_pack_start(GTK_BOX(p), ltbp->p_evbox_launchbar, FALSE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(p), ltbp->p_evbox_taskbar, TRUE, TRUE, 0);
+    /* Allocate an icon grid manager to manage the container. */
+    ltbp->lb_icon_grid = panel_icon_grid_new(panel_get_orientation(panel),
+                                             ltbp->icon_size, ltbp->icon_size,
+                                             3, 0, panel_get_height(panel));
+    gtk_box_pack_start(GTK_BOX(p), ltbp->lb_icon_grid, FALSE, TRUE, 0);
 
     gtk_container_set_border_width(GTK_CONTAINER(p), 0);
-    gtk_container_set_border_width(GTK_CONTAINER(ltbp->p_evbox_launchbar), 0);
-    gtk_container_set_border_width(GTK_CONTAINER(ltbp->p_evbox_taskbar), 0);
+    gtk_container_set_border_width(GTK_CONTAINER(ltbp->lb_icon_grid), 0);
     gtk_widget_set_has_window(p, FALSE);
 
     /* Read parameters from the configuration file. */
@@ -868,8 +854,6 @@ static void launchtaskbar_destructor_launch(LaunchTaskBarPlugin *ltbp)
 {
     /* Free the launchbar. */
     g_slist_foreach(ltbp->buttons, (GFunc) launchbutton_free, NULL);
-    icon_grid_free(ltbp->lb_icon_grid);
-    ltbp->lb_icon_grid = NULL;
 
     /* Free the bootstrap button if it exists. */
     if(ltbp->bootstrap_button != NULL)
@@ -911,7 +895,6 @@ static void launchtaskbar_destructor_task(LaunchTaskBarPlugin *ltbp)
 
     /* Deallocate other memory. */
     gtk_widget_destroy(ltbp->menu);
-    icon_grid_free(ltbp->tb_icon_grid);
 }
 
 /* Plugin destructor. */
@@ -972,7 +955,7 @@ static void launchbar_configure_add_button(GtkButton * widget, LaunchTaskBarPlug
 
 static void  launchbar_remove_button(LaunchTaskBarPlugin *ltbp, LaunchButton *btn)
 {
-    icon_grid_remove(ltbp->lb_icon_grid, btn->widget);
+    gtk_container_remove(GTK_CONTAINER(ltbp->lb_icon_grid), btn->widget);
     ltbp->buttons = g_slist_remove(ltbp->buttons, btn);
     config_setting_destroy(btn->settings);
     launchbutton_free(btn);
@@ -1024,7 +1007,8 @@ static void launchbar_configure_move_up_button(GtkButton * widget, LaunchTaskBar
                 ltbp->buttons = g_slist_remove(ltbp->buttons, btn);
                 ltbp->buttons = g_slist_insert(ltbp->buttons, btn, i);
                 gtk_list_store_move_before(GTK_LIST_STORE(list), &it, &it2);
-                icon_grid_reorder_child(ltbp->lb_icon_grid, btn->widget, i);
+                panel_icon_grid_reorder_child(PANEL_ICON_GRID(ltbp->lb_icon_grid),
+                                              btn->widget, i);
                 config_setting_move_elem(btn->settings,
                                          config_setting_get_parent(btn->settings),
                                          i);
@@ -1058,7 +1042,8 @@ static void launchbar_configure_move_down_button(GtkButton * widget, LaunchTaskB
                 ltbp->buttons = g_slist_remove(ltbp->buttons, btn);
                 ltbp->buttons = g_slist_insert(ltbp->buttons, btn, i + 1);
                 gtk_list_store_move_after(GTK_LIST_STORE(list), &it, &it2);
-                icon_grid_reorder_child( ltbp->lb_icon_grid, btn->widget, i);
+                panel_icon_grid_reorder_child(PANEL_ICON_GRID(ltbp->lb_icon_grid),
+                                              btn->widget, i);
                 config_setting_move_elem(btn->settings,
                                          config_setting_get_parent(btn->settings),
                                          i);
@@ -1155,13 +1140,14 @@ static void on_combobox_mode_changed(GtkComboBox *p_combobox, gpointer p_data)
 
     switch (ltbp->mode) {
     case LAUNCHBAR:
-        gtk_widget_set_visible(ltbp->p_evbox_taskbar, FALSE);
+        if (ltbp->tb_icon_grid)
+            gtk_widget_set_visible(ltbp->tb_icon_grid, FALSE);
         launchtaskbar_constructor_launch(ltbp, TRUE/*build_bootstrap*/);
         plugin_set_expand_status(ltbp, FALSE);
         gtk_widget_set_name(ltbp->plugin, "launchbar");
         break;
     case TASKBAR:
-        gtk_widget_set_visible(ltbp->p_evbox_launchbar, FALSE);
+        gtk_widget_set_visible(ltbp->lb_icon_grid, FALSE);
         launchtaskbar_constructor_task(ltbp);
         plugin_set_expand_status(ltbp, TRUE);
         gtk_widget_set_name(ltbp->plugin, "taskbar");
@@ -1453,9 +1439,10 @@ static void launchtaskbar_panel_configuration_changed(Panel *panel, GtkWidget *p
     int new_icon_size = panel_get_icon_size(panel);
 
     if (ltbp->lb_built)
-        icon_grid_set_geometry(ltbp->lb_icon_grid, panel_get_orientation(panel),
-                               new_icon_size, new_icon_size, 3, 0,
-                               panel_get_height(panel));
+        panel_icon_grid_set_geometry(PANEL_ICON_GRID(ltbp->lb_icon_grid),
+                                     panel_get_orientation(panel),
+                                     new_icon_size, new_icon_size, 3, 0,
+                                     panel_get_height(panel));
 
     /* Reset the bootstrap button. */
     if (ltbp->bootstrap_button != NULL)
@@ -1645,10 +1632,10 @@ static void task_button_redraw(Task * tk, LaunchTaskBarPlugin * tb)
     if (task_is_visible(tb, tk))
     {
         task_draw_label(tk);
-        icon_grid_set_visible(tb->tb_icon_grid, tk->button, TRUE);
+        gtk_widget_set_visible(tk->button, TRUE);
     }
     else
-        icon_grid_set_visible(tb->tb_icon_grid, tk->button, FALSE);
+        gtk_widget_set_visible(tk->button, FALSE);
 }
 
 /* Redraw all tasks in the taskbar. */
@@ -1883,7 +1870,7 @@ static void task_delete(LaunchTaskBarPlugin * tb, Task * tk, gboolean unlink, gb
     /* Deallocate structures. */
     if (remove)
     {
-        icon_grid_remove(tb->tb_icon_grid, tk->button);
+        gtk_container_remove(GTK_CONTAINER(tb->tb_icon_grid), tk->button);
         task_unlink_class(tk);
     }
     task_free_names(tk);
@@ -2618,8 +2605,9 @@ static gboolean taskbar_button_drag_drop(GtkWidget * widget, GdkDragContext * dr
     {
         if (drag_source != tk->button)
         {
-            gint i = icon_grid_get_child_position(tk->tb->tb_icon_grid, tk->button);
-            icon_grid_reorder_child(tk->tb->tb_icon_grid, drag_source, i);
+            PanelIconGrid *ig = PANEL_ICON_GRID(tk->tb->tb_icon_grid);
+            gint i = panel_icon_grid_get_child_position(ig, tk->button);
+            panel_icon_grid_reorder_child(ig, drag_source, i);
         }
         gtk_drag_finish(drag_context, TRUE, TRUE, time);
         return TRUE;
@@ -2708,7 +2696,8 @@ static void taskbar_button_size_allocate(GtkWidget * btn, GtkAllocation * alloc,
 /* Update style on the taskbar when created or after a configuration change. */
 static void taskbar_update_style(LaunchTaskBarPlugin * tb)
 {
-    icon_grid_set_geometry(tb->tb_icon_grid, panel_get_orientation(tb->panel),
+    panel_icon_grid_set_geometry(PANEL_ICON_GRID(tb->tb_icon_grid),
+        panel_get_orientation(tb->panel),
         ((tb->icons_only) ? tb->icon_size + ICON_ONLY_EXTRA : tb->task_width_max),
         tb->icon_size, tb->spacing, 0, panel_get_height(tb->panel));
 }
@@ -2800,12 +2789,13 @@ static void task_build_gui(LaunchTaskBarPlugin * tb, Task * tk)
     gtk_box_pack_start(GTK_BOX(container), tk->label, TRUE, TRUE, 0);
 
     /* Add the box to the button. */
-    gtk_widget_show(container);
     gtk_container_add(GTK_CONTAINER(tk->button), container);
+//    gtk_widget_show(container);
     gtk_container_set_border_width(GTK_CONTAINER(tk->button), 0);
 
     /* Add the button to the taskbar. */
-    icon_grid_add(tb->tb_icon_grid, tk->button, TRUE);
+    gtk_container_add(GTK_CONTAINER(tb->tb_icon_grid), tk->button);
+    gtk_widget_show_all(tk->button);
     gtk_widget_set_can_focus(GTK_WIDGET(tk->button),FALSE);
     gtk_widget_set_can_default(GTK_WIDGET(tk->button),FALSE);
 
index 840a55b..7694941 100644 (file)
@@ -74,7 +74,6 @@ typedef struct _tray_client {
 typedef struct _tray_plugin {
     GtkWidget * plugin;                                /* Back pointer to Plugin */
     Panel * panel;
-    IconGrid * icon_grid;                      /* Icon grid to manage tray presentation */
     TrayClient * client_list;                  /* List of tray clients */
     BalloonMessage * incomplete_messages;      /* List of balloon messages for which we are awaiting data */
     BalloonMessage * messages;                 /* List of balloon messages actively being displayed or waiting to be displayed */
@@ -151,7 +150,7 @@ static void client_delete(TrayPlugin * tr, TrayClient * tc, gboolean unlink, gbo
 
     /* Remove the socket from the icon grid. */
     if (remove)
-        icon_grid_remove(tr->icon_grid, tc->socket);
+        gtk_container_remove(GTK_CONTAINER(tr->plugin), tc->socket);
 
     /* Deallocate the client structure. */
     g_free(tc);
@@ -215,8 +214,8 @@ static void balloon_message_display(TrayPlugin * tr, BalloonMessage * msg)
     GtkWidget * balloon_text = gtk_label_new(msg->string);
     gtk_label_set_line_wrap(GTK_LABEL(balloon_text), TRUE);
     gtk_misc_set_alignment(GTK_MISC(balloon_text), 0.5, 0.5);
-    gtk_widget_show(balloon_text);
     gtk_container_add(GTK_CONTAINER(tr->balloon_message_popup), balloon_text);
+    gtk_widget_show(balloon_text);
     gtk_container_set_border_width(GTK_CONTAINER(tr->balloon_message_popup), 4);
 
     /* Connect signals.  Clicking the popup dismisses it and displays the next message, if any. */
@@ -445,7 +444,8 @@ static void trayclient_request_dock(TrayPlugin * tr, XClientMessageEvent * xeven
     }
 
     /* Add the socket to the icon grid. */
-    icon_grid_add(tr->icon_grid, tc->socket, TRUE);
+    gtk_container_add(GTK_CONTAINER(tr->plugin), tc->socket);
+    gtk_widget_show(tc->socket);
 
     /* Connect the socket to the plug.  This can only be done after the socket is realized. */
     gtk_socket_add_id(GTK_SOCKET(tc->socket), tc->window);
@@ -454,7 +454,7 @@ static void trayclient_request_dock(TrayPlugin * tr, XClientMessageEvent * xeven
     /* Checks if the plug has been created inside of the socket. */
     if (gtk_socket_get_plug_window ( GTK_SOCKET(tc->socket) ) == NULL) {
         //fprintf(stderr, "Notice: removing plug %ud\n", tc->window );
-        icon_grid_remove(tr->icon_grid, tc->socket);
+        gtk_container_remove(GTK_CONTAINER(tr->plugin), tc->socket);
         return;
     }
 }
@@ -628,16 +628,14 @@ static GtkWidget *tray_constructor(Panel *panel, config_setting_t *settings)
     tr->invisible_window = GDK_WINDOW_XWINDOW(gtk_widget_get_window(invisible));
 
     /* Allocate top level widget and set into Plugin widget pointer. */
-    tr->plugin = p = gtk_event_box_new();
+    tr->plugin = p = panel_icon_grid_new(panel_get_orientation(panel),
+                                         panel_get_icon_size(panel),
+                                         panel_get_icon_size(panel),
+                                         3, 0, panel_get_height(panel));
     lxpanel_plugin_set_data(p, tr, tray_destructor);
-    gtk_widget_set_has_window(p,FALSE);
     gtk_widget_set_name(p, "tray");
     gtk_container_set_border_width(GTK_CONTAINER(p), 1);
 
-    /* Create an icon grid to manage the container. */
-    tr->icon_grid = icon_grid_new(panel, p, panel_get_orientation(panel),
-                                  panel_get_icon_size(panel), panel_get_icon_size(panel),
-                                  3, 0, panel_get_height(panel));
     return p;
 }
 
@@ -668,10 +666,6 @@ static void tray_destructor(gpointer user_data)
     while (tr->client_list != NULL)
         client_delete(tr, tr->client_list, TRUE, FALSE);
 
-    /* Deallocate memory. */
-    if (tr->icon_grid != NULL)
-        icon_grid_free(tr->icon_grid);
-
     g_free(tr);
 }
 
@@ -679,13 +673,10 @@ static void tray_destructor(gpointer user_data)
 static void tray_panel_configuration_changed(Panel *panel, GtkWidget *p)
 {
     /* Set orientation into the icon grid. */
-    TrayPlugin * tr = lxpanel_plugin_get_data(p);
-    if (tr->icon_grid != NULL)
-    {
-        icon_grid_set_geometry(tr->icon_grid, panel_get_orientation(panel),
-                               panel_get_icon_size(panel), panel_get_icon_size(panel),
-                               3, 0, panel_get_height(panel));
-    }
+    panel_icon_grid_set_geometry(PANEL_ICON_GRID(p), panel_get_orientation(panel),
+                                 panel_get_icon_size(panel),
+                                 panel_get_icon_size(panel),
+                                 3, 0, panel_get_height(panel));
 }
 
 /* Plugin descriptor. */