[gimp] app: create and use gimp_image_item_list_linked().



commit b05fc6950dfd25207925037fff5380c0db340381
Author: Jehan <jehan girinstud io>
Date:   Tue May 26 13:08:14 2020 +0200

    app: create and use gimp_image_item_list_linked().
    
    This function returns a new list of items from an input list. The output
    list will optionally contains linked items if any of the input item is
    linked so we don't have to rewrite the same duplicated code for every
    feature where item links matter.
    
    Moreover it also filters descendants if any of the input items is an
    item group, hence avoiding to apply a transformation twice to a
    descendant item.
    
    Use this new function already in 2 places, hence skimming quite a bit of
    redundant code.

 app/core/gimpimage-item-list.c    |  66 +++++++++++++++++++
 app/core/gimpimage-item-list.h    |   3 +
 app/tools/gimpeditselectiontool.c | 131 +++++---------------------------------
 3 files changed, 84 insertions(+), 116 deletions(-)
---
diff --git a/app/core/gimpimage-item-list.c b/app/core/gimpimage-item-list.c
index 4efd8a1e73..8d512c477a 100644
--- a/app/core/gimpimage-item-list.c
+++ b/app/core/gimpimage-item-list.c
@@ -24,14 +24,18 @@
 
 #include "core-types.h"
 
+#include "gimpchannel.h"
 #include "gimpcontext.h"
 #include "gimpimage.h"
 #include "gimpimage-item-list.h"
 #include "gimpimage-undo.h"
 #include "gimpitem.h"
+#include "gimplayer.h"
 #include "gimpobjectqueue.h"
 #include "gimpprogress.h"
 
+#include "vectors/gimpvectors.h"
+
 #include "gimp-intl.h"
 
 
@@ -355,6 +359,68 @@ gimp_image_item_list_get_list (GimpImage        *image,
   return g_list_reverse (return_list);
 }
 
+/**
+ * gimp_image_item_list_linked:
+ * @image:
+ * @items: the original list of items. This list is untouched.
+ *
+ * Returns: a newly allocated list of items, containing @items and their
+ * linked items if relevant. Note that the returned list is also
+ * filtered by removing redundant children, so the result may sometimes
+ * be smaller than the original list.
+ * The order of the list is not meaningful and not guaranteed to stay
+ * the same even if the contents is not changed.
+ */
+GList *
+gimp_image_item_list_linked (GimpImage *image,
+                             GList     *items)
+{
+  GList            *new_items = NULL;
+  GList            *iter;
+  GimpItemTypeMask  type   = 0;
+  gboolean          linked = FALSE;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (g_list_length (items) > 0, NULL);
+
+  for (iter = items; iter; iter = iter->next)
+    {
+      GimpItem *item;
+
+      g_return_val_if_fail (GIMP_IS_ITEM (iter->data), NULL);
+      g_return_val_if_fail (image == gimp_item_get_image (iter->data), NULL);
+
+      item = iter->data;
+
+      if (gimp_item_get_linked (item))
+        linked = TRUE;
+
+      if (GIMP_IS_LAYER (item))
+        type |= GIMP_ITEM_TYPE_LAYERS;
+      else if (GIMP_IS_VECTORS (item))
+        type |= GIMP_ITEM_TYPE_VECTORS;
+      else if (GIMP_IS_CHANNEL (item))
+        type |= GIMP_ITEM_TYPE_CHANNELS;
+    }
+
+  if (linked)
+    {
+      new_items = gimp_image_item_list_get_list (image, type, GIMP_ITEM_SET_LINKED);
+
+      for (iter = items; iter; iter = iter->next)
+        if (! g_list_find (new_items, iter->data))
+          new_items = g_list_prepend (new_items, iter->data);
+    }
+  else
+    {
+      new_items = g_list_copy (items);
+    }
+
+  new_items = gimp_image_item_list_filter (new_items);
+
+  return new_items;
+}
+
 static GList *
 gimp_image_item_list_remove_children (GList          *list,
                                       const GimpItem *parent)
