[gimp] app: add tool-group support to GimpToolEditor



commit d1084c581658a8ee024731850276458d6f07d05f
Author: Ell <ell_se yahoo com>
Date:   Wed Jan 29 21:22:05 2020 +0200

    app: add tool-group support to GimpToolEditor
    
    Add tool-group support to GimpToolEditor, used to organize tools in
    the Preferences dialog, including creating, rearranging, and
    deleting groups.  Also, major cleanup.

 app/dialogs/preferences-dialog.c |   3 +-
 app/tools/gimp-tools.c           |  30 +-
 app/tools/gimp-tools.h           |  44 +-
 app/widgets/gimpdnd.c            | 366 ++++++++--------
 app/widgets/gimpdnd.h            |   4 +-
 app/widgets/gimpselectiondata.c  |  18 +-
 app/widgets/gimpselectiondata.h  |   2 +-
 app/widgets/gimptooleditor.c     | 872 ++++++++++++++++++++++++++-------------
 app/widgets/gimptooleditor.h     |  10 +-
 app/widgets/widgets-enums.h      |   2 +-
 10 files changed, 826 insertions(+), 525 deletions(-)
---
diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c
index 5c625f84f3..5f0fa571e1 100644
--- a/app/dialogs/preferences-dialog.c
+++ b/app/dialogs/preferences-dialog.c
@@ -2150,8 +2150,7 @@ prefs_dialog_new (Gimp       *gimp,
   /* Tool Editor */
   vbox2 = prefs_frame_new (_("Tools Configuration"),
                            GTK_CONTAINER (vbox), TRUE);
-  tool_editor = gimp_tool_editor_new (gimp->tool_info_list, gimp->user_context,
-                                      gimp_tools_get_default_order (gimp),
+  tool_editor = gimp_tool_editor_new (gimp->tool_item_list, gimp->user_context,
                                       GIMP_VIEW_SIZE_SMALL, 1);
 
   gtk_box_pack_start (GTK_BOX (vbox2), tool_editor, TRUE, TRUE, 0);
diff --git a/app/tools/gimp-tools.c b/app/tools/gimp-tools.c
index f01346ce6c..271895477a 100644
--- a/app/tools/gimp-tools.c
+++ b/app/tools/gimp-tools.c
@@ -197,9 +197,7 @@ gimp_tools_init (Gimp *gimp)
     gimp_operation_tool_register
   };
 
-  GList *default_order = NULL;
-  GList *list;
-  gint   i;
+  gint i;
 
   g_return_if_fail (GIMP_IS_GIMP (gimp));
 
@@ -217,20 +215,6 @@ gimp_tools_init (Gimp *gimp)
   gimp_tool_options_manager_init (gimp);
 
   tool_manager_init (gimp);
-
-  for (list = gimp_get_tool_info_iter (gimp);
-       list;
-       list = g_list_next (list))
-    {
-      const gchar *identifier = gimp_object_get_name (list->data);
-
-      default_order = g_list_prepend (default_order, g_strdup (identifier));
-    }
-
-  default_order = g_list_reverse (default_order);
-
-  g_object_set_data (G_OBJECT (gimp),
-                     "gimp-tools-default-order", default_order);
 }
 
 void
@@ -633,15 +617,6 @@ gimp_tools_reset (Gimp          *gimp,
   gimp_container_thaw (container);
 }
 
-GList *
-gimp_tools_get_default_order (Gimp *gimp)
-{
-  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
-
-  return g_object_get_data (G_OBJECT (gimp),
-                            "gimp-tools-default-order");
-}
-
 
 /*  private functions  */
 
@@ -748,9 +723,6 @@ gimp_tools_register (GType                   tool_type,
   if (tool_type == GIMP_TYPE_OPERATION_TOOL)
     tool_info->hidden = TRUE;
 
-  g_object_set_data (G_OBJECT (tool_info), "gimp-tool-default-visible",
-                     GINT_TO_POINTER (visible));
-
   g_object_set_data (G_OBJECT (tool_info), "gimp-tool-options-gui-func",
                      options_gui_func);
 
diff --git a/app/tools/gimp-tools.h b/app/tools/gimp-tools.h
index d718b168c5..5be61c3e12 100644
--- a/app/tools/gimp-tools.h
+++ b/app/tools/gimp-tools.h
@@ -19,29 +19,27 @@
 #define __GIMP_TOOLS_H__
 
 
-void       gimp_tools_init              (Gimp              *gimp);
-void       gimp_tools_exit              (Gimp              *gimp);
-
-void       gimp_tools_restore           (Gimp              *gimp);
-void       gimp_tools_save              (Gimp              *gimp,
-                                         gboolean           save_tool_options,
-                                         gboolean           always_save);
-
-gboolean   gimp_tools_clear             (Gimp              *gimp,
-                                         GError           **error);
-
-gboolean   gimp_tools_serialize         (Gimp              *gimp,
-                                         GimpContainer     *container,
-                                         GimpConfigWriter  *writer);
-gboolean   gimp_tools_deserialize       (Gimp              *gimp,
-                                         GimpContainer     *container,
-                                         GScanner          *scanner);
-
-void       gimp_tools_reset             (Gimp              *gimp,
-                                         GimpContainer     *container,
-                                         gboolean           user_toolrc);
-
-GList    * gimp_tools_get_default_order (Gimp              *gimp);
+void       gimp_tools_init        (Gimp              *gimp);
+void       gimp_tools_exit        (Gimp              *gimp);
+
+void       gimp_tools_restore     (Gimp              *gimp);
+void       gimp_tools_save        (Gimp              *gimp,
+                                   gboolean           save_tool_options,
+                                   gboolean           always_save);
+
+gboolean   gimp_tools_clear       (Gimp              *gimp,
+                                   GError           **error);
+
+gboolean   gimp_tools_serialize   (Gimp              *gimp,
+                                   GimpContainer     *container,
+                                   GimpConfigWriter  *writer);
+gboolean   gimp_tools_deserialize (Gimp              *gimp,
+                                   GimpContainer     *container,
+                                   GScanner          *scanner);
+
+void       gimp_tools_reset       (Gimp              *gimp,
+                                   GimpContainer     *container,
+                                   gboolean           user_toolrc);
 
 
 #endif  /* __GIMP_TOOLS_H__ */
diff --git a/app/widgets/gimpdnd.c b/app/widgets/gimpdnd.c
index 37c002bb70..b09f590dde 100644
--- a/app/widgets/gimpdnd.c
+++ b/app/widgets/gimpdnd.c
@@ -42,7 +42,7 @@
 #include "core/gimppalette.h"
 #include "core/gimppattern.h"
 #include "core/gimptemplate.h"
-#include "core/gimptoolinfo.h"
+#include "core/gimptoolitem.h"
 
 #include "text/gimpfont.h"
 
@@ -98,168 +98,168 @@ struct _GimpDndDataDef
 };
 
 
