libegg r835 - in trunk: . libegg/toolpalette



Author: hasselmm
Date: Thu Jan 10 22:49:41 2008
New Revision: 835
URL: http://svn.gnome.org/viewvc/libegg?rev=835&view=rev

Log:
Refactor EggToolPaletteCategory into EggToolItemGroup widget.

* libegg/toolpalette/eggtoolitemgroup.c,
libegg/toolpalette/eggtoolitemgroup.h:
Create EggToolItemGroup from EggToolPaletteCategory structure.
* libegg/toolpalette/eggtoolpalette.c,
libegg/toolpalette/eggtoolpalette.h:
Remove EggToolPaletteCategory and use EggToolItemGroup instead.
* libegg/toolpalette/eggtoolpaletteprivate.h:
Collect internal EggToolPalette and EggToolItemGroup functions.
* libegg/toolpalette/Makefile.am: Add eggtoolitemgroup.c.
* libegg/toolpalette/testtoolpalette.c:
Adopt EggToolItemGroup changes.


Added:
   trunk/libegg/toolpalette/eggtoolitemgroup.c
   trunk/libegg/toolpalette/eggtoolitemgroup.h
   trunk/libegg/toolpalette/eggtoolpaletteprivate.h
Modified:
   trunk/ChangeLog
   trunk/libegg/toolpalette/Makefile.am
   trunk/libegg/toolpalette/eggtoolpalette.c
   trunk/libegg/toolpalette/eggtoolpalette.h
   trunk/libegg/toolpalette/testtoolpalette.c

Modified: trunk/libegg/toolpalette/Makefile.am
==============================================================================
--- trunk/libegg/toolpalette/Makefile.am	(original)
+++ trunk/libegg/toolpalette/Makefile.am	Thu Jan 10 22:49:41 2008
@@ -9,7 +9,7 @@
 noinst_LTLIBRARIES = libeggtoolpalette.la
 noinst_PROGRAMS = testtoolpalette
 
-libeggtoolpalette_la_SOURCES = eggtoolpalette.c
+libeggtoolpalette_la_SOURCES = eggtoolpalette.c eggtoolitemgroup.c
 
 testtoolpalette_SOURCES = testtoolpalette.c
 testtoolpalette_LDFLAGS = libeggtoolpalette.la ../util/libeggutil.la $(EGG_LIBS)

