[gimp] app: implement multi-paths selection.



commit b9eb289b5cc30f10b4006098f77929c0705e9205
Author: Jehan <jehan girinstud io>
Date:   Sun Jun 20 02:07:44 2021 +0200

    app: implement multi-paths selection.
    
    For now, highlighting, snapping and moving (position change with move
    tool) have been implemented.

 app/core/gimpimage-snap.c               | 380 +++++++++++++++++---------------
 app/dialogs/dialogs-constructors.c      |   2 +-
 app/display/gimpdisplayshell-handlers.c |   7 +-
 app/display/gimpdisplayshell.c          |   2 +-
 app/tools/gimpmovetool.c                |  32 ++-
 5 files changed, 230 insertions(+), 193 deletions(-)
---
diff --git a/app/core/gimpimage-snap.c b/app/core/gimpimage-snap.c
index 038ef6dbae..08151b0523 100644
--- a/app/core/gimpimage-snap.c
+++ b/app/core/gimpimage-snap.c
@@ -235,9 +235,12 @@ gimp_image_snap_point (GimpImage *image,
   *tx = x;
   *ty = y;
 
-  if (! gimp_image_get_guides (image))         snap_to_guides  = FALSE;
-  if (! gimp_image_get_grid (image))           snap_to_grid    = FALSE;
-  if (! gimp_image_get_active_vectors (image)) snap_to_vectors = FALSE;
+  if (! gimp_image_get_guides (image))
+    snap_to_guides  = FALSE;
+  if (! gimp_image_get_grid (image))
+    snap_to_grid    = FALSE;
+  if (! gimp_image_get_selected_vectors (image))
+    snap_to_vectors = FALSE;
 
   if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors))
     return FALSE;