-static GtkWidget * gimp_dnd_get_viewable_icon  (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_viewable_func,
-                                                gpointer          get_viewable_data);
-static GtkWidget * gimp_dnd_get_component_icon (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_comp_func,
-                                                gpointer          get_comp_data);
-static GtkWidget * gimp_dnd_get_color_icon     (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_color_func,
-                                                gpointer          get_color_data);
-
-static void        gimp_dnd_get_uri_list_data  (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_uri_list_func,
-                                                gpointer          get_uri_list_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_uri_list_data  (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_uri_list_func,
-                                                gpointer          set_uri_list_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_xds_data       (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_image_func,
-                                                gpointer          get_image_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_color_data     (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_color_func,
-                                                gpointer          get_color_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_color_data     (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_color_func,
-                                                gpointer          set_color_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_stream_data    (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_stream_func,
-                                                gpointer          get_stream_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_stream_data    (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_stream_func,
-                                                gpointer          set_stream_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_pixbuf_data    (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_pixbuf_func,
-                                                gpointer          get_pixbuf_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_pixbuf_data    (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_pixbuf_func,
-                                                gpointer          set_pixbuf_data,
-                                                GtkSelectionData *selection);
-static void        gimp_dnd_get_component_data (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_comp_func,
-                                                gpointer          get_comp_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_component_data (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_comp_func,
-                                                gpointer          set_comp_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_image_data     (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_image_func,
-                                                gpointer          get_image_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_image_data     (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_image_func,
-                                                gpointer          set_image_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_item_data      (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_item_func,
-                                                gpointer          get_item_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_item_data      (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_item_func,
-                                                gpointer          set_item_data,
-                                                GtkSelectionData *selection);
-
-static void        gimp_dnd_get_object_data    (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                GCallback         get_object_func,
-                                                gpointer          get_object_data,
-                                                GtkSelectionData *selection);
-
-static gboolean    gimp_dnd_set_brush_data     (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_brush_func,
-                                                gpointer          set_brush_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_pattern_data   (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_pattern_func,
-                                                gpointer          set_pattern_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_gradient_data  (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_gradient_func,
-                                                gpointer          set_gradient_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_palette_data   (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_palette_func,
-                                                gpointer          set_palette_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_font_data      (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_font_func,
-                                                gpointer          set_font_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_buffer_data    (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_buffer_func,
-                                                gpointer          set_buffer_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_imagefile_data (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_imagefile_func,
-                                                gpointer          set_imagefile_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_template_data  (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_template_func,
-                                                gpointer          set_template_data,
-                                                GtkSelectionData *selection);
-static gboolean    gimp_dnd_set_tool_info_data (GtkWidget        *widget,
-                                                gint              x,
-                                                gint              y,
-                                                GCallback         set_tool_info_func,
-                                                gpointer          set_tool_info_data,
-                                                GtkSelectionData *selection);
+static GtkWidget * gimp_dnd_get_viewable_icon   (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_viewable_func,
+                                                 gpointer          get_viewable_data);
+static GtkWidget * gimp_dnd_get_component_icon  (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_comp_func,
+                                                 gpointer          get_comp_data);
+static GtkWidget * gimp_dnd_get_color_icon      (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_color_func,
+                                                 gpointer          get_color_data);
+
+static void        gimp_dnd_get_uri_list_data   (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_uri_list_func,
+                                                 gpointer          get_uri_list_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_uri_list_data   (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_uri_list_func,
+                                                 gpointer          set_uri_list_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_xds_data        (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_image_func,
+                                                 gpointer          get_image_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_color_data      (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_color_func,
+                                                 gpointer          get_color_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_color_data      (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_color_func,
+                                                 gpointer          set_color_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_stream_data     (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_stream_func,
+                                                 gpointer          get_stream_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_stream_data     (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_stream_func,
+                                                 gpointer          set_stream_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_pixbuf_data     (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_pixbuf_func,
+                                                 gpointer          get_pixbuf_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_pixbuf_data     (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_pixbuf_func,
+                                                 gpointer          set_pixbuf_data,
+                                                 GtkSelectionData *selection);
+static void        gimp_dnd_get_component_data  (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_comp_func,
+                                                 gpointer          get_comp_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_component_data  (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_comp_func,
+                                                 gpointer          set_comp_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_image_data      (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_image_func,
+                                                 gpointer          get_image_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_image_data      (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_image_func,
+                                                 gpointer          set_image_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_item_data       (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_item_func,
+                                                 gpointer          get_item_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_item_data       (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_item_func,
+                                                 gpointer          set_item_data,
+                                                 GtkSelectionData *selection);
+
+static void        gimp_dnd_get_object_data     (GtkWidget        *widget,
+                                                 GdkDragContext   *context,
+                                                 GCallback         get_object_func,
+                                                 gpointer          get_object_data,
+                                                 GtkSelectionData *selection);
+
+static gboolean    gimp_dnd_set_brush_data      (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_brush_func,
+                                                 gpointer          set_brush_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_pattern_data    (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_pattern_func,
+                                                 gpointer          set_pattern_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_gradient_data   (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_gradient_func,
+                                                 gpointer          set_gradient_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_palette_data    (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_palette_func,
+                                                 gpointer          set_palette_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_font_data       (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_font_func,
+                                                 gpointer          set_font_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_buffer_data     (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_buffer_func,
+                                                 gpointer          set_buffer_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_imagefile_data  (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_imagefile_func,
+                                                 gpointer          set_imagefile_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_template_data   (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_template_func,
+                                                 gpointer          set_template_data,
+                                                 GtkSelectionData *selection);
+static gboolean    gimp_dnd_set_tool_item_data  (GtkWidget        *widget,
+                                                 gint              x,
+                                                 gint              y,
+                                                 GCallback         set_tool_item_func,
+                                                 gpointer          set_tool_item_data,
+                                                 GtkSelectionData *selection);
 
 
 
@@ -585,17 +585,17 @@ static const GimpDndDataDef dnd_data_defs[] =
   },
 
   {
-    GIMP_TARGET_TOOL_INFO,
+    GIMP_TARGET_TOOL_ITEM,
 
-    "gimp-dnd-get-tool-info-func",
-    "gimp-dnd-get-tool-info-data",
+    "gimp-dnd-get-tool-item-func",
+    "gimp-dnd-get-tool-item-data",
 
-    "gimp-dnd-set-tool-info-func",
-    "gimp-dnd-set-tool-info-data",
+    "gimp-dnd-set-tool-item-func",
+    "gimp-dnd-set-tool-item-data",
 
     gimp_dnd_get_viewable_icon,
     gimp_dnd_get_object_data,
-    gimp_dnd_set_tool_info_data
+    gimp_dnd_set_tool_item_data
   },
 
   {
@@ -1923,9 +1923,9 @@ gimp_dnd_data_type_get_by_g_type (GType type)
     {
       dnd_type = GIMP_DND_TYPE_TEMPLATE;
     }
-  else if (g_type_is_a (type, GIMP_TYPE_TOOL_INFO))
+  else if (g_type_is_a (type, GIMP_TYPE_TOOL_ITEM))
     {
-      dnd_type = GIMP_DND_TYPE_TOOL_INFO;
+      dnd_type = GIMP_DND_TYPE_TOOL_ITEM;
     }
 
   return dnd_type;
@@ -2437,29 +2437,29 @@ gimp_dnd_set_template_data (GtkWidget        *widget,
 }
 
 
-/********************************/
-/*  GimpToolInfo dnd functions  */
-/********************************/
+/*********************************/
+/*  GimpToolEntry dnd functions  */
+/*********************************/
 
 static gboolean
-gimp_dnd_set_tool_info_data (GtkWidget        *widget,
+gimp_dnd_set_tool_item_data (GtkWidget        *widget,
                              gint              x,
                              gint              y,
-                             GCallback         set_tool_info_func,
-                             gpointer          set_tool_info_data,
+                             GCallback         set_tool_item_func,
+                             gpointer          set_tool_item_data,
                              GtkSelectionData *selection)
 {
-  GimpToolInfo *tool_info = gimp_selection_data_get_tool_info (selection,
+  GimpToolItem *tool_item = gimp_selection_data_get_tool_item (selection,
                                                                the_dnd_gimp);
 
-  GIMP_LOG (DND, "tool_info %p", tool_info);
+  GIMP_LOG (DND, "tool_item %p", tool_item);
 
-  if (! tool_info)
+  if (! tool_item)
     return FALSE;
 
-  (* (GimpDndDropViewableFunc) set_tool_info_func) (widget, x, y,
-                                                    GIMP_VIEWABLE (tool_info),
-                                                    set_tool_info_data);
+  (* (GimpDndDropViewableFunc) set_tool_item_func) (widget, x, y,
+                                                    GIMP_VIEWABLE (tool_item),
+                                                    set_tool_item_data);
 
   return TRUE;
 }
diff --git a/app/widgets/gimpdnd.h b/app/widgets/gimpdnd.h
index 880b95a750..b9f6f84d81 100644
--- a/app/widgets/gimpdnd.h
+++ b/app/widgets/gimpdnd.h
@@ -88,8 +88,8 @@
 #define GIMP_TARGET_TEMPLATE \
         { "application/x-gimp-template-name", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_TEMPLATE }
 
-#define GIMP_TARGET_TOOL_INFO \
-        { "application/x-gimp-tool-info-name", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_TOOL_INFO }
+#define GIMP_TARGET_TOOL_ITEM \
+        { "application/x-gimp-tool-item-name", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_TOOL_ITEM }
 
 #define GIMP_TARGET_NOTEBOOK_TAB \
         { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_NOTEBOOK_TAB }
diff --git a/app/widgets/gimpselectiondata.c b/app/widgets/gimpselectiondata.c
index ad4210e6d5..4c852e19f2 100644
--- a/app/widgets/gimpselectiondata.c
+++ b/app/widgets/gimpselectiondata.c
@@ -753,17 +753,29 @@ gimp_selection_data_get_template (GtkSelectionData *selection,
                                                           NULL);
 }
 
-GimpToolInfo *
-gimp_selection_data_get_tool_info (GtkSelectionData *selection,
+GimpToolItem *
+gimp_selection_data_get_tool_item (GtkSelectionData *selection,
                                    Gimp             *gimp)
 {
+  GimpToolItem *tool_item;
+
   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
   g_return_val_if_fail (selection != NULL, NULL);
 
-  return (GimpToolInfo *)
+  tool_item = (GimpToolItem *)
     gimp_selection_data_get_object (selection,
                                     gimp->tool_info_list,
                                     GIMP_OBJECT (gimp_tool_info_get_standard (gimp)));
+
+  if (! tool_item)
+    {
+      tool_item = (GimpToolItem *)
+        gimp_selection_data_get_object (selection,
+                                        gimp->tool_item_list,
+                                        NULL);
+    }
+
+  return tool_item;
 }
 
 
diff --git a/app/widgets/gimpselectiondata.h b/app/widgets/gimpselectiondata.h
index 25b87cb6c3..c2e9865982 100644
--- a/app/widgets/gimpselectiondata.h
+++ b/app/widgets/gimpselectiondata.h
@@ -105,7 +105,7 @@ GimpImagefile * gimp_selection_data_get_imagefile (GtkSelectionData *selection,
                                                    Gimp             *gimp);
 GimpTemplate  * gimp_selection_data_get_template  (GtkSelectionData *selection,
                                                    Gimp             *gimp);
-GimpToolInfo  * gimp_selection_data_get_tool_info (GtkSelectionData *selection,
+GimpToolItem  * gimp_selection_data_get_tool_item (GtkSelectionData *selection,
                                                    Gimp             *gimp);
 
 
diff --git a/app/widgets/gimptooleditor.c b/app/widgets/gimptooleditor.c
index 2250dcdc13..0408ed52ed 100644
--- a/app/widgets/gimptooleditor.c
+++ b/app/widgets/gimptooleditor.c
@@ -24,6 +24,7 @@
 #include <gegl.h>
 #include <gtk/gtk.h>
 
+#include "libgimpconfig/gimpconfig.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
 #include "widgets-types.h"
@@ -31,10 +32,14 @@
 #include "core/gimp.h"
 #include "core/gimpcontainer.h"
 #include "core/gimpcontext.h"
-#include "core/gimptoolinfo.h"
+#include "core/gimptoolgroup.h"
+#include "core/gimptreehandler.h"
+
+#include "tools/gimp-tools.h"
 
 #include "gimpcontainertreestore.h"
 #include "gimpcontainerview.h"
+#include "gimpdnd.h"
 #include "gimpviewrenderer.h"
 #include "gimptooleditor.h"
 #include "gimphelp-ids.h"
@@ -43,221 +48,170 @@
 #include "gimp-intl.h"
 
 
-typedef struct _GimpToolEditorPrivate GimpToolEditorPrivate;
-
 struct _GimpToolEditorPrivate
 {
-  GtkTreeModel  *model;
-  GimpContext   *context;
-  GimpContainer *container;
-  GtkWidget     *scrolled;
+  GimpContainer   *container;
+  GimpContext     *context;
+
+  GtkWidget       *scrolled;
+
+  GtkWidget       *new_group_button;
+  GtkWidget       *raise_button;
+  GtkWidget       *lower_button;
+  GtkWidget       *delete_button;
+  GtkWidget       *reset_button;
 
-  GtkWidget     *raise_button;
-  GtkWidget     *lower_button;
-  GtkWidget     *reset_button;
+  GimpTreeHandler *visible_changed_handler;
 
   /* State of tools at creation of the editor, stored to support
    * reverting changes
    */
-  gchar        **initial_tool_order;
-  gboolean      *initial_tool_visibility;
-  gint           n_tools;
-
-  GQuark         visible_handler_id;
-  GList         *default_tool_order;
+  gchar           *initial_tool_state;
 };
 
 
-static void   gimp_tool_editor_dispose     (GObject               *object);
-static void   gimp_tool_editor_finalize    (GObject               *object);
-
-static void   gimp_tool_editor_visible_notify
-                                           (GimpToolInfo          *tool_info,
-                                            GParamSpec            *pspec,
-                                            GimpToolEditor        *tool_editor);
-static void   gimp_tool_editor_eye_data_func
-                                           (GtkTreeViewColumn     *tree_column,
-                                            GtkCellRenderer       *cell,
-                                            GtkTreeModel          *tree_model,
-                                            GtkTreeIter           *iter,
-                                            gpointer               data);
-static void   gimp_tool_editor_eye_clicked (GtkCellRendererToggle *toggle,
-                                            gchar                 *path_str,
-                                            GdkModifierType        state,
-                                            GimpToolEditor        *tool_editor);
-
-static void   gimp_tool_editor_raise_clicked
-                                           (GtkButton             *button,
-                                            GimpToolEditor        *tool_editor);
-static void   gimp_tool_editor_raise_extend_clicked
-                                           (GtkButton             *button,
-                                            GdkModifierType        mask,
-                                            GimpToolEditor        *tool_editor);
-static void   gimp_tool_editor_lower_clicked
-                                           (GtkButton             *button,
-                                            GimpToolEditor        *tool_editor);
-static void   gimp_tool_editor_lower_extend_clicked
-                                           (GtkButton             *button,
-                                            GdkModifierType        mask,
-                                            GimpToolEditor        *tool_editor);
-static void   gimp_tool_editor_reset_clicked
-                                           (GtkButton             *button,
-                                            GimpToolEditor        *tool_editor);
-
-
-G_DEFINE_TYPE_WITH_PRIVATE (GimpToolEditor, gimp_tool_editor,
-                            GIMP_TYPE_CONTAINER_TREE_VIEW)
+/*  local function prototypes  */
+
+static void            gimp_tool_editor_view_iface_init           (GimpContainerViewInterface *iface);
+
+static void            gimp_tool_editor_constructed               (GObject                    *object);
+
+static gboolean        gimp_tool_editor_select_item               (GimpContainerView          *view,
+                                                                   GimpViewable               *viewable,
+                                                                   gpointer                    insert_data);
+static void            gimp_tool_editor_set_container             (GimpContainerView          
*container_view,
+                                                                   GimpContainer              *container);
+static void            gimp_tool_editor_set_context               (GimpContainerView          
*container_view,
+                                                                   GimpContext                *context);
+
+static gboolean        gimp_tool_editor_drop_possible             (GimpContainerTreeView      *tree_view,
+                                                                   GimpDndType                 src_type,
+                                                                   GimpViewable               *src_viewable,
+                                                                   GimpViewable               *dest_viewable,
+                                                                   GtkTreePath                *drop_path,
+                                                                   GtkTreeViewDropPosition     drop_pos,
+                                                                   GtkTreeViewDropPosition    
*return_drop_pos,
+                                                                   GdkDragAction              
*return_drag_action);
+static void            gimp_tool_editor_drop_viewable             (GimpContainerTreeView      *tree_view,
+                                                                   GimpViewable               *src_viewable,
+                                                                   GimpViewable               *dest_viewable,
+                                                                   GtkTreeViewDropPosition     drop_pos);
+
+static void            gimp_tool_editor_visible_changed          (GimpToolItem                *tool_item,
+                                                                  GimpToolEditor              *tool_editor);
+
+static void            gimp_tool_editor_eye_data_func            (GtkTreeViewColumn           *tree_column,
+                                                                  GtkCellRenderer             *cell,
+                                                                  GtkTreeModel                *tree_model,
+                                                                  GtkTreeIter                 *iter,
+                                                                  gpointer                     data);
+static void            gimp_tool_editor_eye_clicked              (GtkCellRendererToggle       *toggle,
+                                                                  gchar                       *path_str,
+                                                                  GdkModifierType              state,
+                                                                  GimpToolEditor              *tool_editor);
+
+static void            gimp_tool_editor_new_group_clicked        (GtkButton                   *button,
+                                                                  GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_raise_clicked            (GtkButton                   *button,
+                                                                  GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_raise_extend_clicked     (GtkButton                   *button,
+                                                                  GdkModifierType              mask,
+                                                                  GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_lower_clicked            (GtkButton                   *button,
+                                                                  GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_lower_extend_clicked     (GtkButton                   *button,
+                                                                  GdkModifierType              mask,
+                                                                  GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_delete_clicked           (GtkButton                   *button,
+                                                                  GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_reset_clicked            (GtkButton                   *button,
+                                                                  GimpToolEditor              *tool_editor);
+
+static GimpToolItem  * gimp_tool_editor_get_selected_tool_item   (GimpToolEditor              *tool_editor);
+static GimpContainer * gimp_tool_editor_get_tool_item_container  (GimpToolEditor              *tool_editor,
+                                                                  GimpToolItem                *tool_item);
+
+static void            gimp_tool_editor_update_container         (GimpToolEditor              *tool_editor);
+static void            gimp_tool_editor_update_sensitivity       (GimpToolEditor              *tool_editor);
+
+
+G_DEFINE_TYPE_WITH_CODE (GimpToolEditor, gimp_tool_editor,
+                         GIMP_TYPE_CONTAINER_TREE_VIEW,
+                         G_ADD_PRIVATE (GimpToolEditor)
+                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONTAINER_VIEW,
+                                                gimp_tool_editor_view_iface_init))
 
 #define parent_class gimp_tool_editor_parent_class
 
-#define GIMP_TOOL_EDITOR_GET_PRIVATE(obj) ((GimpToolEditorPrivate *) gimp_tool_editor_get_instance_private 
((GimpToolEditor *) (obj)))
+static GimpContainerViewInterface *parent_view_iface = NULL;
+
 
+/*  private functions  */
 
 static void
 gimp_tool_editor_class_init (GimpToolEditorClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GObjectClass               *object_class    = G_OBJECT_CLASS (klass);
+  GimpContainerTreeViewClass *tree_view_class = GIMP_CONTAINER_TREE_VIEW_CLASS (klass);
 
-  object_class->dispose  = gimp_tool_editor_dispose;
-  object_class->finalize = gimp_tool_editor_finalize;
+  object_class->constructed      = gimp_tool_editor_constructed;
+
+  tree_view_class->drop_possible = gimp_tool_editor_drop_possible;
+  tree_view_class->drop_viewable = gimp_tool_editor_drop_viewable;
 }
 
 static void
-gimp_tool_editor_init (GimpToolEditor *tool_editor)
+gimp_tool_editor_view_iface_init (GimpContainerViewInterface *iface)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
+  parent_view_iface = g_type_interface_peek_parent (iface);
 
-  priv->model                   = NULL;
-  priv->context                 = NULL;
-  priv->container               = NULL;
-  priv->scrolled                = NULL;
+  if (! parent_view_iface)
+    parent_view_iface = g_type_default_interface_peek (GIMP_TYPE_CONTAINER_VIEW);
 
-  priv->visible_handler_id      = 0;
-  priv->default_tool_order      = NULL;
-
-  priv->initial_tool_order      = NULL;
-  priv->initial_tool_visibility = NULL;
-  priv->n_tools                 = 0;
-
-  priv->raise_button            = NULL;
-  priv->lower_button            = NULL;
-  priv->reset_button            = NULL;
+  iface->select_item   = gimp_tool_editor_select_item;
+  iface->set_container = gimp_tool_editor_set_container;
+  iface->set_context   = gimp_tool_editor_set_context;
 }
 
 static void
-gimp_tool_editor_dispose (GObject *object)
+gimp_tool_editor_init (GimpToolEditor *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (object);
-
-  if (priv->visible_handler_id)
-    {
-      gimp_container_remove_handler (priv->container,
-                                     priv->visible_handler_id);
-      priv->visible_handler_id = 0;
-    }
-
-  priv->context      = NULL;
-  priv->container    = NULL;
-
-  priv->raise_button = NULL;
-  priv->lower_button = NULL;
-  priv->reset_button = NULL;
-
-  priv->scrolled     = NULL;
-
-  G_OBJECT_CLASS (parent_class)->dispose (object);
+  tool_editor->priv = gimp_tool_editor_get_instance_private (tool_editor);
 }
 
 static void
-gimp_tool_editor_finalize (GObject *object)
+gimp_tool_editor_constructed (GObject *object)
 {
-  GimpToolEditor *tool_editor;
-  GimpToolEditorPrivate *priv;
-
-  tool_editor = GIMP_TOOL_EDITOR (object);
-  priv        = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
+  GimpToolEditor        *tool_editor    = GIMP_TOOL_EDITOR (object);
+  GimpContainerTreeView *tree_view      = GIMP_CONTAINER_TREE_VIEW (object);
+  GimpContainerView     *container_view = GIMP_CONTAINER_VIEW (object);
+  gint                   view_size;
+  gint                   border_width;
 
-  if (priv->initial_tool_order)
-    {
-      int i;
-
-      for (i = 0; i < priv->n_tools; i++)
-        {
-          g_free (priv->initial_tool_order[i]);
-        }
+  G_OBJECT_CLASS (parent_class)->constructed (object);
 
-      g_clear_pointer (&priv->initial_tool_order, g_free);
-    }
+  view_size = gimp_container_view_get_view_size (container_view,
+                                                 &border_width);
 
-  if (priv->initial_tool_visibility)
-    {
-      g_slice_free1 (sizeof (gboolean) * priv->n_tools,
-                     priv->initial_tool_visibility);
+  gimp_editor_set_show_name (GIMP_EDITOR (tool_editor), FALSE);
 
-      priv->initial_tool_visibility = NULL;
-    }
+  gtk_tree_view_set_level_indentation (tree_view->view,
+                                       0.8 * (view_size + 2 * border_width));
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
+  gimp_dnd_viewable_dest_add (GTK_WIDGET (tree_view->view),
+                              GIMP_TYPE_TOOL_ITEM,
+                              NULL, NULL);
 
-GtkWidget *
-gimp_tool_editor_new (GimpContainer *container,
-                      GimpContext   *context,
-                      GList         *default_tool_order,
-                      gint           view_size,
-                      gint           view_border_width)
-{
-  int                    i;
-  GimpToolEditor        *tool_editor;
-  GimpContainerTreeView *tree_view;
-  GimpContainerView     *container_view;
-  GObject               *object;
-  GimpObject            *gimp_object;
-  GimpToolEditorPrivate *priv;
-
-  g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
-  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
-
-  object         = g_object_new (GIMP_TYPE_TOOL_EDITOR, NULL);
-  tool_editor    = GIMP_TOOL_EDITOR (object);
-  tree_view      = GIMP_CONTAINER_TREE_VIEW (object);
-  container_view = GIMP_CONTAINER_VIEW (object);
-  priv           = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
-
-  priv->container               = container;
-  priv->context                 = context;
-  priv->model                   = tree_view->model;
-  priv->default_tool_order      = default_tool_order;
-  priv->initial_tool_order      = gimp_container_get_name_array (container,
-                                                                 &priv->n_tools);
-  priv->initial_tool_visibility = g_slice_alloc (sizeof (gboolean) *
-                                                 priv->n_tools);
-  for (i = 0; i < priv->n_tools; i++)
-    {
-      gimp_object = gimp_container_get_child_by_index (container, i);
-
-      g_object_get (gimp_object,
-                    "visible", &(priv->initial_tool_visibility[i]), NULL);
-    }
+  /* construct tree view */
+  {
+    GtkTreeViewColumn *column;
+    GtkCellRenderer   *eye_cell;
+    GtkStyleContext   *tree_style;
+    GtkBorder          border;
+    gint               icon_size;
 
-  gimp_container_view_set_view_size (container_view,
-                                     view_size, view_border_width);
-  gimp_container_view_set_container (container_view, priv->container);
-  gimp_container_view_set_context (container_view, context);
-  gimp_container_view_set_reorderable (container_view, TRUE);
-  gimp_editor_set_show_name (GIMP_EDITOR (tree_view), FALSE);
+    tree_style = gtk_widget_get_style_context (GTK_WIDGET (tool_editor));
 
-  /* Construct tree view */
-  {
-    GimpContainerTreeView *tree_view   = GIMP_CONTAINER_TREE_VIEW (tool_editor);
-    GtkWidget             *tree_widget = GTK_WIDGET (tree_view);
-    GtkStyleContext       *tree_style;
-    GtkTreeViewColumn     *column;
-    GtkCellRenderer       *eye_cell;
-    GtkBorder              border;
-    gint                   icon_size;
-
-    tree_style = gtk_widget_get_style_context (tree_widget);
     gtk_style_context_get_border (tree_style, 0, &border);
 
     column = gtk_tree_view_column_new ();
@@ -280,83 +234,195 @@ gimp_tool_editor_new (GimpContainer *container,
     g_signal_connect (eye_cell, "clicked",
                       G_CALLBACK (gimp_tool_editor_eye_clicked),
                       tool_editor);
-
-    priv->visible_handler_id =
-      gimp_container_add_handler (container, "notify::visible",
-                                  G_CALLBACK (gimp_tool_editor_visible_notify),
-                                  tool_editor);
   }
 
   /* buttons */
-  priv->raise_button =
-    gimp_editor_add_button (GIMP_EDITOR (tree_view), GIMP_ICON_GO_UP,
+  tool_editor->priv->new_group_button =
+    gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_FOLDER_NEW,
+                            _("Create a new tool group"), NULL,
+                            G_CALLBACK (gimp_tool_editor_new_group_clicked),
+                            NULL,
+                            tool_editor);
+
+  tool_editor->priv->raise_button =
+    gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_GO_UP,
                             _("Raise this tool"),
                             _("Raise this tool to the top"),
                             G_CALLBACK (gimp_tool_editor_raise_clicked),
                             G_CALLBACK (gimp_tool_editor_raise_extend_clicked),
                             tool_editor);
 
-  priv->lower_button =
-    gimp_editor_add_button (GIMP_EDITOR (tree_view), GIMP_ICON_GO_DOWN,
+  tool_editor->priv->lower_button =
+    gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_GO_DOWN,
                             _("Lower this tool"),
                             _("Lower this tool to the bottom"),
                             G_CALLBACK (gimp_tool_editor_lower_clicked),
                             G_CALLBACK (gimp_tool_editor_lower_extend_clicked),
                             tool_editor);
 
-  priv->reset_button =
-    gimp_editor_add_button (GIMP_EDITOR (tree_view), GIMP_ICON_RESET,
+  tool_editor->priv->delete_button =
+    gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_EDIT_DELETE,
+                            _("Delete this tool"), NULL,
+                            G_CALLBACK (gimp_tool_editor_delete_clicked),
+                            NULL,
+                            tool_editor);
+
+  tool_editor->priv->reset_button =
+    gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_RESET,
                             _("Reset tool order and visibility"), NULL,
-                            G_CALLBACK (gimp_tool_editor_reset_clicked), NULL,
+                            G_CALLBACK (gimp_tool_editor_reset_clicked),
+                            NULL,
                             tool_editor);
 
-  return GTK_WIDGET (tool_editor);
+  gimp_tool_editor_update_sensitivity (tool_editor);
 }
 
-/**
- * gimp_tool_editor_revert_changes:
- * @tool_editor:
- *
- * Reverts the tool order and visibility to the state at creation.
- **/
-void
-gimp_tool_editor_revert_changes (GimpToolEditor *tool_editor)
+static gboolean
+gimp_tool_editor_select_item (GimpContainerView *container_view,
+                              GimpViewable      *viewable,
+                              gpointer           insert_data)
 {
-  int i;
-  GimpToolEditorPrivate *priv;
+  GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
+  gboolean        result;
 
-  priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
+  result = parent_view_iface->select_item (container_view,
+                                           viewable, insert_data);
 
-  for (i = 0; i < priv->n_tools; i++)
+  gimp_tool_editor_update_sensitivity (tool_editor);
+
+  return result;
+}
+
+static void
+gimp_tool_editor_set_container (GimpContainerView *container_view,
+                                GimpContainer     *container)
+{
+  GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
+
+  parent_view_iface->set_container (container_view, container);
+
+  gimp_tool_editor_update_container (tool_editor);
+}
+
+static void
+gimp_tool_editor_set_context (GimpContainerView *container_view,
+                              GimpContext       *context)
+{
+  GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
+
+  parent_view_iface->set_context (container_view, context);
+
+  gimp_tool_editor_update_container (tool_editor);
+}
+
+static gboolean
+gimp_tool_editor_drop_possible (GimpContainerTreeView   *tree_view,
+                                GimpDndType              src_type,
+                                GimpViewable            *src_viewable,
+                                GimpViewable            *dest_viewable,
+                                GtkTreePath             *drop_path,
+                                GtkTreeViewDropPosition  drop_pos,
+                                GtkTreeViewDropPosition *return_drop_pos,
+                                GdkDragAction           *return_drag_action)
+{
+  if (GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (
+        tree_view,
+        src_type, src_viewable, dest_viewable, drop_path, drop_pos,
+        return_drop_pos, return_drag_action))
+    {
+      if (gimp_viewable_get_parent (dest_viewable)       ||
+          (gimp_viewable_get_children (dest_viewable)    &&
+           (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
+            drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
+        {
+          return ! gimp_viewable_get_children (src_viewable);
+        }
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gimp_tool_editor_drop_viewable (GimpContainerTreeView   *tree_view,
+                                GimpViewable            *src_viewable,
+                                GimpViewable            *dest_viewable,
+                                GtkTreeViewDropPosition  drop_pos)
+{
+  GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tree_view);
+
+  GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewable (tree_view,
+                                                                src_viewable,
+                                                                dest_viewable,
+                                                                drop_pos);
+
+  gimp_container_view_select_item (container_view, src_viewable);
+}
+
+static void
+gimp_tool_editor_new_group_clicked (GtkButton      *button,
+                                    GimpToolEditor *tool_editor)
+{
+  GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
+  GimpContainer     *container;
+  GimpToolItem      *tool_item;
+  GimpToolGroup     *group;
+  gint               index = 0;
+
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
+
+  if (tool_item)
+    {
+      if (gimp_viewable_get_parent (GIMP_VIEWABLE (tool_item)) != NULL)
+        return;
+
+      container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                            tool_item);
+
+      index = gimp_container_get_child_index (container,
+                                              GIMP_OBJECT (tool_item));
+    }
+  else
     {
-      GimpObject *object;
+      container = tool_editor->priv->container;
+    }
+
+  if (container)
+    {
+      group = gimp_tool_group_new ();
+
+      gimp_container_insert (container, GIMP_OBJECT (group), index);
 
-      object = gimp_container_get_child_by_name (priv->container,
-                                                 priv->initial_tool_order[i]);
+      g_object_unref (group);
 
-      gimp_container_reorder (priv->container, object, i);
-      g_object_set (object, "visible", priv->initial_tool_visibility[i], NULL);
+      gimp_container_view_select_item (container_view, GIMP_VIEWABLE (group));
     }
 }
 
 static void
-gimp_tool_editor_raise_clicked (GtkButton    *button,
+gimp_tool_editor_raise_clicked (GtkButton      *button,
                                 GimpToolEditor *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
-  GimpToolInfo          *tool_info;
+  GimpToolItem *tool_item;
 
-  tool_info = gimp_context_get_tool (priv->context);
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
 
-  if (tool_info)
+  if (tool_item)
     {
-      gint index = gimp_container_get_child_index (priv->container,
-                                                   GIMP_OBJECT (tool_info));
+      GimpContainer *container;
+      gint           index;
+
+      container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                            tool_item);
+
+      index = gimp_container_get_child_index (container,
+                                              GIMP_OBJECT (tool_item));
 
       if (index > 0)
         {
-          gimp_container_reorder (priv->container,
-                                  GIMP_OBJECT (tool_info), index - 1);
+          gimp_container_reorder (container,
+                                  GIMP_OBJECT (tool_item), index - 1);
         }
     }
 }
@@ -364,44 +430,54 @@ gimp_tool_editor_raise_clicked (GtkButton    *button,
 static void
 gimp_tool_editor_raise_extend_clicked (GtkButton       *button,
                                        GdkModifierType  mask,
-                                       GimpToolEditor    *tool_editor)
+                                       GimpToolEditor  *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
-  GimpToolInfo          *tool_info;
+  GimpToolItem *tool_item;
 
-  tool_info = gimp_context_get_tool (priv->context);
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
 
-  if (tool_info && (mask & GDK_SHIFT_MASK))
+  if (tool_item && (mask & GDK_SHIFT_MASK))
     {
-      gint index = gimp_container_get_child_index (priv->container,
-                                                   GIMP_OBJECT (tool_info));
+      GimpContainer *container;
+      gint           index;
+
+      container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                            tool_item);
+
+      index = gimp_container_get_child_index (container,
+                                              GIMP_OBJECT (tool_item));
 
       if (index > 0)
         {
-          gimp_container_reorder (priv->container,
-                                  GIMP_OBJECT (tool_info), 0);
+          gimp_container_reorder (container,
+                                  GIMP_OBJECT (tool_item), 0);
         }
     }
 }
 
 static void
-gimp_tool_editor_lower_clicked (GtkButton    *button,
+gimp_tool_editor_lower_clicked (GtkButton      *button,
                                 GimpToolEditor *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
-  GimpToolInfo          *tool_info;
+  GimpToolItem *tool_item;
 
-  tool_info = gimp_context_get_tool (priv->context);
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
 
-  if (tool_info)
+  if (tool_item)
     {
-      gint index = gimp_container_get_child_index (priv->container,
-                                                   GIMP_OBJECT (tool_info));
+      GimpContainer *container;
+      gint           index;
 
-      if (index + 1 < gimp_container_get_n_children (priv->container))
+      container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                            tool_item);
+
+      index = gimp_container_get_child_index (container,
+                                              GIMP_OBJECT (tool_item));
+
+      if (index + 1 < gimp_container_get_n_children (container))
         {
-          gimp_container_reorder (priv->container,
-                                  GIMP_OBJECT (tool_info), index + 1);
+          gimp_container_reorder (container,
+                                  GIMP_OBJECT (tool_item), index + 1);
         }
     }
 }
@@ -409,74 +485,125 @@ gimp_tool_editor_lower_clicked (GtkButton    *button,
 static void
 gimp_tool_editor_lower_extend_clicked (GtkButton       *button,
                                        GdkModifierType  mask,
-                                       GimpToolEditor    *tool_editor)
+                                       GimpToolEditor  *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
-  GimpToolInfo          *tool_info;
+  GimpToolItem *tool_item;
 
-  tool_info = gimp_context_get_tool (priv->context);
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
 
-  if (tool_info && (mask & GDK_SHIFT_MASK))
+  if (tool_item && (mask & GDK_SHIFT_MASK))
     {
-      gint index = gimp_container_get_n_children (priv->container) - 1;
+      GimpContainer *container;
+      gint           index;
+
+      container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                            tool_item);
 
+      index = gimp_container_get_n_children (container) - 1;
       index = MAX (index, 0);
 
-      gimp_container_reorder (priv->container,
-                              GIMP_OBJECT (tool_info), index);
+      gimp_container_reorder (container,
+                              GIMP_OBJECT (tool_item), index);
     }
 }
 
 static void
-gimp_tool_editor_reset_clicked (GtkButton    *button,
-                                GimpToolEditor *tool_editor)
+gimp_tool_editor_delete_clicked (GtkButton      *button,
+                                 GimpToolEditor *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
-  GList                 *list;
-  gint                   i;
+  GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
+  GimpToolItem     *tool_item;
+
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
 
-  for (list = priv->default_tool_order, i = 0;
-       list;
-       list = g_list_next (list), i++)
+  if (tool_item)
     {
-      GimpObject *object =
-        gimp_container_get_child_by_name (priv->container, list->data);
+      GimpContainer *src_container;
+      GimpContainer *dest_container;
+      gint           index;
+      gint           dest_index;
+
+      src_container  = gimp_viewable_get_children (GIMP_VIEWABLE (tool_item));
+      dest_container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                                 tool_item);
+
+      if (! src_container)
+        return;
+
+      index      = gimp_container_get_child_index (dest_container,
+                                                   GIMP_OBJECT (tool_item));
+      dest_index = index;
+
+      g_object_ref (tool_item);
+
+      gimp_container_freeze (src_container);
+      gimp_container_freeze (dest_container);
 
-      if (object)
+      gimp_container_remove (dest_container, GIMP_OBJECT (tool_item));
+
+      while (! gimp_container_is_empty (src_container))
         {
-          gboolean visible;
-          gpointer data;
+          GimpObject *object = gimp_container_get_first_child (src_container);
+
+          g_object_ref (object);
 
-          gimp_container_reorder (priv->container, object, i);
-          data = g_object_get_data (G_OBJECT (object),
-                                    "gimp-tool-default-visible");
+          gimp_container_remove (src_container,  object);
+          gimp_container_insert (dest_container, object, dest_index++);
 
-          visible = GPOINTER_TO_INT (data);
-          g_object_set (object, "visible", visible, NULL);
+          g_object_unref (object);
         }
+
+      gimp_container_thaw (dest_container);
+      gimp_container_thaw (src_container);
+
+      gimp_container_view_select_item (
+        container_view,
+        GIMP_VIEWABLE (gimp_container_get_child_by_index (dest_container,
+                                                          index)));
+
+      g_object_unref (tool_item);
     }
 }
 
 static void
-gimp_tool_editor_visible_notify (GimpToolInfo  *tool_info,
-                                 GParamSpec    *pspec,
-                                 GimpToolEditor  *tool_editor)
+gimp_tool_editor_reset_clicked (GtkButton      *button,
+                                GimpToolEditor *tool_editor)
+{
+  gimp_tools_reset (tool_editor->priv->context->gimp,
+                    tool_editor->priv->container,
+                    FALSE);
+}
+
+static void
+gimp_tool_editor_visible_changed (GimpToolItem   *tool_item,
+                                  GimpToolEditor *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
+  GimpContainerTreeView *tree_view      = GIMP_CONTAINER_TREE_VIEW (tool_editor);
+  GimpContainerView     *container_view = GIMP_CONTAINER_VIEW (tool_editor);
   GtkTreeIter           *iter;
 
-  iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (tool_editor),
-                                     GIMP_VIEWABLE (tool_info));
+  iter = gimp_container_view_lookup (container_view,
+                                     GIMP_VIEWABLE (tool_item));
 
   if (iter)
     {
-      GtkTreePath *path;
+      GtkTreePath   *path;
+      GimpContainer *children;
 
-      path = gtk_tree_model_get_path (priv->model, iter);
+      path = gtk_tree_model_get_path (tree_view->model, iter);
 
-      gtk_tree_model_row_changed (priv->model, path, iter);
+      gtk_tree_model_row_changed (tree_view->model, path, iter);
 
       gtk_tree_path_free (path);
+
+      children = gimp_viewable_get_children (GIMP_VIEWABLE (tool_item));
+
+      if (children)
+        {
+          gimp_container_foreach (children,
+                                  (GFunc) gimp_tool_editor_visible_changed,
+                                  tool_editor);
+        }
     }
 }
 
@@ -488,17 +615,21 @@ gimp_tool_editor_eye_data_func (GtkTreeViewColumn *tree_column,
                                 gpointer           data)
 {
   GimpViewRenderer *renderer;
-  gboolean          visible;
+  GimpToolItem     *tool_item;
 
   gtk_tree_model_get (tree_model, iter,
                       GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
                       -1);
 
-  g_object_get (renderer->viewable, "visible", &visible, NULL);
+  tool_item = GIMP_TOOL_ITEM (renderer->viewable);
 
-  g_object_unref (renderer);
+  g_object_set (cell,
+                "active",       gimp_tool_item_get_visible (tool_item),
+                "inconsistent", gimp_tool_item_get_visible (tool_item) &&
+                                ! gimp_tool_item_is_visible (tool_item),
+                NULL);
 
-  g_object_set (cell, "active", visible, NULL);
+  g_object_unref (renderer);
 }
 
 static void
@@ -507,28 +638,215 @@ gimp_tool_editor_eye_clicked (GtkCellRendererToggle *toggle,
                               GdkModifierType        state,
                               GimpToolEditor        *tool_editor)
 {
-  GimpToolEditorPrivate *priv = GIMP_TOOL_EDITOR_GET_PRIVATE (tool_editor);
+  GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (tool_editor);
   GtkTreePath           *path;
   GtkTreeIter            iter;
 
   path = gtk_tree_path_new_from_string (path_str);
 
-  if (gtk_tree_model_get_iter (priv->model, &iter, path))
+  if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
     {
       GimpViewRenderer *renderer;
+      GimpToolItem     *tool_item;
       gboolean          active;
 
+      gtk_tree_model_get (tree_view->model, &iter,
+                          GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
+                          -1);
+
+      tool_item = GIMP_TOOL_ITEM (renderer->viewable);
+
       g_object_get (toggle,
                     "active", &active,
                     NULL);
-      gtk_tree_model_get (priv->model, &iter,
+
+      gimp_tool_item_set_visible (tool_item, ! active);
+
+      g_object_unref (renderer);
+    }
+
+  gtk_tree_path_free (path);
+}
+
+static GimpToolItem *
+gimp_tool_editor_get_selected_tool_item (GimpToolEditor *tool_editor)
+{
+  GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (tool_editor);
+
+  if (tool_editor->priv->container)
+    {
+      GimpViewRenderer *renderer;
+      GimpToolItem     *tool_item;
+      GtkTreeSelection *selection;
+      GtkTreeModel     *model;
+      GtkTreeIter       iter;
+
+      selection = gtk_tree_view_get_selection (tree_view->view);
+
+      if (! gtk_tree_selection_get_selected (selection, &model, &iter))
+        return NULL;
+
+      gtk_tree_model_get (model, &iter,
                           GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
                           -1);
 
-      g_object_set (renderer->viewable, "visible", ! active, NULL);
+      tool_item = GIMP_TOOL_ITEM (renderer->viewable);
 
       g_object_unref (renderer);
+
+      return tool_item;
     }
 
-  gtk_tree_path_free (path);
+  return NULL;
+}
+
+static GimpContainer *
+gimp_tool_editor_get_tool_item_container (GimpToolEditor *tool_editor,
+                                          GimpToolItem   *tool_item)
+{
+  GimpViewable *parent;
+
+  parent = gimp_viewable_get_parent (GIMP_VIEWABLE (tool_item));
+
+  if (parent)
+    {
+      return gimp_viewable_get_children (parent);
+    }
+  else
+    {
+      return tool_editor->priv->container;
+    }
+}
+
+static void
+gimp_tool_editor_update_container (GimpToolEditor *tool_editor)
+{
+  GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
+  GimpContainer     *container;
+  GimpContext       *context;
+
+  g_clear_pointer (&tool_editor->priv->visible_changed_handler,
+                   gimp_tree_handler_disconnect);
+
+  g_clear_pointer (&tool_editor->priv->initial_tool_state, g_free);
+
+  container = gimp_container_view_get_container (container_view);
+  context   = gimp_container_view_get_context   (container_view);
+
+  if (container && context)
+    {
+      GString          *string;
+      GimpConfigWriter *writer;
+
+      tool_editor->priv->container = container;
+      tool_editor->priv->context   = context;
+
+      tool_editor->priv->visible_changed_handler = gimp_tree_handler_connect (
+        container, "visible-changed",
+        G_CALLBACK (gimp_tool_editor_visible_changed),
+        tool_editor);
+
+      /* save initial tool order */
+      string = g_string_new (NULL);
+
+      writer = gimp_config_writer_new_from_string (string);
+
+      gimp_tools_serialize (context->gimp, container, writer);
+
+      gimp_config_writer_finish (writer, NULL, NULL);
+
+      tool_editor->priv->initial_tool_state = g_string_free (string, FALSE);
+    }
+}
+
+static void
+gimp_tool_editor_update_sensitivity (GimpToolEditor *tool_editor)
+{
+  GimpToolItem *tool_item;
+
+  tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
+
+  if (tool_item)
+    {
+      GimpContainer *container;
+      gint           index;
+
+      container = gimp_tool_editor_get_tool_item_container (tool_editor,
+                                                            tool_item);
+
+      index = gimp_container_get_child_index (container,
+                                              GIMP_OBJECT (tool_item));
+
+      gtk_widget_set_sensitive (
+        tool_editor->priv->new_group_button,
+        gimp_viewable_get_parent (GIMP_VIEWABLE (tool_item)) == NULL);
+
+      gtk_widget_set_sensitive (
+        tool_editor->priv->raise_button,
+        index > 0);
+
+      gtk_widget_set_sensitive (
+        tool_editor->priv->lower_button,
+        index < gimp_container_get_n_children (container) - 1);
+
+      gtk_widget_set_sensitive (
+        tool_editor->priv->delete_button,
+        gimp_viewable_get_children (GIMP_VIEWABLE (tool_item)) != NULL);
+    }
+  else
+    {
+      gtk_widget_set_sensitive (tool_editor->priv->new_group_button, TRUE);
+      gtk_widget_set_sensitive (tool_editor->priv->raise_button,     FALSE);
+      gtk_widget_set_sensitive (tool_editor->priv->lower_button,     FALSE);
+      gtk_widget_set_sensitive (tool_editor->priv->delete_button,    FALSE);
+    }
+}
+
+
+/*  public functions  */
+
+GtkWidget *
+gimp_tool_editor_new (GimpContainer *container,
+                      GimpContext   *context,
+                      gint           view_size,
+                      gint           view_border_width)
+{
+  GimpContainerView *container_view;
+
+  g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
+  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+  container_view = g_object_new (GIMP_TYPE_TOOL_EDITOR,
+                                 "view-size",         view_size,
+                                 "view-border-width", view_border_width,
+                                 NULL);
+
+  gimp_container_view_set_context     (container_view, context);
+  gimp_container_view_set_container   (container_view, container);
+  gimp_container_view_set_reorderable (container_view, TRUE);
+
+  return GTK_WIDGET (container_view);
+}
+
+/**
+ * gimp_tool_editor_revert_changes:
+ * @tool_editor:
+ *
+ * Reverts the tool order and visibility to the state at creation.
+ **/
+void
+gimp_tool_editor_revert_changes (GimpToolEditor *tool_editor)
+{
+  GScanner *scanner;
+
+  g_return_if_fail (GIMP_IS_TOOL_EDITOR (tool_editor));
+
+  scanner = gimp_scanner_new_string (tool_editor->priv->initial_tool_state, -1,
+                                     NULL);
+
+  gimp_tools_deserialize (tool_editor->priv->context->gimp,
+                          tool_editor->priv->container,
+                          scanner);
+
+  gimp_scanner_unref (scanner);
 }
diff --git a/app/widgets/gimptooleditor.h b/app/widgets/gimptooleditor.h
index 33e7f570fa..ac34b92c12 100644
--- a/app/widgets/gimptooleditor.h
+++ b/app/widgets/gimptooleditor.h
@@ -34,16 +34,19 @@
 #define GIMP_TOOL_EDITOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TOOL_EDITOR, 
GimpToolEditorClass))
 
 
-typedef struct _GimpToolEditorClass  GimpToolEditorClass;
+typedef struct _GimpToolEditorPrivate GimpToolEditorPrivate;
+typedef struct _GimpToolEditorClass   GimpToolEditorClass;
 
 struct _GimpToolEditor
 {
-  GimpContainerTreeView parent_instance;
+  GimpContainerTreeView  parent_instance;
+
+  GimpToolEditorPrivate *priv;
 };
 
 struct _GimpToolEditorClass
 {
-  GimpContainerTreeViewClass parent_class;
+  GimpContainerTreeViewClass  parent_class;
 };
 
 
@@ -51,7 +54,6 @@ GType       gimp_tool_editor_get_type       (void) G_GNUC_CONST;
 
 GtkWidget * gimp_tool_editor_new            (GimpContainer  *container,
                                              GimpContext    *context,
-                                             GList          *default_tool_order,
                                              gint            view_size,
                                              gint            view_border_width);
 
diff --git a/app/widgets/widgets-enums.h b/app/widgets/widgets-enums.h
index 3951738aa8..625463abc4 100644
--- a/app/widgets/widgets-enums.h
+++ b/app/widgets/widgets-enums.h
@@ -164,7 +164,7 @@ typedef enum  /*< skip >*/
   GIMP_DND_TYPE_BUFFER       = 20,
   GIMP_DND_TYPE_IMAGEFILE    = 21,
   GIMP_DND_TYPE_TEMPLATE     = 22,
-  GIMP_DND_TYPE_TOOL_INFO    = 23,
+  GIMP_DND_TYPE_TOOL_ITEM    = 23,
   GIMP_DND_TYPE_NOTEBOOK_TAB = 24,
 
   GIMP_DND_TYPE_LAST         = GIMP_DND_TYPE_NOTEBOOK_TAB


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