Added: trunk/libegg/toolpalette/eggtoolitemgroup.c
==============================================================================
--- (empty file)
+++ trunk/libegg/toolpalette/eggtoolitemgroup.c	Thu Jan 10 22:49:41 2008
@@ -0,0 +1,704 @@
+/* EggToolPalette -- A tool palette with categories and DnD support
+ * Copyright (C) 2008  Openismus GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *      Mathias Hasselmann
+ */
+
+#include "eggtoolitemgroup.h"
+#include "eggtoolpaletteprivate.h"
+
+#include <glib/gi18n.h>
+
+#include <gtk/gtkalignment.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtklabel.h>
+
+#include <string.h>
+
+#define DEFAULT_EXPANDER_SIZE   16
+#define DEFAULT_HEADER_SPACING  2
+
+#define P_(msgid) _(msgid)
+
+enum
+{
+  PROP_NONE,
+  PROP_NAME,
+  PROP_EXPANED,
+};
+
+struct _EggToolItemGroupPrivate
+{
+  GtkWidget        *header;
+  GArray           *items;
+
+  guint             animation_timeout;
+  GtkExpanderStyle  expander_style;
+  gint              expander_size;
+  gint              header_spacing;
+
+  guint             expanded : 1;
+};
+
+G_DEFINE_TYPE (EggToolItemGroup,
+               egg_tool_item_group,
+               GTK_TYPE_CONTAINER);
+
+static gboolean
+egg_tool_item_group_header_expose_event_cb (GtkWidget      *widget,
+                                            GdkEventExpose *event,
+                                            gpointer        data)
+{
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (data);
+
+  gint x = widget->allocation.x + group->priv->expander_size / 2;
+  gint y = widget->allocation.y + widget->allocation.height / 2;
+
+  gtk_paint_expander (widget->style, widget->window,
+                      group->priv->header->state,
+                      &event->area, GTK_WIDGET (group),
+                      "tool-palette-header", x, y,
+                      group->priv->expander_style);
+
+  return FALSE;
+}
+
+static void
+egg_tool_item_group_header_size_request_cb (GtkWidget      *widget G_GNUC_UNUSED,
+                                            GtkRequisition *requisition,
+                                            gpointer        data)
+{
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (data);
+  requisition->height = MAX (requisition->height, group->priv->expander_size);
+}
+
+static void
+egg_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED,
+                                       gpointer   data)
+{
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (data);
+  egg_tool_item_group_set_expanded (group, !group->priv->expanded);
+}
+
+static void
+egg_tool_item_group_init (EggToolItemGroup *group)
+{
+  GtkWidget *alignment;
+  GtkWidget *label;
+
+  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE);
+
+  group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
+                                            EGG_TYPE_TOOL_ITEM_GROUP,
+                                            EggToolItemGroupPrivate);
+
+  group->priv->items = g_array_new (TRUE, TRUE, sizeof (GtkToolItem*));
+  group->priv->header_spacing = DEFAULT_HEADER_SPACING;
+  group->priv->expander_size = DEFAULT_EXPANDER_SIZE;
+  group->priv->expander_style = GTK_EXPANDER_EXPANDED;
+  group->priv->expanded = TRUE;
+
+  label = gtk_label_new (NULL);
+  alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
+
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0,
+                             group->priv->header_spacing +
+                             group->priv->expander_size, 0);
+
+  gtk_container_add (GTK_CONTAINER (alignment), label);
+  gtk_widget_show_all (alignment);
+
+  gtk_widget_push_composite_child ();
+  group->priv->header = gtk_button_new ();
+  gtk_widget_set_composite_name (group->priv->header, "header");
+  gtk_widget_pop_composite_child ();
+
+  g_object_ref_sink (group->priv->header);
+  gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE);
+  gtk_container_add (GTK_CONTAINER (group->priv->header), alignment);
+  gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group));
+
+  g_signal_connect_after (alignment, "expose-event",
+                          G_CALLBACK (egg_tool_item_group_header_expose_event_cb),
+                          group);
+  g_signal_connect_after (alignment, "size-request",
+                          G_CALLBACK (egg_tool_item_group_header_size_request_cb),
+                          group);
+
+  g_signal_connect (group->priv->header, "clicked",
+                    G_CALLBACK (egg_tool_item_group_header_clicked_cb),
+                    group);
+}
+
+static void
+egg_tool_item_group_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  EggToolItemGroup *self = EGG_TOOL_ITEM_GROUP (object);
+
+  switch (prop_id)
+    {
+      case PROP_NAME:
+        egg_tool_item_group_set_name (self, g_value_get_string (value));
+        break;
+
+      case PROP_EXPANED:
+        egg_tool_item_group_set_expanded (self, g_value_get_boolean (value));
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+egg_tool_item_group_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  EggToolItemGroup *self = EGG_TOOL_ITEM_GROUP (object);
+
+  switch (prop_id)
+    {
+      case PROP_NAME:
+        g_value_set_string (value, egg_tool_item_group_get_name (self));
+        break;
+
+      case PROP_EXPANED:
+        g_value_set_boolean (value, egg_tool_item_group_get_expanded (self));
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+egg_tool_item_group_finalize (GObject *object)
+{
+  EggToolItemGroup *self = EGG_TOOL_ITEM_GROUP (object);
+
+  if (self->priv->items)
+    {
+      g_array_free (self->priv->items, TRUE);
+      self->priv->items = NULL;
+    }
+
+  G_OBJECT_CLASS (egg_tool_item_group_parent_class)->finalize (object);
+}
+
+static void
+egg_tool_item_group_size_request (GtkWidget      *widget,
+                                  GtkRequisition *requisition)
+{
+  const gint border_width = GTK_CONTAINER (widget)->border_width;
+  EggToolItemGroup *self = EGG_TOOL_ITEM_GROUP (widget);
+
+  if (self->priv->items->len && egg_tool_item_group_get_name (self))
+    {
+      gtk_widget_size_request (self->priv->header, requisition);
+      gtk_widget_show (self->priv->header);
+    }
+  else
+    {
+      requisition->width = requisition->height = 0;
+      gtk_widget_hide (self->priv->header);
+    }
+
+  requisition->width += border_width;
+  requisition->height += border_width;
+}
+
+static void
+egg_tool_item_group_size_allocate (GtkWidget     *widget,
+                                   GtkAllocation *allocation)
+{
+  const gint border_width = GTK_CONTAINER (widget)->border_width;
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (widget);
+  GtkRequisition child_requistion;
+  GtkAllocation child_allocation;
+  GtkRequisition item_size;
+  GtkWidget *parent;
+  guint i;
+
+  GTK_WIDGET_CLASS (egg_tool_item_group_parent_class)->size_allocate (widget, allocation);
+
+  parent = gtk_widget_get_parent (widget);
+
+  if (EGG_IS_TOOL_PALETTE (parent))
+    _egg_tool_palette_get_item_size (EGG_TOOL_PALETTE (parent), &item_size);
+  else
+    _egg_tool_item_group_item_size_request (group, &item_size);
+
+  child_allocation.x = border_width;
+  child_allocation.y = border_width;
+
+  if (GTK_WIDGET_VISIBLE (group->priv->header))
+    {
+      gtk_widget_size_request (group->priv->header, &child_requistion);
+
+      child_allocation.width = allocation->width;
+      child_allocation.height = child_requistion.height;
+
+      gtk_widget_size_allocate (group->priv->header, &child_allocation);
+
+      child_allocation.y += child_allocation.height;
+    }
+
+    if (group->priv->expanded)
+      {
+        for (i = 0; i < group->priv->items->len; ++i)
+          {
+            GtkToolItem *item = egg_tool_item_group_get_nth_item (group, i);
+
+            child_allocation.width = item_size.width;
+            child_allocation.height = item_size.height;
+
+            if (child_allocation.x + child_allocation.width > allocation->width)
+              {
+                child_allocation.y += child_allocation.height;
+                child_allocation.x = border_width;
+              }
+
+            gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation);
+            gtk_widget_show (GTK_WIDGET (item));
+
+            child_allocation.x += child_allocation.width;
+          }
+
+        child_allocation.y += item_size.height;
+        child_allocation.x = border_width;
+      }
+    else
+      {
+        for (i = 0; i < group->priv->items->len; ++i)
+          {
+            GtkToolItem *item = egg_tool_item_group_get_nth_item (group, i);
+            gtk_widget_hide (GTK_WIDGET (item));
+          }
+      }
+
+  if (GTK_WIDGET_MAPPED (widget))
+    gdk_window_invalidate_rect (widget->window, NULL, FALSE);
+}
+
+static void
+egg_tool_item_group_realize (GtkWidget *widget)
+{
+  const gint border_width = GTK_CONTAINER (widget)->border_width;
+  gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  GdkWindowAttr attributes;
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x + border_width;
+  attributes.y = widget->allocation.y + border_width;
+  attributes.width = widget->allocation.width - border_width * 2;
+  attributes.height = widget->allocation.height - border_width * 2;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
+                        | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+                        | GDK_BUTTON_MOTION_MASK;
+
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                                   &attributes, attributes_mask);
+
+  gdk_window_set_user_data (widget->window, widget);
+  widget->style = gtk_style_attach (widget->style, widget->window);
+  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+  gtk_container_forall (GTK_CONTAINER (widget),
+                        (GtkCallback) gtk_widget_set_parent_window,
+                        widget->window);
+
+  gtk_widget_queue_resize_no_redraw (widget);
+}
+
+static GtkWidget*
+egg_tool_item_group_get_alignment (EggToolItemGroup *group)
+{
+  return gtk_bin_get_child (GTK_BIN (group->priv->header));
+}
+
+static GtkWidget*
+egg_tool_item_group_get_label (EggToolItemGroup *group)
+{
+  GtkWidget *alignment = egg_tool_item_group_get_alignment (group);
+  return gtk_bin_get_child (GTK_BIN (alignment));
+}
+
+static void
+egg_tool_item_group_style_set (GtkWidget *widget,
+                               GtkStyle  *previous_style)
+{
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (widget);
+  GtkWidget *alignment = NULL;
+
+  gtk_widget_style_get (widget,
+                        "header-spacing", &group->priv->header_spacing,
+                        "expander-size", &group->priv->expander_size,
+                        NULL);
+
+  alignment = egg_tool_item_group_get_alignment (group);
+
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
+                             0, 0,
+                             group->priv->header_spacing +
+                             group->priv->expander_size, 0);
+
+  GTK_WIDGET_CLASS (egg_tool_item_group_parent_class)->style_set (widget, previous_style);
+}
+
+static void
+egg_tool_item_group_add (GtkContainer *container,
+                         GtkWidget    *widget)
+{
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (container));
+  g_return_if_fail (GTK_IS_TOOL_ITEM (widget));
+
+  egg_tool_item_group_insert (EGG_TOOL_ITEM_GROUP (container),
+                              GTK_TOOL_ITEM (widget), -1);
+}
+
+static void
+egg_tool_item_group_remove (GtkContainer *container,
+                            GtkWidget    *widget G_GNUC_UNUSED)
+{
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (container));
+  g_return_if_reached ();
+}
+
+static void
+egg_tool_item_group_forall (GtkContainer *container,
+                            gboolean      internals,
+                            GtkCallback   callback,
+                            gpointer      callback_data)
+{
+  EggToolItemGroup *self = EGG_TOOL_ITEM_GROUP (container);
+  guint i;
+
+  if (internals && self->priv->header)
+    callback (self->priv->header, callback_data);
+
+  if (NULL != self->priv->items)
+    for (i = 0; i < self->priv->items->len; ++i)
+      {
+        GtkToolItem *item = egg_tool_item_group_get_nth_item (self, i);
+        callback (GTK_WIDGET (item), callback_data);
+      }
+}
+
+static GType
+egg_tool_item_group_child_type (GtkContainer *container G_GNUC_UNUSED)
+{
+  return GTK_TYPE_TOOL_ITEM;
+}
+
+static void
+egg_tool_item_group_class_init (EggToolItemGroupClass *cls)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (cls);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
+  GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
+
+  oclass->set_property  = egg_tool_item_group_set_property;
+  oclass->get_property  = egg_tool_item_group_get_property;
+  oclass->finalize      = egg_tool_item_group_finalize;
+
+  wclass->size_request  = egg_tool_item_group_size_request;
+  wclass->size_allocate = egg_tool_item_group_size_allocate;
+  wclass->realize       = egg_tool_item_group_realize;
+  wclass->style_set     = egg_tool_item_group_style_set;
+
+  cclass->add           = egg_tool_item_group_add;
+  cclass->remove        = egg_tool_item_group_remove;
+  cclass->forall        = egg_tool_item_group_forall;
+  cclass->child_type    = egg_tool_item_group_child_type;
+
+  g_object_class_install_property (oclass, PROP_NAME,
+                                   g_param_spec_string ("name",
+                                                        P_("Name"),
+                                                        P_("The name of this item group"),
+                                                        NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
+                                                        G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_object_class_install_property (oclass, PROP_EXPANED,
+                                   g_param_spec_boolean ("expanded",
+                                                         P_("Expanded"),
+                                                         P_("Wether the group has been expanded and items are shown"),
+                                                         TRUE,
+                                                         G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
+                                                         G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  gtk_widget_class_install_style_property (wclass,
+                                           g_param_spec_int ("expander-size",
+                                                             P_("Expander Size"),
+                                                             P_("Size of the expander arrow"),
+                                                             0,
+                                                             G_MAXINT,
+                                                             DEFAULT_EXPANDER_SIZE,
+                                                             G_PARAM_READABLE | G_PARAM_STATIC_NAME |
+                                                             G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  gtk_widget_class_install_style_property (wclass,
+                                           g_param_spec_int ("header-spacing",
+                                                             P_("Header Spacing"),
+                                                             P_("Spacing between expander arrow and caption"),
+                                                             0,
+                                                             G_MAXINT,
+                                                             DEFAULT_HEADER_SPACING,
+                                                             G_PARAM_READABLE | G_PARAM_STATIC_NAME |
+                                                             G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_type_class_add_private (cls, sizeof (EggToolItemGroupPrivate));
+}
+
+GtkWidget*
+egg_tool_item_group_new (const gchar *name)
+{
+  return g_object_new (EGG_TYPE_TOOL_ITEM_GROUP, "name", name, NULL);
+}
+
+void
+egg_tool_item_group_set_name (EggToolItemGroup *group,
+                              const gchar      *name)
+{
+  const gchar *current_name;
+  GtkWidget *label;
+
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (group));
+  current_name = egg_tool_item_group_get_name (group);
+
+  if (current_name != name && (!current_name || !name || strcmp (current_name, name)))
+    {
+      label = egg_tool_item_group_get_label (group);
+      gtk_label_set_text (GTK_LABEL (label), name);
+
+      if (name && group->priv->items->len)
+        gtk_widget_show (group->priv->header);
+      else
+        gtk_widget_hide (group->priv->header);
+
+      g_object_notify (G_OBJECT (group), "name");
+    }
+}
+
+static gboolean
+egg_tool_item_group_animation_cb (gpointer data)
+{
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (data);
+  gboolean finish = TRUE;
+  GdkRectangle area;
+
+  if (GTK_WIDGET_REALIZED (group->priv->header))
+    {
+      GtkWidget *alignment = egg_tool_item_group_get_alignment (group);
+
+      area.x = alignment->allocation.x;
+      area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2;
+      area.height = group->priv->expander_size;
+      area.width = group->priv->expander_size;
+
+      gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE);
+    }
+
+  if (group->priv->expanded)
+    {
+      if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED)
+        {
+          group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
+          finish = FALSE;
+        }
+      else
+        group->priv->expander_style = GTK_EXPANDER_EXPANDED;
+    }
+  else
+    {
+      if (group->priv->expander_style == GTK_EXPANDER_EXPANDED)
+        {
+          group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
+          finish = FALSE;
+        }
+      else
+        group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
+    }
+
+  if (finish)
+    {
+      group->priv->animation_timeout = 0;
+      gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group));
+    }
+
+  return !finish;
+}
+
+void
+egg_tool_item_group_set_expanded (EggToolItemGroup *group,
+                                  gboolean          expanded)
+{
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (group));
+
+  if (expanded != group->priv->expanded)
+    {
+      if (group->priv->animation_timeout)
+        g_source_remove (group->priv->animation_timeout);
+
+      group->priv->expanded = expanded;
+      group->priv->animation_timeout = g_timeout_add (50, egg_tool_item_group_animation_cb, group);
+
+      g_object_notify (G_OBJECT (group), "expanded");
+    }
+}
+
+G_CONST_RETURN gchar*
+egg_tool_item_group_get_name (EggToolItemGroup *group)
+{
+  GtkWidget *label;
+
+  g_return_val_if_fail (EGG_IS_TOOL_ITEM_GROUP (group), NULL);
+
+  label = egg_tool_item_group_get_label (group);
+  return gtk_label_get_text (GTK_LABEL (label));
+}
+
+gboolean
+egg_tool_item_group_get_expanded (EggToolItemGroup *group)
+{
+  g_return_val_if_fail (EGG_IS_TOOL_ITEM_GROUP (group), FALSE);
+  return group->priv->expanded;
+}
+
+void
+egg_tool_item_group_insert (EggToolItemGroup *group,
+                            GtkToolItem      *item,
+                            gint              position)
+{
+  GtkWidget *parent;
+
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (group));
+  g_return_if_fail (GTK_IS_TOOL_ITEM (item));
+  g_return_if_fail (position >= -1);
+
+  parent = gtk_widget_get_parent (GTK_WIDGET (group));
+
+  if (-1 == position)
+    position = egg_tool_item_group_get_n_items (group);
+
+  g_return_if_fail (position <= egg_tool_item_group_get_n_items (group));
+  g_array_insert_val (group->priv->items, position, item);
+  g_object_ref_sink (item);
+
+  if (EGG_IS_TOOL_PALETTE (parent))
+    _egg_tool_palette_item_set_drag_source (GTK_WIDGET (item), parent);
+
+  gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group));
+}
+
+void
+egg_tool_item_group_set_item_position (EggToolItemGroup *group,
+                                       GtkToolItem      *item,
+                                       guint             position)
+{
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (group));
+  g_return_if_fail (GTK_IS_TOOL_ITEM (item));
+
+  g_return_if_fail (position < (guint) egg_tool_item_group_get_n_items (group));
+  g_return_if_reached ();
+}
+
+gint
+egg_tool_item_group_get_item_position (EggToolItemGroup *group,
+                                       GtkToolItem      *item)
+{
+  guint i;
+
+  g_return_val_if_fail (EGG_IS_TOOL_ITEM_GROUP (group), -1);
+  g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
+
+  for (i = 0; i < group->priv->items->len; ++i)
+    if (item == egg_tool_item_group_get_nth_item (group, i))
+      return i;
+
+  return -1;
+}
+
+gint
+egg_tool_item_group_get_n_items (EggToolItemGroup *group)
+{
+  g_return_val_if_fail (EGG_IS_TOOL_ITEM_GROUP (group), 0);
+  return group->priv->items->len;
+}
+
+GtkToolItem*
+egg_tool_item_group_get_nth_item (EggToolItemGroup *group,
+                                  gint              index)
+{
+  g_return_val_if_fail (EGG_IS_TOOL_ITEM_GROUP (group), NULL);
+  g_return_val_if_fail (index < egg_tool_item_group_get_n_items (group), NULL);
+  g_return_val_if_fail (index >= 0, NULL);
+
+  return g_array_index (group->priv->items, GtkToolItem*, index);
+}
+
+GtkToolItem*
+egg_tool_item_group_get_drop_item (EggToolItemGroup *group,
+                                   gint              x,
+                                   gint              y)
+{
+  GtkAllocation *allocation;
+
+  g_return_val_if_fail (EGG_IS_TOOL_ITEM_GROUP (group), NULL);
+
+  allocation = &GTK_WIDGET (group)->allocation;
+
+  g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
+  g_return_val_if_fail (y >= 0 && y < allocation->width, NULL);
+
+  g_return_val_if_reached (NULL);
+}
+
+void
+_egg_tool_item_group_item_size_request (EggToolItemGroup *group,
+                                        GtkRequisition   *item_size)
+{
+  GtkRequisition child_requisition;
+  guint i;
+
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (group));
+  g_return_if_fail (NULL != item_size);
+
+  item_size->width = item_size->height = 0;
+
+  for (i = 0; i < group->priv->items->len; ++i)
+    {
+      GtkToolItem *item = egg_tool_item_group_get_nth_item (group, i);
+
+      gtk_widget_size_request (GTK_WIDGET (item), &child_requisition);
+
+      item_size->width = MAX (item_size->width, child_requisition.width);
+      item_size->height = MAX (item_size->height, child_requisition.height);
+    }
+}