@@ -336,27 +339,33 @@ gimp_image_snap_point (GimpImage *image,
 
   if (snap_to_vectors)
     {
-      GimpVectors *vectors = gimp_image_get_active_vectors (image);
-      GimpStroke  *stroke  = NULL;
-      GimpCoords   coords  = { 0, 0, 0, 0, 0 };
+      GList      *selected_vectors = gimp_image_get_selected_vectors (image);
+      GList      *iter;
+      GimpStroke *stroke           = NULL;
+      GimpCoords  coords           = { 0, 0, 0, 0, 0 };
 
       coords.x = x;
       coords.y = y;
 
-      while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
+      for (iter = selected_vectors; iter; iter = iter->next)
         {
-          GimpCoords nearest;
+          GimpVectors *vectors = iter->data;
 
-          if (gimp_stroke_nearest_point_get (stroke, &coords, 1.0,
-                                             &nearest,
-                                             NULL, NULL, NULL) >= 0)
+          while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
             {
-              snapped |= gimp_image_snap_distance (x, nearest.x,
-                                                   epsilon_x,
-                                                   &mindist_x, tx);
-              snapped |= gimp_image_snap_distance (y, nearest.y,
-                                                   epsilon_y,
-                                                   &mindist_y, ty);
+              GimpCoords nearest;
+
+              if (gimp_stroke_nearest_point_get (stroke, &coords, 1.0,
+                                                 &nearest,
+                                                 NULL, NULL, NULL) >= 0)
+                {
+                  snapped |= gimp_image_snap_distance (x, nearest.x,
+                                                       epsilon_x,
+                                                       &mindist_x, tx);
+                  snapped |= gimp_image_snap_distance (y, nearest.y,
+                                                       epsilon_y,
+                                                       &mindist_y, ty);
+                }
             }
         }
     }
@@ -393,9 +402,12 @@ gimp_image_snap_rectangle (GimpImage *image,
   *tx1 = x1;
   *ty1 = y1;
 
-  if (! gimp_image_get_guides (image))         snap_to_guides  = FALSE;
-  if (! gimp_image_get_grid (image))           snap_to_grid    = FALSE;
-  if (! gimp_image_get_active_vectors (image)) snap_to_vectors = FALSE;
+  if (! gimp_image_get_guides (image))
+    snap_to_guides  = FALSE;
+  if (! gimp_image_get_grid (image))
+    snap_to_grid    = FALSE;
+  if (! gimp_image_get_selected_vectors (image))
+    snap_to_vectors = FALSE;
 
   if (! (snap_to_guides || snap_to_grid || snap_to_canvas || snap_to_vectors))
     return FALSE;
@@ -474,208 +486,214 @@ gimp_image_snap_rectangle (GimpImage *image,
 
   if (snap_to_vectors)
     {
-      GimpVectors *vectors = gimp_image_get_active_vectors (image);
-      GimpStroke  *stroke  = NULL;
-      GimpCoords   coords1 = GIMP_COORDS_DEFAULT_VALUES;
-      GimpCoords   coords2 = GIMP_COORDS_DEFAULT_VALUES;
+      GList      *selected_vectors = gimp_image_get_selected_vectors (image);
+      GList      *iter;
+      GimpStroke *stroke           = NULL;
+      GimpCoords  coords1          = GIMP_COORDS_DEFAULT_VALUES;
+      GimpCoords  coords2          = GIMP_COORDS_DEFAULT_VALUES;
 
-      while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
+      for (iter = selected_vectors; iter; iter = iter->next)
         {
-          GimpCoords nearest;
-          gdouble    dist;
+          GimpVectors *vectors = iter->data;
 
-          /*  top edge  */
-
-          coords1.x = x1;
-          coords1.y = y1;
-          coords2.x = x2;
-          coords2.y = y1;
-
-          if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
-                                               1.0, &nearest,
-                                               NULL, NULL, NULL) >= 0)
+          while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
             {
-              snapped |= gimp_image_snap_distance (y1, nearest.y,
-                                                   epsilon_y,
-                                                   &mindist_y, ty1);
-            }
+              GimpCoords nearest;
+              gdouble    dist;
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              snapped |= gimp_image_snap_distance (x1, nearest.x,
-                                                   epsilon_x,
-                                                   &mindist_x, tx1);
-            }
+              /*  top edge  */
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              dist = ABS (nearest.x - x2);
+              coords1.x = x1;
+              coords1.y = y1;
+              coords2.x = x2;
+              coords2.y = y1;
 
-              if (dist < MIN (epsilon_x, mindist_x))
+              if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
+                                                   1.0, &nearest,
+                                                   NULL, NULL, NULL) >= 0)
                 {
-                  mindist_x = dist;
-                  *tx1 = RINT (x1 + (nearest.x - x2));
-                  snapped = TRUE;
+                  snapped |= gimp_image_snap_distance (y1, nearest.y,
+                                                       epsilon_y,
+                                                       &mindist_y, ty1);
                 }
-            }
-
-          /*  bottom edge  */
-
-          coords1.x = x1;
-          coords1.y = y2;
-          coords2.x = x2;
-          coords2.y = y2;
 
-          if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
-                                               1.0, &nearest,
-                                               NULL, NULL, NULL) >= 0)
-            {
-              dist = ABS (nearest.y - y2);
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
+                {
+                  snapped |= gimp_image_snap_distance (x1, nearest.x,
+                                                       epsilon_x,
+                                                       &mindist_x, tx1);
+                }
 
-              if (dist < MIN (epsilon_y, mindist_y))
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
                 {
-                  mindist_y = dist;
-                  *ty1 = RINT (y1 + (nearest.y - y2));
-                  snapped = TRUE;
+                  dist = ABS (nearest.x - x2);
+
+                  if (dist < MIN (epsilon_x, mindist_x))
+                    {
+                      mindist_x = dist;
+                      *tx1 = RINT (x1 + (nearest.x - x2));
+                      snapped = TRUE;
+                    }
                 }
-            }
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              snapped |= gimp_image_snap_distance (x1, nearest.x,
-                                                   epsilon_x,
-                                                   &mindist_x, tx1);
-            }
+              /*  bottom edge  */
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              dist = ABS (nearest.x - x2);
+              coords1.x = x1;
+              coords1.y = y2;
+              coords2.x = x2;
+              coords2.y = y2;
 