diff --git a/app/core/gimpimage-item-list.h b/app/core/gimpimage-item-list.h
index cd69637588..b67046be16 100644
--- a/app/core/gimpimage-item-list.h
+++ b/app/core/gimpimage-item-list.h
@@ -57,6 +57,9 @@ GList    * gimp_image_item_list_get_list  (GimpImage              *image,
                                            GimpItemTypeMask        type,
                                            GimpItemSet             set);
 
+GList    * gimp_image_item_list_linked    (GimpImage              *image,
+                                           GList                  *items);
+
 GList    * gimp_image_item_list_filter    (GList                  *list);
 
 
diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c
index abda63c6ae..ce05c9cd2b 100644
--- a/app/tools/gimpeditselectiontool.c
+++ b/app/tools/gimpeditselectiontool.c
@@ -212,7 +212,6 @@ gimp_edit_selection_tool_start (GimpTool          *parent_tool,
   GList                 *selected_items;
   GList                 *iter;
   GList                 *list;
-  gboolean               have_linked = FALSE;
   gint                   off_x       = G_MAXINT;
   gint                   off_y       = G_MAXINT;
 
@@ -261,9 +260,6 @@ gimp_edit_selection_tool_start (GimpTool          *parent_tool,
       gimp_item_get_offset (iter->data, &item_off_x, &item_off_y);
       off_x = MIN (off_x, item_off_x);
       off_y = MIN (off_y, item_off_y);
-
-      if (gimp_item_get_linked (iter->data))
-        have_linked = TRUE;
     }
 
   /* Manually set the last coords to the starting point */
@@ -333,13 +329,16 @@ gimp_edit_selection_tool_start (GimpTool          *parent_tool,
       case GIMP_TRANSLATE_MODE_CHANNEL:
       case GIMP_TRANSLATE_MODE_MASK:
       case GIMP_TRANSLATE_MODE_LAYER_MASK:
-        gimp_item_bounds (selected_items->data, &x, &y, &w, &h);
+        edit_select->delayed_items = gimp_image_item_list_linked (image, selected_items);
+        gimp_image_item_list_bounds (image, edit_select->delayed_items, &x, &y, &w, &h);
         x += off_x;
         y += off_y;
+
         break;
 
       case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
       case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
+        /* MASK_TO_LAYER and MASK_COPY_TO_LAYER create a live_item later */
         x = edit_select->sel_x + off_x;
         y = edit_select->sel_y + off_y;
         w = edit_select->sel_width;
@@ -349,30 +348,9 @@ gimp_edit_selection_tool_start (GimpTool          *parent_tool,
       case GIMP_TRANSLATE_MODE_LAYER:
       case GIMP_TRANSLATE_MODE_FLOATING_SEL:
       case GIMP_TRANSLATE_MODE_VECTORS:
-        if (have_linked)
-          {
-            GList *linked;
-
-            linked = gimp_image_item_list_get_list (image,
-                                                    GIMP_IS_LAYER (selected_items->data) ?
-                                                    GIMP_ITEM_TYPE_LAYERS :
-                                                    GIMP_ITEM_TYPE_VECTORS,
-                                                    GIMP_ITEM_SET_LINKED);
-            linked = gimp_image_item_list_filter (linked);
-
-            for (iter = selected_items; iter; iter = iter->next)
-              if (! g_list_find (linked, iter->data))
-                linked = g_list_prepend (linked, iter->data);
-
-            gimp_image_item_list_bounds (image, linked, &x, &y, &w, &h);
-
-            g_list_free (linked);
-          }
-        else
-          {
-            gimp_image_item_list_bounds (image, selected_items, &x, &y, &w, &h);
-          }
-       break;
+        edit_select->live_items = gimp_image_item_list_linked (image, selected_items);
+        gimp_image_item_list_bounds (image, edit_select->live_items, &x, &y, &w, &h);
+        break;
       }
 
     gimp_tool_control_set_snap_offsets (tool->control,
@@ -385,61 +363,6 @@ gimp_edit_selection_tool_start (GimpTool          *parent_tool,
     edit_select->center_y = y + h / 2.0;
   }
 
-  if (have_linked)
-    {
-      switch (edit_select->edit_mode)
-        {
-        case GIMP_TRANSLATE_MODE_CHANNEL:
-        case GIMP_TRANSLATE_MODE_LAYER:
-        case GIMP_TRANSLATE_MODE_VECTORS:
-          edit_select->live_items =
-            gimp_image_item_list_get_list (image,
-                                           GIMP_ITEM_TYPE_LAYERS |
-                                           GIMP_ITEM_TYPE_VECTORS,
-                                           GIMP_ITEM_SET_LINKED);
-
-          for (iter = selected_items; iter; iter = iter->next)
-            if (! g_list_find (edit_select->live_items, iter->data))
-              edit_select->live_items = g_list_prepend (edit_select->live_items, iter->data);
-
-          edit_select->live_items =
-            gimp_image_item_list_filter (edit_select->live_items);
-
-          edit_select->delayed_items =
-            gimp_image_item_list_get_list (image,
-                                           GIMP_ITEM_TYPE_CHANNELS,
-                                           GIMP_ITEM_SET_LINKED);
-          edit_select->delayed_items =
-            gimp_image_item_list_filter (edit_select->delayed_items);
-          break;
-
-        default:
-          /* other stuff can't be linked so don't bother */
-          break;
-        }
-    }
-  else
-    {
-      switch (edit_select->edit_mode)
-        {
-        case GIMP_TRANSLATE_MODE_VECTORS:
-        case GIMP_TRANSLATE_MODE_LAYER:
-        case GIMP_TRANSLATE_MODE_FLOATING_SEL:
-          edit_select->live_items = g_list_copy (selected_items);
-          break;
-
-        case GIMP_TRANSLATE_MODE_CHANNEL:
-        case GIMP_TRANSLATE_MODE_LAYER_MASK:
-        case GIMP_TRANSLATE_MODE_MASK:
-          edit_select->delayed_items = g_list_copy (selected_items);
-          break;
-
-        default:
-          /* MASK_TO_LAYER and MASK_COPY_TO_LAYER create a live_item later */
-          break;
-        }
-    }
-
   for (list = edit_select->live_items; list; list = g_list_next (list))
     {
       GimpItem *item = list->data;
@@ -709,7 +632,6 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
   GimpImage             *image       = gimp_display_get_image (display);
   GList                 *selected_items;
   GList                 *iter;
-  gboolean               have_linked = FALSE;
   gint                   off_x       = G_MAXINT;
   gint                   off_y       = G_MAXINT;
 
@@ -723,9 +645,6 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
       gimp_item_get_offset (iter->data, &item_off_x, &item_off_y);
       off_x = MIN (off_x, item_off_x);
       off_y = MIN (off_y, item_off_y);
-
-      if (gimp_item_get_linked (iter->data))
-        have_linked = TRUE;
     }
 
   switch (edit_select->edit_mode)
@@ -787,36 +706,16 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
 
     case GIMP_TRANSLATE_MODE_LAYER:
     case GIMP_TRANSLATE_MODE_VECTORS:
-      {
-        gint x, y, w, h;
-
-        if (have_linked)
-          {
-            GList *linked;
-
-            linked = gimp_image_item_list_get_list (image,
-                                                    GIMP_IS_LAYER (selected_items->data) ?
-                                                    GIMP_ITEM_TYPE_LAYERS :
-                                                    GIMP_ITEM_TYPE_VECTORS,
-                                                    GIMP_ITEM_SET_LINKED);
-            linked = gimp_image_item_list_filter (linked);
-
-            for (iter = selected_items; iter; iter = iter->next)
-              if (! g_list_find (linked, iter->data))
-                linked = g_list_prepend (linked, iter->data);
-
-            gimp_image_item_list_bounds (image, linked, &x, &y, &w, &h);
+        {
+          GList *translate_items;
+          gint   x, y, w, h;
 
-            g_list_free (linked);
-          }
-        else
-          {
-            gimp_image_item_list_bounds (image, selected_items, &x, &y, &w, &h);
-          }
+          translate_items = gimp_image_item_list_linked (image, selected_items);
+          gimp_image_item_list_bounds (image, translate_items, &x, &y, &w, &h);
+          g_list_free (translate_items);
 
-        gimp_draw_tool_add_rectangle (draw_tool, FALSE,
-                                      x, y, w, h);
-      }
+          gimp_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h);
+        }
       break;
 
     case GIMP_TRANSLATE_MODE_FLOATING_SEL:


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