Added: trunk/libegg/toolpalette/eggtoolitemgroup.h
==============================================================================
--- (empty file)
+++ trunk/libegg/toolpalette/eggtoolitemgroup.h	Thu Jan 10 22:49:41 2008
@@ -0,0 +1,81 @@
+/* EggToolPalette -- A tool palette with categories and DnD support
+ * Copyright (C) 2008  Openismus GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *      Mathias Hasselmann
+ */
+
+#ifndef __EGG_TOOL_ITEM_GROUP_H__
+#define __EGG_TOOL_ITEM_GROUP_H__
+
+#include <gtk/gtkcontainer.h>
+#include <gtk/gtktoolitem.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TOOL_ITEM_GROUP           (egg_tool_item_group_get_type())
+#define EGG_TOOL_ITEM_GROUP(obj)           (G_TYPE_CHECK_INSTANCE_CAST(obj, EGG_TYPE_TOOL_ITEM_GROUP, EggToolItemGroup))
+#define EGG_TOOL_ITEM_GROUP_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST(cls, EGG_TYPE_TOOL_ITEM_GROUP, EggToolItemGroupClass))
+#define EGG_IS_TOOL_ITEM_GROUP(obj)        (G_TYPE_CHECK_INSTANCE_TYPE(obj, EGG_TYPE_TOOL_ITEM_GROUP))
+#define EGG_IS_TOOL_ITEM_GROUP_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE(obj, EGG_TYPE_TOOL_ITEM_GROUP))
+#define EGG_TOOL_ITEM_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_TOOL_ITEM_GROUP, EggToolItemGroupClass))
+
+typedef struct _EggToolItemGroup        EggToolItemGroup;
+typedef struct _EggToolItemGroupClass   EggToolItemGroupClass;
+typedef struct _EggToolItemGroupPrivate EggToolItemGroupPrivate;
+
+struct _EggToolItemGroup
+{
+  GtkContainer parent_instance;
+  EggToolItemGroupPrivate *priv;
+};
+
+struct _EggToolItemGroupClass
+{
+  GtkContainerClass parent_class;
+};
+
+GType                 egg_tool_item_group_get_type          (void) G_GNUC_CONST;
+GtkWidget*            egg_tool_item_group_new               (const gchar *name);
+
+void                  egg_tool_item_group_set_name          (EggToolItemGroup *group,
+                                                             const gchar      *name);
+void                  egg_tool_item_group_set_expanded      (EggToolItemGroup *group,
+                                                             gboolean          expanded);
+
+G_CONST_RETURN gchar* egg_tool_item_group_get_name          (EggToolItemGroup *group);
+gboolean              egg_tool_item_group_get_expanded      (EggToolItemGroup *group);
+
+void                  egg_tool_item_group_insert            (EggToolItemGroup *group,
+                                                             GtkToolItem      *item,
+                                                             gint              position);
+void                  egg_tool_item_group_set_item_position (EggToolItemGroup *group,
+                                                             GtkToolItem      *item,
+                                                             guint             position);
+gint                  egg_tool_item_group_get_item_position (EggToolItemGroup *group,
+                                                             GtkToolItem      *item);
+
+gint                  egg_tool_item_group_get_n_items       (EggToolItemGroup *group);
+GtkToolItem*          egg_tool_item_group_get_nth_item      (EggToolItemGroup *group,
+                                                             gint              index);
+GtkToolItem*          egg_tool_item_group_get_drop_item     (EggToolItemGroup *group,
+                                                             gint              x,
+                                                             gint              y);
+
+G_END_DECLS
+
+#endif /* __EGG_TOOL_ITEM_GROUP_H__ */ 

Modified: trunk/libegg/toolpalette/eggtoolpalette.c
==============================================================================
--- trunk/libegg/toolpalette/eggtoolpalette.c	(original)
+++ trunk/libegg/toolpalette/eggtoolpalette.c	Thu Jan 10 22:49:41 2008
@@ -1,297 +1,131 @@
+/* EggToolPalette -- A tool palette with categories and DnD support
+ * Copyright (C) 2008  Openismus GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *      Mathias Hasselmann
+ */
+
 #include "eggtoolpalette.h"
+#include "eggtoolpaletteprivate.h"
+#include "eggtoolitemgroup.h"
 #include "eggmarshalers.h"
 
 #include <gtk/gtk.h>
 #include <string.h>
 
-#define DEFAULT_HEADER_SPACING  2
-#define DEFAULT_EXPANDER_SIZE   16
+#define DEFAULT_ICON_SIZE       GTK_ICON_SIZE_SMALL_TOOLBAR
+#define DEFAULT_ORIENTATION     GTK_ORIENTATION_VERTICAL
+#define DEFAULT_STYLE           GTK_TOOLBAR_ICONS
 
-typedef struct _EggToolPaletteCategory     EggToolPaletteCategory;
-typedef struct _EggToolPaletteCallbackData EggToolPaletteCallbackData;
+typedef struct _EggToolPaletteDragData EggToolPaletteDragData;
 
 enum
 {
-  PROP_NONE
-  /* TODO: fill in properties */
-};
-
-struct _EggToolPaletteCategory
-{
-  gchar            *id;
-  GArray           *items;
-
-  GtkWidget        *header;
-  GtkExpanderStyle  expander_style;
-  guint             animation_timeout;
-
-  GdkWindow        *window;
-
-  guint             expanded : 1;
+  PROP_NONE,
+  PROP_ICON_SIZE,
+  PROP_ORIENTATION,
+  PROP_STYLE,
 };
 
 struct _EggToolPalettePrivate
 {
-  EggToolPaletteCategory *current_category;
-  GArray                 *categories;
+  GArray          *groups;
 
-  GtkAdjustment          *hadjustment;
-  GtkAdjustment          *vadjustment;
+  GtkAdjustment   *hadjustment;
+  GtkAdjustment   *vadjustment;
 
-  gint                    header_spacing;
-  gint                    expander_size;
+  GtkRequisition   item_size;
+  GtkIconSize      icon_size;
+  GtkOrientation   orientation;
+  GtkToolbarStyle  style;
 
-  guint                   is_drag_source : 1;
+  guint            is_drag_source : 1;
 };
 
-struct _EggToolPaletteCallbackData
+struct _EggToolPaletteDragData
 {
-  EggToolPaletteCallback callback;
-  gpointer               user_data;
+  EggToolPalette *palette;
+  GtkToolItem    *item;
 };
 
+static GdkAtom dnd_target_atom = GDK_NONE;
 static GtkTargetEntry dnd_targets[] =
 {
-  { "application/x-egg-tool-palette-item", GTK_TARGET_SAME_APP, 0 }
+  { "application/x-egg-tool-palette-item", GTK_TARGET_SAME_APP, 0 },
 };
 
-G_DEFINE_TYPE (EggToolPalette, egg_tool_palette, GTK_TYPE_CONTAINER);
-
-static EggToolPaletteCategory*
-egg_tool_palette_get_category (EggToolPalette *self,
-                               guint           index)
-{
-  g_return_val_if_fail (index < self->priv->categories->len, NULL);
-
-  return g_array_index (self->priv->categories,
-                        EggToolPaletteCategory*,
-                        index);
-}
-
-static EggToolPaletteCategory*
-egg_tool_palette_find_category (EggToolPalette *self,
-                                const gchar    *id)
-{
-  guint i;
-
-  if (NULL == id)
-    id = "";
-
-  if (self->priv->current_category &&
-      strcmp (id, self->priv->current_category->id))
-    self->priv->current_category = NULL;
-
-  for (i = 0; i < self->priv->categories->len; ++i)
-    {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-
-      if (g_str_equal (id, category->id))
-        {
-          self->priv->current_category = category;
-          break;
-        }
-    }
-
-  return self->priv->current_category;
-}
-
-static gboolean
-egg_tool_palette_header_expose_event (GtkWidget      *widget,
-                                      GdkEventExpose *event G_GNUC_UNUSED,
-                                      gpointer        data)
-{
-  EggToolPaletteCategory *category = data;
-  EggToolPalette *self;
-  GtkWidget *palette;
-  gint x, y;
-
-  palette = gtk_widget_get_parent (category->header);
-  self = EGG_TOOL_PALETTE (palette);
-
-  x = widget->allocation.x + self->priv->expander_size / 2;
-  y = widget->allocation.y + widget->allocation.height / 2;
-
-  gtk_paint_expander (widget->style, widget->window,
-                      category->header->state,
-                      &event->area, palette, NULL,
-                      x, y, category->expander_style);
-
-  return FALSE;
-}
-
-static gboolean
-egg_tool_palette_expand_animation (gpointer data)
-{
-  EggToolPaletteCategory *category = data;
-  GtkWidget *palette = gtk_widget_get_parent (category->header);
-  gboolean finish = TRUE;
-
-  if (GTK_WIDGET_REALIZED (category->header))
-    {
-      GtkWidget *alignment = gtk_bin_get_child (GTK_BIN (category->header));
-      EggToolPalette *self = EGG_TOOL_PALETTE (palette);
-      GdkRectangle area;
-
-      area.x = alignment->allocation.x;
-      area.y = alignment->allocation.y + (alignment->allocation.height - self->priv->expander_size) / 2;
-      area.height = self->priv->expander_size;
-      area.width = self->priv->expander_size;
-
-      gdk_window_invalidate_rect (category->header->window, &area, TRUE);
-    }
-
-  if (category->expanded)
-    {
-      if (category->expander_style == GTK_EXPANDER_COLLAPSED)
-        {
-          category->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
-          finish = FALSE;
-        }
-      else
-        category->expander_style = GTK_EXPANDER_EXPANDED;
-    }
-  else
-    {
-      if (category->expander_style == GTK_EXPANDER_EXPANDED)
-        {
-          category->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
-          finish = FALSE;
-        }
-      else
-        category->expander_style = GTK_EXPANDER_COLLAPSED;
-    }
-
-  if (finish)
-    {
-      category->animation_timeout = 0;
-      gtk_widget_queue_resize (palette);
-    }
+G_DEFINE_TYPE (EggToolPalette,
+               egg_tool_palette,
+               GTK_TYPE_CONTAINER);
 
-  return !finish;
-}
-
-static void
-egg_tool_palette_category_set_expanded (EggToolPaletteCategory *category,
-                                        gboolean                expanded)
+static EggToolItemGroup*
+egg_tool_palette_get_group (EggToolPalette *palette,
+                            guint           index)
 {
-  if (category->animation_timeout)
-    g_source_remove (category->animation_timeout);
-
-  category->expanded = expanded;
-  category->animation_timeout = g_timeout_add (50, egg_tool_palette_expand_animation, category);
+  g_return_val_if_fail (index < palette->priv->groups->len, NULL);
+  return g_array_index (palette->priv->groups, EggToolItemGroup*, index);
 }
 
 static void