-              if (dist < MIN (epsilon_x, mindist_x))
+              if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
+                                                   1.0, &nearest,
+                                                   NULL, NULL, NULL) >= 0)
                 {
-                  mindist_x = dist;
-                  *tx1 = RINT (x1 + (nearest.x - x2));
-                  snapped = TRUE;
+                  dist = ABS (nearest.y - y2);
+
+                  if (dist < MIN (epsilon_y, mindist_y))
+                    {
+                      mindist_y = dist;
+                      *ty1 = RINT (y1 + (nearest.y - y2));
+                      snapped = TRUE;
+                    }
                 }
-            }
 
-          /*  left edge  */
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
+                {
+                  snapped |= gimp_image_snap_distance (x1, nearest.x,
+                                                       epsilon_x,
+                                                       &mindist_x, tx1);
+                }
 
-          coords1.x = x1;
-          coords1.y = y1;
-          coords2.x = x1;
-          coords2.y = y2;
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
+                {
+                  dist = ABS (nearest.x - x2);
+
+                  if (dist < MIN (epsilon_x, mindist_x))
+                    {
+                      mindist_x = dist;
+                      *tx1 = RINT (x1 + (nearest.x - x2));
+                      snapped = TRUE;
+                    }
+                }
 
-          if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
-                                               1.0, &nearest,
-                                               NULL, NULL, NULL) >= 0)
-            {
-              snapped |= gimp_image_snap_distance (x1, nearest.x,
-                                                   epsilon_x,
-                                                   &mindist_x, tx1);
-            }
+              /*  left edge  */
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              snapped |= gimp_image_snap_distance (y1, nearest.y,
-                                                   epsilon_y,
-                                                   &mindist_y, ty1);
-            }
+              coords1.x = x1;
+              coords1.y = y1;
+              coords2.x = x1;
+              coords2.y = y2;
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              dist = ABS (nearest.y - y2);
+              if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
+                                                   1.0, &nearest,
+                                                   NULL, NULL, NULL) >= 0)
+                {
+                  snapped |= gimp_image_snap_distance (x1, nearest.x,
+                                                       epsilon_x,
+                                                       &mindist_x, tx1);
+                }
 
-              if (dist < MIN (epsilon_y, mindist_y))
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
                 {
-                  mindist_y = dist;
-                  *ty1 = RINT (y1 + (nearest.y - y2));
-                  snapped = TRUE;
+                  snapped |= gimp_image_snap_distance (y1, nearest.y,
+                                                       epsilon_y,
+                                                       &mindist_y, ty1);
                 }
-            }
 
-          /*  right edge  */
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
+                {
+                  dist = ABS (nearest.y - y2);
+
+                  if (dist < MIN (epsilon_y, mindist_y))
+                    {
+                      mindist_y = dist;
+                      *ty1 = RINT (y1 + (nearest.y - y2));
+                      snapped = TRUE;
+                    }
+                }
 
-          coords1.x = x2;
-          coords1.y = y1;
-          coords2.x = x2;
-          coords2.y = y2;
+              /*  right edge  */
 