-egg_tool_palette_header_clicked (GtkButton *button G_GNUC_UNUSED,
-                                 gpointer   data)
-{
-  EggToolPaletteCategory *category = data;
-  egg_tool_palette_category_set_expanded (category, !category->expanded);
-}
-
-static EggToolPaletteCategory*
-egg_tool_palette_create_category (EggToolPalette *self,
-                                  const gchar    *id,
-                                  const gchar    *name)
-{
-  EggToolPaletteCategory *category;
-  GtkWidget *alignment;
-  GtkWidget *label;
-
-  g_assert (NULL != id);
-
-  category = g_slice_new0 (EggToolPaletteCategory);
-  category->items = g_array_new (TRUE, TRUE, sizeof (GtkToolItem*));
-  category->id = g_strdup (id);
-
-  category->expanded = TRUE;
-  category->expander_style = GTK_EXPANDER_EXPANDED;
-
-  label = gtk_label_new (name);
-  alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
-
-  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0,
-                             self->priv->header_spacing +
-                             self->priv->expander_size, 0);
-
-  gtk_widget_set_size_request (alignment, -1, self->priv->expander_size);
-  gtk_container_add (GTK_CONTAINER (alignment), label);
-  gtk_widget_show_all (alignment);
-
-  gtk_widget_push_composite_child ();
-  category->header = gtk_button_new ();
-  gtk_widget_set_composite_name (category->header, "header");
-  gtk_widget_pop_composite_child ();
-
-  gtk_button_set_focus_on_click (GTK_BUTTON (category->header), FALSE);
-  gtk_container_add (GTK_CONTAINER (category->header), alignment);
-  gtk_widget_set_parent (category->header, GTK_WIDGET (self));
-
-  g_signal_connect_after (alignment, "expose-event",
-                          G_CALLBACK (egg_tool_palette_header_expose_event),
-                          category);
-
-  g_signal_connect (category->header, "clicked",
-                    G_CALLBACK (egg_tool_palette_header_clicked),
-                    category);
-
-  if (name)
-    gtk_widget_show (category->header);
-
-  g_array_append_val (self->priv->categories, category);
-  self->priv->current_category = category;
-  return self->priv->current_category;
-}
-
-static void
-egg_tool_palette_category_free (EggToolPaletteCategory *category)
-{
-  if (category->header)
-    gtk_widget_unparent (category->header);
-  if (category->window)
-    g_object_unref (category->window);
-  if (category->items)
-    g_array_free (category->items, TRUE);
-
-  g_slice_free (EggToolPaletteCategory, category);
-}
-
-static GtkToolItem*
-egg_tool_palette_category_get_child (EggToolPaletteCategory *category,
-                                     guint                   index)
+egg_tool_palette_init (EggToolPalette *palette)
 {
-  g_return_val_if_fail (index < category->items->len, NULL);
-  return g_array_index (category->items, GtkToolItem*, index);
-}
-
-static void
-egg_tool_palette_init (EggToolPalette *self)
-{
-  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (self), FALSE);
-#if 0
-  GTK_WIDGET_SET_FLAGS (self, GTK_NO_WINDOW);
-#endif
-
-  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+  palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette,
                                             EGG_TYPE_TOOL_PALETTE,
                                             EggToolPalettePrivate);
 
-  self->priv->categories = g_array_new (TRUE, TRUE, sizeof (EggToolPaletteCategory*));
-  egg_tool_palette_create_category (self, "", NULL);
+  palette->priv->groups = g_array_new (TRUE, TRUE, sizeof (EggToolItemGroup*));
+  palette->priv->icon_size = DEFAULT_ICON_SIZE;
+  palette->priv->orientation = DEFAULT_ORIENTATION;
+  palette->priv->style = DEFAULT_STYLE;
 }
 
-#if 0
 static void
 egg_tool_palette_set_property (GObject      *object,
                                guint         prop_id,
                                const GValue *value,
                                GParamSpec   *pspec)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (object);
+  EggToolPalette *palette = EGG_TOOL_PALETTE (object);
 
   switch (prop_id)
     {
-      /* TODO: handle properties */
+      case PROP_ICON_SIZE:
+        if ((guint) g_value_get_enum (value) != palette->priv->icon_size)
+          {
+            palette->priv->icon_size = g_value_get_enum (value);
+            gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette));
+          }
+        break;
+
+      case PROP_ORIENTATION:
+        if ((guint) g_value_get_enum (value) != palette->priv->orientation)
+          {
+            palette->priv->orientation = g_value_get_enum (value);
+            gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette));
+          }
+        break;
+
+      case PROP_STYLE:
+        if ((guint) g_value_get_enum (value) != palette->priv->style)
+          {
+            palette->priv->style = g_value_get_enum (value);
+            gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette));
+          }
+        break;
 
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -305,135 +139,104 @@
                                GValue     *value,
                                GParamSpec *pspec)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (object);
+  EggToolPalette *palette = EGG_TOOL_PALETTE (object);
 
   switch (prop_id)
     {
-      /* TODO: handle properties */
+      case PROP_ICON_SIZE:
+        g_value_set_enum (value, egg_tool_palette_get_icon_size (palette));
+        break;
+
+      case PROP_ORIENTATION:
+        g_value_set_enum (value, egg_tool_palette_get_orientation (palette));
+        break;
+
+      case PROP_STYLE:
+        g_value_set_enum (value, egg_tool_palette_get_style (palette));
+        break;
 
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
     }
 }
-#endif
 
 static void
 egg_tool_palette_dispose (GObject *object)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (object);
-  guint i;
-
-  gtk_container_forall (GTK_CONTAINER (self), (GtkCallback) g_object_unref, NULL);
+  EggToolPalette *palette = EGG_TOOL_PALETTE (object);
 
-  if (self->priv->hadjustment)
+  if (palette->priv->hadjustment)
     {
-      g_object_unref (self->priv->hadjustment);
-      self->priv->hadjustment = NULL;
+      g_object_unref (palette->priv->hadjustment);
+      palette->priv->hadjustment = NULL;
     }
 
-  if (self->priv->vadjustment)
+  if (palette->priv->vadjustment)
     {
-      g_object_unref (self->priv->vadjustment);
-      self->priv->vadjustment = NULL;
-    }
-
-  if (self->priv->categories)
-    {
-      for (i = 0; i < self->priv->categories->len; ++i)
-        egg_tool_palette_category_free (egg_tool_palette_get_category (self, i));
-
-      g_array_free (self->priv->categories, TRUE);
-      self->priv->categories = NULL;
+      g_object_unref (palette->priv->vadjustment);
+      palette->priv->vadjustment = NULL;
     }
 
   G_OBJECT_CLASS (egg_tool_palette_parent_class)->dispose (object);
 }
 
 static void
-egg_tool_palette_realize (GtkWidget *widget)
+egg_tool_palette_finalize (GObject *object)
 {
-  const gint border_width = GTK_CONTAINER (widget)->border_width;
-  gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-  GdkWindowAttr attributes;
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
-  attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = widget->allocation.x + border_width;
-  attributes.y = widget->allocation.y + border_width;
-  attributes.width = widget->allocation.width - border_width * 2;
-  attributes.height = widget->allocation.height - border_width * 2;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
-                        | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-                        | GDK_BUTTON_MOTION_MASK;
+  EggToolPalette *palette = EGG_TOOL_PALETTE (object);
 
-  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
-                                   &attributes, attributes_mask);
-
-  gdk_window_set_user_data (widget->window, widget);
-
-  widget->style = gtk_style_attach (widget->style, widget->window);
-  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
-
-  gtk_container_forall (GTK_CONTAINER (widget),
-                        (GtkCallback) gtk_widget_set_parent_window,
-                        widget->window);
-
-  gtk_widget_queue_resize_no_redraw (widget);
-}
-
-static void
-egg_tool_palette_unrealize (GtkWidget *widget)
-{
-  EggToolPalette *self = EGG_TOOL_PALETTE (widget);
-  guint i;
-
-  for (i = 0; i < self->priv->categories->len; ++i)
+  if (palette->priv->groups)
     {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-
-      if (category->animation_timeout)
-        {
-          g_source_remove (category->animation_timeout);
-          category->animation_timeout = 0;
-        }
-
-      if (category->window)
-        {
-          g_object_unref (category->window);
-          category->window = NULL;
-        }
+      g_array_free (palette->priv->groups, TRUE);
+      palette->priv->groups = NULL;
     }
+
+  G_OBJECT_CLASS (egg_tool_palette_parent_class)->finalize (object);
 }
 
 static void
 egg_tool_palette_size_request (GtkWidget      *widget,
                                GtkRequisition *requisition)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (widget);
+  const gint border_width = GTK_CONTAINER (widget)->border_width;
+  EggToolPalette *palette = EGG_TOOL_PALETTE (widget);
+  GtkRequisition child_requisition;
   guint i;
 
-  requisition->width = requisition->height = 0;
+  requisition->width = 0;
+  requisition->height = 0;
 
-  for (i = 0; i < self->priv->categories->len; ++i)
+  palette->priv->item_size.width = 0;
+  palette->priv->item_size.height = 0;
+
+  for (i = 0; i < palette->priv->groups->len; ++i)
     {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-      GtkRequisition child_requistion;
+      EggToolItemGroup *group = egg_tool_palette_get_group (palette, i);
+
+      gtk_widget_size_request (GTK_WIDGET (group), &child_requisition);
 
-      if (GTK_WIDGET_VISIBLE (category->header))
+      if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
         {
-          gtk_widget_size_request (category->header, &child_requistion);
-          requisition->width = MAX (requisition->width, child_requistion.width);
-          requisition->height += child_requistion.height;
+          requisition->width = MAX (requisition->width, child_requisition.width);
+          requisition->height += child_requisition.height;
         }
+      else
+        {
+          requisition->width += child_requisition.width;
+          requisition->height = MAX (requisition->height, child_requisition.height);
+        }
+
+      _egg_tool_item_group_item_size_request (group, &child_requisition);
+
+      palette->priv->item_size.width = MAX (palette->priv->item_size.width,
+                                            child_requisition.width);
+      palette->priv->item_size.height = MAX (palette->priv->item_size.height,
+                                             child_requisition.height);
     }
 
-  requisition->width += GTK_CONTAINER (self)->border_width * 2;
-  requisition->height += GTK_CONTAINER (self)->border_width * 2;
+  requisition->width += border_width * 2;
+  requisition->height += border_width * 2;
 }
 
 static void
@@ -441,140 +244,114 @@
                                 GtkAllocation *allocation)
 {
   const gint border_width = GTK_CONTAINER (widget)->border_width;
-  EggToolPalette *self = EGG_TOOL_PALETTE (widget);
-  GtkRequisition child_requistion;
+  EggToolPalette *palette = EGG_TOOL_PALETTE (widget);
+  GtkRequisition child_requisition;
   GtkAllocation child_allocation;
-  gint item_height = 0;
-  gint item_width = 0;
   gint offset = 0;
-  guint i, j;
+  guint i;
 
   GTK_WIDGET_CLASS (egg_tool_palette_parent_class)->size_allocate (widget, allocation);
 
-  if (GTK_WIDGET_REALIZED (widget))
-    {
-      gdk_window_move_resize (widget->window,
-                              allocation->x      + border_width,
-                              allocation->y      + border_width,
-                              allocation->width  - border_width * 2,
-                              allocation->height - border_width * 2);
-    }
-
-  if (self->priv->vadjustment)
-    offset = -gtk_adjustment_get_value (self->priv->vadjustment);
+  if (palette->priv->vadjustment)
+    offset = -gtk_adjustment_get_value (palette->priv->vadjustment);
 
   child_allocation.x = border_width;
   child_allocation.y = border_width + offset;
+  child_allocation.width = allocation->width - border_width * 2;
 
-  for (i = 0; i < self->priv->categories->len; ++i)
+  for (i = 0; i < palette->priv->groups->len; ++i)
     {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
+      EggToolItemGroup *group = egg_tool_palette_get_group (palette, i);
+      gint n_items = egg_tool_item_group_get_n_items (group);
 
-      for (j = 0; j < category->items->len; ++j)
-        {
-          GtkToolItem *child = egg_tool_palette_category_get_child (category, j);
-
-          gtk_widget_size_request (GTK_WIDGET (child), &child_requistion);
-
-          item_width = MAX (item_width, child_requistion.width);
-          item_height = MAX (item_height, child_requistion.height);
-        }
-    }
-
-  for (i = 0; i < self->priv->categories->len; ++i)
-    {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-
-      if (!category->items->len)
+      if (!n_items)
         continue;
 
-      if (GTK_WIDGET_VISIBLE (category->header))
-        {
-          gtk_widget_size_request (category->header, &child_requistion);
-
-          child_allocation.width  = allocation->width - border_width * 2;
-          child_allocation.height = child_requistion.height;
+      gtk_widget_size_request (GTK_WIDGET (group), &child_requisition);
+      child_allocation.height = child_requisition.height;
 
-          gtk_widget_size_allocate (category->header, &child_allocation);
-
-          child_allocation.y += child_allocation.height;
-        }
-
-      if (category->expanded)
+      if (egg_tool_item_group_get_expanded (group))
         {
-          for (j = 0; j < category->items->len; ++j)
-            {
-              GtkToolItem *child = egg_tool_palette_category_get_child (category, j);
-
-              child_allocation.width = item_width;
-              child_allocation.height = item_height;
-
-              if (child_allocation.x + child_allocation.width > allocation->width)
-                {
-                  child_allocation.y += child_allocation.height;
-                  child_allocation.x = border_width;
-                }
-
-              gtk_widget_size_allocate (GTK_WIDGET (child), &child_allocation);
-              gtk_widget_show (GTK_WIDGET (child));
-
-              child_allocation.x += child_allocation.width;
-            }
+        /* TODO: Use gtk_widget_get_height_for_width */
+          gint n_columns = child_allocation.width / palette->priv->item_size.width;
+          gint n_rows = (n_items + n_columns - 1) / n_columns;
 
-          child_allocation.y += item_height;
-          child_allocation.x = border_width;
-        }
-      else
-        {
-          for (j = 0; j < category->items->len; ++j)
-            {
-              GtkToolItem *child = egg_tool_palette_category_get_child (category, j);
-              gtk_widget_hide (GTK_WIDGET (child));
-            }
+          child_allocation.height += palette->priv->item_size.height * n_rows;
         }
+
+      gtk_widget_size_allocate (GTK_WIDGET (group), &child_allocation);
+      child_allocation.y += child_allocation.height;
     }
 
   child_allocation.y += border_width;
 
-  if (self->priv->vadjustment)
+  if (palette->priv->vadjustment)
     {
-      self->priv->vadjustment->page_size = allocation->height;
-      self->priv->vadjustment->page_increment = allocation->height * 0.9;
-      self->priv->vadjustment->step_increment = allocation->height * 0.1;
-      self->priv->vadjustment->upper = MAX (0, child_allocation.y - offset);
+      palette->priv->vadjustment->page_size = allocation->height;
+      palette->priv->vadjustment->page_increment = allocation->height * 0.9;
+      palette->priv->vadjustment->step_increment = allocation->height * 0.1;
+      palette->priv->vadjustment->upper = MAX (0, child_allocation.y - allocation->y - offset);
 
-      gtk_adjustment_changed (self->priv->vadjustment);
-      gtk_adjustment_clamp_page (self->priv->vadjustment, -offset, allocation->height -offset);
+      gtk_adjustment_changed (palette->priv->vadjustment);
+      gtk_adjustment_clamp_page (palette->priv->vadjustment, -offset, allocation->height -offset);
     }
-
-  if (GTK_WIDGET_MAPPED (widget))
-    gdk_window_invalidate_rect (widget->window, NULL, FALSE);
 }
 
 static gboolean
 egg_tool_palette_expose_event (GtkWidget      *widget,
                                GdkEventExpose *event)
 {
-  EggToolPalette *self =  EGG_TOOL_PALETTE (widget);
+  EggToolPalette *palette =  EGG_TOOL_PALETTE (widget);
   guint i;
 
   if (GTK_WIDGET_CLASS (egg_tool_palette_parent_class)->expose_event (widget, event))
     return TRUE;
 
-  for (i = 0; i < self->priv->categories->len; ++i)
+  for (i = 0; i < palette->priv->groups->len; ++i)
     {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-
-      if (category->window)
-        {
-          /* TODO: draw composited window */
-        }
+/* TODO: draw composited window
+      EggToolItemGroup *group = egg_tool_palette_get_group (palette, i);
+*/
     }
 
   return FALSE;
 }
 
 static void
+egg_tool_palette_realize (GtkWidget *widget)
+{
+  const gint border_width = GTK_CONTAINER (widget)->border_width;
+  gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  GdkWindowAttr attributes;
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x + border_width;
+  attributes.y = widget->allocation.y + border_width;
+  attributes.width = widget->allocation.width - border_width * 2;
+  attributes.height = widget->allocation.height - border_width * 2;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
+                        | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+                        | GDK_BUTTON_MOTION_MASK;
+
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                                   &attributes, attributes_mask);
+
+  gdk_window_set_user_data (widget->window, widget);
+  widget->style = gtk_style_attach (widget->style, widget->window);
+  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+  gtk_container_forall (GTK_CONTAINER (widget),
+                        (GtkCallback) gtk_widget_set_parent_window,
+                        widget->window);
+
+  gtk_widget_queue_resize_no_redraw (widget);
+}
+
+static void
 egg_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED,
                                            gpointer       data)
 {
@@ -587,126 +364,94 @@
                                          GtkAdjustment *hadjustment,
                                          GtkAdjustment *vadjustment)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (widget);
+  EggToolPalette *palette = EGG_TOOL_PALETTE (widget);
 
-  if (self->priv->hadjustment)
-    g_object_unref (self->priv->hadjustment);
-  if (self->priv->vadjustment)
-    g_object_unref (self->priv->vadjustment);
+  if (palette->priv->hadjustment)
+    g_object_unref (palette->priv->hadjustment);
+  if (palette->priv->vadjustment)
+    g_object_unref (palette->priv->vadjustment);
 
   if (hadjustment)
     g_object_ref_sink (hadjustment);
   if (vadjustment)
     g_object_ref_sink (vadjustment);
 
-  self->priv->hadjustment = hadjustment;
-  self->priv->vadjustment = vadjustment;
+  palette->priv->hadjustment = hadjustment;
+  palette->priv->vadjustment = vadjustment;
 
-  if (self->priv->hadjustment)
-    g_signal_connect (self->priv->hadjustment, "value-changed",
+  if (palette->priv->hadjustment)
+    g_signal_connect (palette->priv->hadjustment, "value-changed",
                       G_CALLBACK (egg_tool_palette_adjustment_value_changed),
-                      self);
-  if (self->priv->vadjustment)
-    g_signal_connect (self->priv->vadjustment, "value-changed",
+                      palette);
+  if (palette->priv->vadjustment)
+    g_signal_connect (palette->priv->vadjustment, "value-changed",
                       G_CALLBACK (egg_tool_palette_adjustment_value_changed),
-                      self);
+                      palette);
 }
 
 static void