-          if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
-                                               1.0, &nearest,
-                                               NULL, NULL, NULL) >= 0)
-            {
-              dist = ABS (nearest.x - x2);
+              coords1.x = x2;
+              coords1.y = y1;
+              coords2.x = x2;
+              coords2.y = y2;
 
-              if (dist < MIN (epsilon_x, mindist_x))
+              if (gimp_stroke_nearest_tangent_get (stroke, &coords1, &coords2,
+                                                   1.0, &nearest,
+                                                   NULL, NULL, NULL) >= 0)
                 {
-                  mindist_x = dist;
-                  *tx1 = RINT (x1 + (nearest.x - x2));
-                  snapped = TRUE;
+                  dist = ABS (nearest.x - x2);
+
+                  if (dist < MIN (epsilon_x, mindist_x))
+                    {
+                      mindist_x = dist;
+                      *tx1 = RINT (x1 + (nearest.x - x2));
+                      snapped = TRUE;
+                    }
                 }
-            }
-
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              snapped |= gimp_image_snap_distance (y1, nearest.y,
-                                                   epsilon_y,
-                                                   &mindist_y, ty1);
-            }
 
-          if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
-                                                    1.0, &nearest,
-                                                    NULL, NULL, NULL) >= 0)
-            {
-              dist = ABS (nearest.y - y2);
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords1, &coords2,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
+                {
+                  snapped |= gimp_image_snap_distance (y1, nearest.y,
+                                                       epsilon_y,
+                                                       &mindist_y, ty1);
+                }
 
-              if (dist < MIN (epsilon_y, mindist_y))
+              if (gimp_stroke_nearest_intersection_get (stroke, &coords2, &coords1,
+                                                        1.0, &nearest,
+                                                        NULL, NULL, NULL) >= 0)
                 {
-                  mindist_y = dist;
-                  *ty1 = RINT (y1 + (nearest.y - y2));
-                  snapped = TRUE;
+                  dist = ABS (nearest.y - y2);
+
+                  if (dist < MIN (epsilon_y, mindist_y))
+                    {
+                      mindist_y = dist;
+                      *ty1 = RINT (y1 + (nearest.y - y2));
+                      snapped = TRUE;
+                    }
                 }
-            }
 
-          /*  center  */
+              /*  center  */
 
-          coords1.x = x_center;
-          coords1.y = y_center;
+              coords1.x = x_center;
+              coords1.y = y_center;
 
-          if (gimp_stroke_nearest_point_get (stroke, &coords1, 1.0,
-                                             &nearest,
-                                             NULL, NULL, NULL) >= 0)
-            {
-              if (gimp_image_snap_distance (x_center, nearest.x,
-                                            epsilon_x,
-                                            &mindist_x, &nx))
+              if (gimp_stroke_nearest_point_get (stroke, &coords1, 1.0,
+                                                 &nearest,
+                                                 NULL, NULL, NULL) >= 0)
                 {
-                  mindist_x = ABS (nx - x_center);
-                  *tx1 = RINT (x1 + (nx - x_center));
-                  snapped = TRUE;
+                  if (gimp_image_snap_distance (x_center, nearest.x,
+                                                epsilon_x,
+                                                &mindist_x, &nx))
+                    {
+                      mindist_x = ABS (nx - x_center);
+                      *tx1 = RINT (x1 + (nx - x_center));
+                      snapped = TRUE;
+                    }
+
+                  if (gimp_image_snap_distance (y_center, nearest.y,
+                                                epsilon_y,
+                                                &mindist_y, &ny))
+                    {
+                      mindist_y = ABS (ny - y_center);
+                      *ty1 = RINT (y1 + (ny - y_center));
+                      snapped = TRUE;
+                    }
                 }
-
-              if (gimp_image_snap_distance (y_center, nearest.y,
-                                            epsilon_y,
-                                            &mindist_y, &ny))
-                {
-                  mindist_y = ABS (ny - y_center);
-                  *ty1 = RINT (y1 + (ny - y_center));
-                  snapped = TRUE;
-               }
             }
         }
     }