-egg_tool_palette_style_set (GtkWidget *widget,
-                            GtkStyle  *previous_style)
+egg_tool_palette_add (GtkContainer *container,
+                      GtkWidget    *child)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (widget);
-  guint i;
-
-  self->priv->header_spacing = DEFAULT_HEADER_SPACING; /* TODO: use real style property */
-  self->priv->expander_size = DEFAULT_EXPANDER_SIZE; /* TODO: use real style property */
+  EggToolPalette *palette;
 
-  for (i = 0; i < self->priv->categories->len; ++i)
-    {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-      GtkWidget *alignment = NULL;
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (container));
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (child));
 
-      if (category->header)
-        {
-          alignment = gtk_bin_get_child (GTK_BIN (category->header));
-
-          gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0,
-                                     self->priv->header_spacing +
-                                     self->priv->expander_size, 0);
-          gtk_widget_set_size_request (alignment, -1, self->priv->expander_size);
-        }
-    }
+  palette = EGG_TOOL_PALETTE (container);
 
-  GTK_WIDGET_CLASS (egg_tool_palette_parent_class)->style_set (widget, previous_style);
+  g_object_ref_sink (child);
+  g_array_append_val (palette->priv->groups, child);
+  gtk_widget_set_parent (child, GTK_WIDGET (palette));
 }
 
 static void
-egg_tool_palette_add (GtkContainer *container G_GNUC_UNUSED,
-                      GtkWidget    *child     G_GNUC_UNUSED)
-{
-  g_return_if_reached ();
-}
-
-static void
-egg_tool_palette_remove (GtkContainer *container G_GNUC_UNUSED,
-                         GtkWidget    *child     G_GNUC_UNUSED)
+egg_tool_palette_remove (GtkContainer *container,
+                         GtkWidget    *child G_GNUC_UNUSED)
 {
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (container));
   g_return_if_reached ();
 }
 
 static void
 egg_tool_palette_forall (GtkContainer *container,
-                         gboolean      internals,
+                         gboolean      internals G_GNUC_UNUSED,
                          GtkCallback   callback,
                          gpointer      callback_data)
 {
-  EggToolPalette *self = EGG_TOOL_PALETTE (container);
-  guint i, j;
-
-  if (NULL == self->priv->categories)
-    return;
-
-  for (i = 0; i < self->priv->categories->len; ++i)
-    {
-      EggToolPaletteCategory *category = egg_tool_palette_get_category (self, i);
-
-      if (internals && category->header)
-        callback (category->header, callback_data);
+  EggToolPalette *palette = EGG_TOOL_PALETTE (container);
+  guint i;
 
-      for (j = 0; j < category->items->len; ++j)
-        {
-          GtkToolItem *child = egg_tool_palette_category_get_child (category, j);
-          callback (GTK_WIDGET (child), callback_data);
-        }
-    }
+  if (palette->priv->groups)
+    for (i = 0; i < palette->priv->groups->len; ++i)
+      {
+        EggToolItemGroup *group = egg_tool_palette_get_group (palette, i);
+        callback (GTK_WIDGET (group), callback_data);
+      }
 }
 
 static GType
 egg_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED)
 {
-  return GTK_TYPE_TOOL_ITEM;
+  return EGG_TYPE_TOOL_ITEM_GROUP;
 }
 
 static void
 egg_tool_palette_class_init (EggToolPaletteClass *cls)
 {
-  GObjectClass      *oclass = G_OBJECT_CLASS (cls);
-  GtkWidgetClass    *wclass = GTK_WIDGET_CLASS (cls);
+  GObjectClass *oclass = G_OBJECT_CLASS (cls);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
   GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
 
-#if 0
   oclass->set_property        = egg_tool_palette_set_property;
   oclass->get_property        = egg_tool_palette_get_property;
-#endif
   oclass->dispose             = egg_tool_palette_dispose;
+  oclass->finalize            = egg_tool_palette_finalize;
 
-  wclass->realize             = egg_tool_palette_realize;
-  wclass->unrealize           = egg_tool_palette_unrealize;
   wclass->size_request        = egg_tool_palette_size_request;
   wclass->size_allocate       = egg_tool_palette_size_allocate;
   wclass->expose_event        = egg_tool_palette_expose_event;
-  wclass->style_set           = egg_tool_palette_style_set;
+  wclass->realize             = egg_tool_palette_realize;
 
   cclass->add                 = egg_tool_palette_add;
   cclass->remove              = egg_tool_palette_remove;
@@ -727,9 +472,9 @@
                   GTK_TYPE_ADJUSTMENT);
 
   g_type_class_add_private (cls, sizeof (EggToolPalettePrivate));
-}
 
-/* ===== instance handling ===== */
+  dnd_target_atom = gdk_atom_intern_static_string (dnd_targets[0].target);
+}
 
 GtkWidget*
 egg_tool_palette_new (void)
@@ -737,292 +482,189 @@
   return g_object_new (EGG_TYPE_TOOL_PALETTE, NULL);
 }
 
-/* ===== category settings ===== */
-
 void
-egg_tool_palette_set_category_name (EggToolPalette *self,
-                                    const gchar    *category,
-                                    const gchar    *name G_GNUC_UNUSED)
+egg_tool_palette_set_icon_size (EggToolPalette *palette,
+                                GtkIconSize     icon_size)
 {
-  EggToolPaletteCategory *category_info;
-
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (NULL != category);
-
-  category_info = egg_tool_palette_find_category (self, category);
-
-  if (category_info)
-    {
-      GtkWidget *alignment = gtk_bin_get_child (GTK_BIN (category_info->header));
-      GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment));
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
 
-      gtk_label_set_text (GTK_LABEL (label), name);
-      gtk_widget_show (category_info->header);
-    }
+  if (icon_size != palette->priv->icon_size)
+    g_object_set (palette, "icon-size", icon_size, NULL);
 }
 
 void
-egg_tool_palette_set_category_position (EggToolPalette *self,
-                                        const gchar    *category,
-                                        gint            position G_GNUC_UNUSED)
+egg_tool_palette_set_orientation (EggToolPalette *palette,
+                                  GtkOrientation  orientation)
 {
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (NULL != category);
-  g_return_if_reached ();
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
+
+  if (orientation != palette->priv->orientation)
+    g_object_set (palette, "orientation", orientation, NULL);
 }
 
 void
-egg_tool_palette_set_category_expanded (EggToolPalette *self,
-                                        const gchar    *category,
-                                        gboolean        expanded)
+egg_tool_palette_set_style (EggToolPalette  *palette,
+                            GtkToolbarStyle  style)
 {
-  EggToolPaletteCategory *category_info;
-
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (NULL != category);
-
-  category_info = egg_tool_palette_find_category (self, category);
-  g_return_if_fail (NULL != category_info);
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
 
-  egg_tool_palette_category_set_expanded (category_info, expanded);
+  if (style != palette->priv->style)
+    g_object_set (palette, "style", style, NULL);
 }
 
-G_CONST_RETURN gchar*
-egg_tool_palette_get_category_name (EggToolPalette *self,
-                                    const gchar    *category)
+GtkIconSize
+egg_tool_palette_get_icon_size (EggToolPalette *palette)
 {
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), NULL);
-  g_return_val_if_fail (NULL != category, NULL);
-  g_return_val_if_reached (NULL);
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE);
+  return palette->priv->icon_size;
 }
 
-gint
-egg_tool_palette_get_category_position (EggToolPalette *self,
-                                        const gchar    *category)
+GtkOrientation
+egg_tool_palette_get_orientation (EggToolPalette *palette)
 {
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), 0);
-  g_return_val_if_fail (NULL != category, 0);
-  g_return_val_if_reached (0);
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION);
+  return palette->priv->orientation;
 }
 
-gboolean
-egg_tool_palette_get_category_expanded (EggToolPalette *self,
-                                        const gchar    *category)
+GtkToolbarStyle
+egg_tool_palette_get_style (EggToolPalette *palette)
 {
-  EggToolPaletteCategory *category_info;
-
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), FALSE);
-  g_return_val_if_fail (NULL != category, FALSE);
-
-  category_info = egg_tool_palette_find_category (self, category);
-  g_return_val_if_fail (NULL != category_info, FALSE);
-
-  return category_info->expanded;
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), DEFAULT_STYLE);
+  return palette->priv->style;
 }
 
-/* ===== item packing ===== */
-
-static void
-egg_tool_palette_item_drag_data_get (GtkWidget        *widget,
-                                     GdkDragContext   *context G_GNUC_UNUSED,
-                                     GtkSelectionData *selection,
-                                     guint             info G_GNUC_UNUSED,
-                                     guint             time G_GNUC_UNUSED,
-                                     gpointer          data G_GNUC_UNUSED)
-{
-  const gchar *target_name = gdk_atom_name (selection->target);
-
-  if (g_str_equal (target_name, dnd_targets[0].target))
-    gtk_selection_data_set (selection, selection->target, 8,
-                            (guchar*) &widget, sizeof (&widget));
-}
+void
+egg_tool_palette_reorder_group (EggToolPalette *palette,
+                                GtkWidget      *group,
+                                guint           position)
+{
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
+  g_return_if_fail (EGG_IS_TOOL_ITEM_GROUP (group));
+  g_return_if_fail (position < palette->priv->groups->len);
 
-static void
-egg_tool_palette_item_set_drag_source (GtkWidget *widget,
-                                       gpointer   data)
-{
-  gtk_tool_item_set_use_drag_window (GTK_TOOL_ITEM (widget), TRUE);
-  gtk_drag_source_set (widget, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
-                       dnd_targets, G_N_ELEMENTS (dnd_targets),
-                       GDK_ACTION_COPY);
-
-  g_signal_connect (widget, "drag-data-get",
-                    G_CALLBACK (egg_tool_palette_item_drag_data_get),
-                    data);
+  g_return_if_reached ();
 }
 
-void
-egg_tool_palette_insert (EggToolPalette *self,
-                         const gchar    *category,
-                         GtkToolItem    *item,
-                         gint            position)
+GtkToolItem*
+egg_tool_palette_get_drop_item (EggToolPalette   *palette,
+                                gint              x,
+                                gint              y)
 {
-  EggToolPaletteCategory *category_info;
+  GtkAllocation *allocation;
 
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-  g_return_if_fail (position >= -1);
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), NULL);
 
-  category_info = egg_tool_palette_find_category (self, category);
+  allocation = &GTK_WIDGET (palette)->allocation;
 
-  if (NULL == category_info)
-    category_info = egg_tool_palette_create_category (self, category, NULL);
-  if (-1 == position)
-    position = category_info->items->len;
+  g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
+  g_return_val_if_fail (y >= 0 && y < allocation->width, NULL);
 
-  g_return_if_fail ((guint) position <= category_info->items->len);
-  g_array_insert_val (category_info->items, position, item);
-
-  if (self->priv->is_drag_source)
-    egg_tool_palette_item_set_drag_source (GTK_WIDGET (item), self);
-
-  gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (self));
-  g_object_ref (item);
+  g_return_val_if_reached (NULL);
 }
 