diff --git a/app/dialogs/dialogs-constructors.c b/app/dialogs/dialogs-constructors.c
index ff885950da..36a8065179 100644
--- a/app/dialogs/dialogs-constructors.c
+++ b/app/dialogs/dialogs-constructors.c
@@ -762,7 +762,7 @@ dialogs_vectors_list_view_new (GimpDialogFactory *factory,
     view_size = context->gimp->config->layer_preview_size;
 
   return gimp_item_tree_view_new (GIMP_TYPE_VECTORS_TREE_VIEW,
-                                  view_size, 1, FALSE,
+                                  view_size, 1, TRUE,
                                   gimp_context_get_image (context),
                                   gimp_dialog_factory_get_menu_factory (factory),
                                   "<Vectors>",
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index 70ca41d860..1932839907 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -945,8 +945,8 @@ static void
 gimp_display_shell_active_vectors_handler (GimpImage        *image,
                                            GimpDisplayShell *shell)
 {
-  GimpCanvasProxyGroup *group  = GIMP_CANVAS_PROXY_GROUP (shell->vectors);
-  GimpVectors          *active = gimp_image_get_active_vectors (image);
+  GimpCanvasProxyGroup *group    = GIMP_CANVAS_PROXY_GROUP (shell->vectors);
+  GList                *selected = gimp_image_get_selected_vectors (image);
   GList                *list;
 
   for (list = gimp_image_get_vectors_iter (image);
@@ -958,7 +958,8 @@ gimp_display_shell_active_vectors_handler (GimpImage        *image,
 
       item = gimp_canvas_proxy_group_get_item (group, vectors);
 
-      gimp_canvas_item_set_highlight (item, vectors == active);
+      gimp_canvas_item_set_highlight (item,
+                                      g_list_find (selected, vectors) != NULL);
     }
 }
 
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 87f6be027e..a87b940290 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -1611,7 +1611,7 @@ gimp_display_shell_snap_coords (GimpDisplayShell *shell,
   snap_to_canvas = gimp_display_shell_get_snap_to_canvas (shell);
 
   if (gimp_display_shell_get_snap_to_vectors (shell) &&
-      gimp_image_get_active_vectors (image))
+      gimp_image_get_selected_vectors (image))
     {
       snap_to_vectors = TRUE;
     }
diff --git a/app/tools/gimpmovetool.c b/app/tools/gimpmovetool.c
index 264cbfafc7..68ff5058d7 100644
--- a/app/tools/gimpmovetool.c
+++ b/app/tools/gimpmovetool.c
@@ -282,17 +282,27 @@ gimp_move_tool_button_press (GimpTool            *tool,
     {
     case GIMP_TRANSFORM_TYPE_PATH:
       {
-        active_item = GIMP_ITEM (gimp_image_get_active_vectors (image));
+        selected_items = gimp_image_get_selected_vectors (image);
+        selected_items = g_list_copy (selected_items);
 
         translate_mode = GIMP_TRANSLATE_MODE_VECTORS;
 
-        if (! active_item)
+        if (! selected_items)
           {
-            null_message = _("There is no path to move.");
+            null_message = _("There are no paths to move.");
           }
-        else if (gimp_item_is_position_locked (active_item))
+        else
           {
-            locked_message = _("The active path's position is locked.");
+            gint n_items = 0;
+
+            for (iter = selected_items; iter; iter = iter->next)
+              {
+                if (! gimp_item_is_position_locked (iter->data))
+                  n_items++;
+              }
+
+            if (n_items == 0)
+              locked_message = _("All selected path's position are locked.");
           }
       }
       break;
@@ -587,9 +597,17 @@ gimp_move_tool_cursor_update (GimpTool         *tool,
 
       if (options->move_current)
         {
-          GimpItem *item = GIMP_ITEM (gimp_image_get_active_vectors (image));
+          GList *selected = gimp_image_get_selected_vectors (image);
+          GList *iter;
+          gint   n_items = 0;
+
+          for (iter = selected; iter; iter = iter->next)
+            {
+              if (! gimp_item_is_position_locked (iter->data))
+                n_items++;
+            }
 
-          if (! item || gimp_item_is_position_locked (item))
+          if (n_items == 0)
             modifier = GIMP_CURSOR_MODIFIER_BAD;
         }
       else


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