-gint
-egg_tool_palette_get_n_items (EggToolPalette *self,
-                              const gchar    *category)
+GtkToolItem*
+egg_tool_palette_get_drag_item (EggToolPalette   *palette,
+                                GtkSelectionData *selection)
 {
-  EggToolPaletteCategory *category_info;
+  EggToolPaletteDragData *data;
 
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), 0);
-  category_info = egg_tool_palette_find_category (self, category);
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), NULL);
+  g_return_val_if_fail (NULL != selection, NULL);
 
-  if (NULL != category_info)
-    return category_info->items->len;
+  g_return_val_if_fail (selection->format == 8, NULL);
+  g_return_val_if_fail (selection->length == sizeof (EggToolPaletteDragData), NULL);
+  g_return_val_if_fail (selection->target == dnd_target_atom, NULL);
 
-  return 0;
-}
-
-GtkToolItem*
-egg_tool_palette_get_nth_item (EggToolPalette *self,
-                               const gchar    *category,
-                               gint            index)
-{
-  EggToolPaletteCategory *category_info;
-
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), NULL);
-  category_info = egg_tool_palette_find_category (self, category);
+  data = (EggToolPaletteDragData*) selection->data;
 
-  if (NULL != category_info)
-    return egg_tool_palette_category_get_child (category_info, index);
+  g_return_val_if_fail (data->palette == palette, NULL);
 
-  return 0;
+  return data->item;
 }
 
-GtkToolItem*
-egg_tool_palette_get_drop_item (EggToolPalette *self,
-                                gint            x G_GNUC_UNUSED,
-                                gint            y G_GNUC_UNUSED)
+void
+egg_tool_palette_set_drag_source (EggToolPalette *palette)
 {
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), NULL);
-  g_return_val_if_reached (NULL);
-}
+  guint i;
 
-/* ===== item settings ===== */
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
 
-void
-egg_tool_palette_set_item_category (EggToolPalette *self,
-                                    GtkToolItem    *item,
-                                    const gchar    *category G_GNUC_UNUSED)
-{
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-  g_return_if_reached ();
+  if (palette->priv->is_drag_source)
+    return;
+
+  palette->priv->is_drag_source = TRUE;
+
+  for (i = 0; i < palette->priv->groups->len; ++i)
+    gtk_container_foreach (GTK_CONTAINER (egg_tool_palette_get_group (palette, i)),
+                           _egg_tool_palette_item_set_drag_source,
+                           palette);
 }
 
 void
-egg_tool_palette_set_item_position (EggToolPalette *self,
-                                    GtkToolItem    *item,
-                                    gint            position G_GNUC_UNUSED)
+egg_tool_palette_add_drag_dest (EggToolPalette  *palette,
+                                GtkWidget       *widget,
+                                GtkDestDefaults  flags)
 {
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-  g_return_if_reached ();
-}
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
 
-G_CONST_RETURN gchar*
-egg_tool_palette_get_item_category (EggToolPalette *self,
-                                    GtkToolItem    *item)
-{
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), NULL);
-  g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), NULL);
-  g_return_val_if_reached (NULL);
-}
+  egg_tool_palette_set_drag_source (palette);
 
-gint
-egg_tool_palette_get_item_position (EggToolPalette *self,
-                                    GtkToolItem    *item)
-{
-  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (self), 0);
-  g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), 0);
-  g_return_val_if_reached (0);
+  gtk_drag_dest_set (widget, flags, dnd_targets,
+                     G_N_ELEMENTS (dnd_targets),
+                     GDK_ACTION_COPY);
 }
 
 void
-egg_tool_palette_set_drag_source (EggToolPalette *self)
+_egg_tool_palette_get_item_size (EggToolPalette *palette,
+                                 GtkRequisition *item_size)
 {
-  if (self->priv->is_drag_source)
-    return;
+  g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
+  g_return_if_fail (NULL != item_size);
 
-  gtk_container_foreach (GTK_CONTAINER (self),
-                         egg_tool_palette_item_set_drag_source,
-                         self);
-
-  self->priv->is_drag_source = TRUE;
+  *item_size = palette->priv->item_size;
 }
 
 static void
-egg_tool_palette_drag_data_received (GtkWidget        *widget G_GNUC_UNUSED,
+egg_tool_palette_item_drag_data_get (GtkWidget        *widget,
                                      GdkDragContext   *context G_GNUC_UNUSED,
-                                     gint              x G_GNUC_UNUSED,
-                                     gint              y G_GNUC_UNUSED,
-                                     GtkSelectionData *selection G_GNUC_UNUSED,
+                                     GtkSelectionData *selection,
                                      guint             info G_GNUC_UNUSED,
                                      guint             time G_GNUC_UNUSED,
                                      gpointer          data)
 {
-  GtkWidget *item = *(GtkWidget**) selection->data;
-  EggToolPaletteCallbackData *callback_data = data;
-  EggToolPalette *palette;
-
-  if (GTK_IS_TOOL_ITEM (item))
+  if (selection->target == dnd_target_atom)
     {
-      palette = EGG_TOOL_PALETTE (gtk_widget_get_parent (item));
-      callback_data->callback (palette, GTK_TOOL_ITEM (item), callback_data->user_data);
+      EggToolPaletteDragData drag_data = {
+        EGG_TOOL_PALETTE (data),
+        GTK_TOOL_ITEM (widget)
+      };
+
+      gtk_selection_data_set (selection, selection->target, 8,
+                              (guchar*) &drag_data,
+                              sizeof (drag_data));
     }
 }
 
-static void
-egg_tool_palette_callback_data_free (gpointer  data,
-                                     GClosure *closure G_GNUC_UNUSED)
-{
-  g_slice_free (EggToolPaletteCallbackData, data);
-}
-
 void
-egg_tool_palette_add_drag_dest (EggToolPalette         *self,
-                                GtkWidget              *widget,
-                                EggToolPaletteCallback  callback,
-                                gpointer                user_data)
+_egg_tool_palette_item_set_drag_source (GtkWidget *widget,
+                                        gpointer   data)
 {
-  EggToolPaletteCallbackData *callback_data;
+  EggToolPalette *palette = EGG_TOOL_PALETTE (data);
 
-  g_return_if_fail (EGG_IS_TOOL_PALETTE (self));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (NULL != callback);
+  g_return_if_fail (GTK_IS_TOOL_ITEM (widget));
 
-  callback_data = g_slice_new (EggToolPaletteCallbackData);
-  callback_data->user_data = user_data;
-  callback_data->callback = callback;
+  if (palette->priv->is_drag_source)
+    {
+      gtk_tool_item_set_use_drag_window (GTK_TOOL_ITEM (widget), TRUE);
 
-  gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL,
-                     dnd_targets, G_N_ELEMENTS (dnd_targets),
-                     GDK_ACTION_COPY);
+      gtk_drag_source_set (widget,
+                           GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+                           dnd_targets, G_N_ELEMENTS (dnd_targets),
+                           GDK_ACTION_COPY);
 
-  g_signal_connect_data (widget, "drag-data-received",
-                         G_CALLBACK (egg_tool_palette_drag_data_received),
-                         callback_data, egg_tool_palette_callback_data_free, 0);
+      g_signal_connect (widget, "drag-data-get",
+                        G_CALLBACK (egg_tool_palette_item_drag_data_get),
+                        palette);
+    }
 }
-

Modified: trunk/libegg/toolpalette/eggtoolpalette.h
==============================================================================
--- trunk/libegg/toolpalette/eggtoolpalette.h	(original)
+++ trunk/libegg/toolpalette/eggtoolpalette.h	Thu Jan 10 22:49:41 2008
@@ -1,7 +1,29 @@
+/* EggToolPalette -- A tool palette with categories and DnD support
+ * Copyright (C) 2008  Openismus GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *      Mathias Hasselmann
+ */
+
 #ifndef __EGG_TOOL_PALETTE_H__
 #define __EGG_TOOL_PALETTE_H__
 
 #include <gtk/gtkcontainer.h>
+#include <gtk/gtkdnd.h>
 #include <gtk/gtktoolitem.h>
 
 G_BEGIN_DECLS
@@ -13,13 +35,9 @@
 #define EGG_IS_TOOL_PALETTE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE(obj, EGG_TYPE_TOOL_PALETTE))
 #define EGG_TOOL_PALETTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_TOOL_PALETTE, EggToolPaletteClass))
 
-typedef struct _EggToolPalette        EggToolPalette;
-typedef struct _EggToolPaletteClass   EggToolPaletteClass;
-typedef struct _EggToolPalettePrivate EggToolPalettePrivate;
-
-typedef void (*EggToolPaletteCallback) (EggToolPalette *palette,
-                                        GtkToolItem    *item,
-                                        gpointer        data);
+typedef struct _EggToolPalette           EggToolPalette;
+typedef struct _EggToolPaletteClass      EggToolPaletteClass;
+typedef struct _EggToolPalettePrivate    EggToolPalettePrivate;
 
 struct _EggToolPalette
 {
@@ -36,67 +54,34 @@
                                   GtkAdjustment *vadjustment);
 };
 
-/* ===== instance handling ===== */
-
-GType                 egg_tool_palette_get_type              (void) G_GNUC_CONST;
-GtkWidget*            egg_tool_palette_new                   (void);
-
-/* ===== category settings ===== */
+GType           egg_tool_palette_get_type        (void) G_GNUC_CONST;
+GtkWidget*      egg_tool_palette_new             (void);
 
-void                  egg_tool_palette_set_category_name     (EggToolPalette *palette,
-                                                              const gchar    *category,
-                                                              const gchar    *name);
-void                  egg_tool_palette_set_category_position (EggToolPalette *palette,
-                                                              const gchar    *category,
-                                                              gint            position);
-void                  egg_tool_palette_set_category_expanded (EggToolPalette *palette,
-                                                              const gchar    *category,
-                                                              gboolean        expanded);
-
-G_CONST_RETURN gchar* egg_tool_palette_get_category_name     (EggToolPalette *palette,
-                                                              const gchar    *category);
-gint                  egg_tool_palette_get_category_position (EggToolPalette *palette,
-                                                              const gchar    *category);
-gboolean              egg_tool_palette_get_category_expanded (EggToolPalette *palette,
-                                                              const gchar    *category);
-
-/* ===== item packing ===== */
-
-void                  egg_tool_palette_insert            (EggToolPalette *palette,
-                                                          const gchar    *category,
-                                                          GtkToolItem    *item,
-                                                          gint            position);
-
-gint                  egg_tool_palette_get_n_items       (EggToolPalette *palette,
-                                                          const gchar    *category);
-GtkToolItem*          egg_tool_palette_get_nth_item      (EggToolPalette *palette,
-                                                          const gchar    *category,
-                                                          gint            index);
-GtkToolItem*          egg_tool_palette_get_drop_item     (EggToolPalette *palette,
-                                                          gint            x,
-                                                          gint            y);
-
-/* ===== item settings ===== */
-
-void                  egg_tool_palette_set_item_category (EggToolPalette *palette,
-                                                          GtkToolItem    *item,
-                                                          const gchar    *category);
-void                  egg_tool_palette_set_item_position (EggToolPalette *palette,
-                                                          GtkToolItem    *item,
-                                                          gint            position);
-
-G_CONST_RETURN gchar* egg_tool_palette_get_item_category (EggToolPalette *palette,
-                                                          GtkToolItem    *item);
-gint                  egg_tool_palette_get_item_position (EggToolPalette *palette,
-                                                          GtkToolItem    *item);
-
-/* ===== drag-and-drop ===== */
-
-void                  egg_tool_palette_set_drag_source   (EggToolPalette         *palette);
-void                  egg_tool_palette_add_drag_dest     (EggToolPalette         *palette,
-                                                          GtkWidget              *widget,
-                                                          EggToolPaletteCallback  callback,
-                                                          gpointer                user_data);
+void            egg_tool_palette_reorder_group   (EggToolPalette   *palette,
+                                                  GtkWidget        *group,
+                                                  guint             position);
+
+void            egg_tool_palette_set_icon_size   (EggToolPalette   *palette,
+                                                  GtkIconSize       icon_size);
+void            egg_tool_palette_set_orientation (EggToolPalette   *palette,
+                                                  GtkOrientation    orientation);
+void            egg_tool_palette_set_style       (EggToolPalette   *palette,
+                                                  GtkToolbarStyle   style);
+
+GtkIconSize     egg_tool_palette_get_icon_size   (EggToolPalette   *palette);
+GtkOrientation  egg_tool_palette_get_orientation (EggToolPalette   *palette);
+GtkToolbarStyle egg_tool_palette_get_style       (EggToolPalette   *palette);
+
+GtkToolItem*    egg_tool_palette_get_drop_item   (EggToolPalette   *palette,
+                                                  gint              x,
+                                                  gint              y);
+GtkToolItem*    egg_tool_palette_get_drag_item   (EggToolPalette   *palette,
+                                                  GtkSelectionData *selection);
+
+void            egg_tool_palette_set_drag_source (EggToolPalette   *palette);
+void            egg_tool_palette_add_drag_dest   (EggToolPalette   *palette,
+                                                  GtkWidget        *widget,
+                                                  GtkDestDefaults   flags);
 
 G_END_DECLS
 

Added: trunk/libegg/toolpalette/eggtoolpaletteprivate.h
==============================================================================
--- (empty file)
+++ trunk/libegg/toolpalette/eggtoolpaletteprivate.h	Thu Jan 10 22:49:41 2008
@@ -0,0 +1,36 @@
+/* EggToolPalette -- A tool palette with categories and DnD support
+ * Copyright (C) 2008  Openismus GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *      Mathias Hasselmann
+ */
+
+#ifndef __EGG_TOOL_PALETTE_PRIVATE_H__
+#define __EGG_TOOL_PALETTE_PRIVATE_H__
+
+#include "eggtoolpalette.h"
+#include "eggtoolitemgroup.h"
+
+void _egg_tool_palette_get_item_size        (EggToolPalette   *palette,
+                                             GtkRequisition   *item_size);
+void _egg_tool_palette_item_set_drag_source (GtkWidget        *widget,
+                                             gpointer          data);
+
+void _egg_tool_item_group_item_size_request (EggToolItemGroup *group,
+                                             GtkRequisition   *item_size);
+
+#endif /* __EGG_TOOL_PALETTE_PRIVATE_H__ */

Modified: trunk/libegg/toolpalette/testtoolpalette.c
==============================================================================
--- trunk/libegg/toolpalette/testtoolpalette.c	(original)
+++ trunk/libegg/toolpalette/testtoolpalette.c	Thu Jan 10 22:49:41 2008
@@ -1,4 +1,5 @@
 #include "eggtoolpalette.h"
+#include "eggtoolitemgroup.h"
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
@@ -25,7 +26,12 @@
 static void
 load_stock_items (EggToolPalette *palette)
 {
-  const gchar *group = NULL;
+  GtkWidget *group_af = egg_tool_item_group_new (_("Stock Icons (A-F)"));
+  GtkWidget *group_gn = egg_tool_item_group_new (_("Stock Icons (G-N)"));
+  GtkWidget *group_or = egg_tool_item_group_new (_("Stock Icons (O-R)"));
+  GtkWidget *group_sz = egg_tool_item_group_new (_("Stock Icons (S-Z)"));
+  GtkWidget *group = NULL;
+
   GtkToolItem *item;
   GSList *stock_ids;
   GSList *iter;
@@ -33,6 +39,11 @@
   stock_ids = gtk_stock_list_ids ();
   stock_ids = g_slist_sort (stock_ids, (GCompareFunc) strcmp);
 
+  gtk_container_add (GTK_CONTAINER (palette), group_af);
+  gtk_container_add (GTK_CONTAINER (palette), group_gn);
+  gtk_container_add (GTK_CONTAINER (palette), group_or);
+  gtk_container_add (GTK_CONTAINER (palette), group_sz);
+
   for (iter = stock_ids; iter; iter = g_slist_next (iter))
     {
       gchar *id = iter->data;
@@ -40,25 +51,25 @@
       switch (id[4])
         {
           case 'a':
-            group = "stock-icons-af";
+            group = group_af;
             break;
 
           case 'g':
-            group = "stock-icons-gn";
+            group = group_gn;
             break;
 
           case 'o':
-            group = "stock-icons-or";
+            group = group_or;
             break;
 
           case 's':
-            group = "stock-icons-sz";
+            group = group_sz;
             break;
         }
 
       item = gtk_tool_button_new_from_stock (id);
       gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (item), id);
-      egg_tool_palette_insert (palette, group, item, -1);
+      egg_tool_item_group_insert (EGG_TOOL_ITEM_GROUP (group), item, -1);
 
       g_free (id);
     }
@@ -67,13 +78,35 @@
 }
 
 static void
-contents_drop_cb (EggToolPalette *palette G_GNUC_UNUSED,
-                  GtkToolItem    *item,
-                  gpointer        data)
+contents_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x         G_GNUC_UNUSED,
+                             gint              y         G_GNUC_UNUSED,
+                             GtkSelectionData *selection,
+                             guint             info      G_GNUC_UNUSED,
+                             guint             time      G_GNUC_UNUSED,
+                             gpointer          data      G_GNUC_UNUSED)
+
 {
-  GtkTextBuffer *buffer = gtk_text_view_get_buffer (data);
-  const gchar *stock_id = gtk_tool_button_get_stock_id (GTK_TOOL_BUTTON (item));
-  gtk_text_buffer_set_text (buffer, stock_id, -1);
+  GtkWidget *palette = NULL;
+  GtkToolItem *item = NULL;
+  GtkTextBuffer *buffer;
+  const gchar *stock_id;
+
+  palette = gtk_drag_get_source_widget (context);
+
+  while (palette && !EGG_IS_TOOL_PALETTE (palette))
+    palette = gtk_widget_get_parent (palette);
+
+  if (palette)
+    item = egg_tool_palette_get_drag_item (EGG_TOOL_PALETTE (palette), selection);
+
+  if (GTK_IS_TOOL_ITEM (item))
+    {
+      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+      stock_id = gtk_tool_button_get_stock_id (GTK_TOOL_BUTTON (item));
+      gtk_text_buffer_set_text (buffer, stock_id, -1);
+    }
 }
 
 static GtkWidget*
@@ -152,17 +185,6 @@
 
   load_stock_items (EGG_TOOL_PALETTE (palette));
 
-  egg_tool_palette_set_category_name (EGG_TOOL_PALETTE (palette),
-                                      "stock-icons-af", _("Stock Icons (A-F)"));
-  egg_tool_palette_set_category_name (EGG_TOOL_PALETTE (palette),
-                                      "stock-icons-gn", _("Stock Icons (G-N)"));
-  egg_tool_palette_set_category_name (EGG_TOOL_PALETTE (palette),
-                                      "stock-icons-or", _("Stock Icons (O-R)"));
-  egg_tool_palette_set_category_name (EGG_TOOL_PALETTE (palette),
-                                      "stock-icons-sz", _("Stock Icons (S-Z)"));
-
-  egg_tool_palette_set_drag_source (EGG_TOOL_PALETTE (palette));
-
   palette_scroller = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (palette_scroller),
                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
@@ -173,9 +195,11 @@
 
   contents = gtk_text_view_new ();
   gtk_widget_set_size_request (contents, 100, 400);
-  egg_tool_palette_add_drag_dest (EGG_TOOL_PALETTE (palette),
-                                  contents, contents_drop_cb,
-                                  contents);
+  egg_tool_palette_add_drag_dest (EGG_TOOL_PALETTE (palette), contents, GTK_DEST_DEFAULT_ALL);
+
+  g_signal_connect (contents, "drag-data-received",
+                    G_CALLBACK (contents_drag_data_received),
+                    NULL);
 
   contents_scroller = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
@@ -219,18 +243,27 @@
   gtk_init (&argc, &argv);
 
   gtk_rc_parse_string ("                                \
-    style 'egg-tool-palette-header' {                   \
+    style 'egg-tool-item-group' {                       \
+      EggToolItemGroup::expander-size = 10              \
+    }                                                   \
+                                                        \
+    style 'egg-tool-item-group-header' {                \
       bg[NORMAL] = @selected_bg_color                   \
       fg[NORMAL] = @selected_fg_color                   \
       bg[PRELIGHT] = shade(1.04, @selected_bg_color)    \
       fg[PRELIGHT] = @selected_fg_color                 \
       bg[ACTIVE] = shade(0.9, @selected_bg_color)       \
       fg[ACTIVE] = shade(0.9, @selected_fg_color)       \
+                                                        \
       font_name = 'Sans Serif Bold 10.'                 \
+      GtkButton::inner_border = { 0, 3, 0, 0 }          \
     }                                                   \
                                                         \
-    widget_class '*<EggToolPalette>.GtkButton*'         \
-    style 'egg-tool-palette-header'                     \
+    class 'EggToolItemGroup'                            \
+    style 'egg-tool-item-group'                         \
+                                                        \
+    widget_class '*<EggToolItemGroup>.GtkButton*'       \
+    style 'egg-tool-item-group-header'                  \
     ");
 
   ui = create_ui ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]