[gimp] app: allowing to "Lock position" on layer groups.



commit ed5934440603e4c46777208dea847b84c2f25c1f
Author: Jehan <jehan girinstud io>
Date:   Tue Feb 15 18:30:53 2022 +0100

    app: allowing to "Lock position" on layer groups.
    
    Since we are now allowed to move groups (which is the same thing as
    multi-selecting all its children and moving them), it makes no sense
    that this lock is disabled.
    
    This works the same way as "Lock pixels" in that a locked grouped also
    forbid moving children. And there was already some logics so that you
    can't move a layer group if one of it's children is locked. So this lock
    really works both ways and is a bit special.
    
    Finally I cleaned up a bit the multi-layer selection logics and
    messaging, as well as which lock to blink (similar to the previous
    commit) for the "Lock position" case.

 app/actions/drawable-actions.c    |  2 +-
 app/actions/layers-actions.c      |  2 +-
 app/core/gimpgrouplayer.c         | 51 ++++++++++++++++++++++++++++++---------
 app/core/gimpitem.c               | 43 ++++++++++++++++++++++++---------
 app/core/gimpitem.h               |  7 ++++--
 app/core/gimplayermask.c          | 10 +++++---
 app/display/gimptoolpath.c        |  4 +--
 app/pdb/gimppdb-utils.c           |  2 +-
 app/tools/gimpeditselectiontool.c | 22 ++++++++++-------
 app/tools/gimpmovetool.c          | 40 +++++++++++++-----------------
 app/tools/gimptransformtool.c     | 10 ++++----
 11 files changed, 122 insertions(+), 71 deletions(-)
---
diff --git a/app/actions/drawable-actions.c b/app/actions/drawable-actions.c
index a549fa2df2..8f1adbd097 100644
--- a/app/actions/drawable-actions.c
+++ b/app/actions/drawable-actions.c
@@ -197,7 +197,7 @@ drawable_actions_update (GimpActionGroup *group,
           writable      = ! gimp_item_is_content_locked (item, NULL);
           locked_pos    = gimp_item_get_lock_position (item);
           can_lock_pos  = gimp_item_can_lock_position (item);
-          movable       = ! gimp_item_is_position_locked (item);
+          movable       = ! gimp_item_is_position_locked (item, NULL);
 
           if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
             children = TRUE;
diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index b6f0fe6394..1a70a1a3b8 100644
--- a/app/actions/layers-actions.c
+++ b/app/actions/layers-actions.c
@@ -841,7 +841,7 @@ layers_actions_update (GimpActionGroup *group,
           else
             all_writable  = FALSE;
 
-          if (gimp_item_is_position_locked (GIMP_ITEM (iter->data)))
+          if (gimp_item_is_position_locked (GIMP_ITEM (iter->data), NULL))
             all_movable = FALSE;
 
           if (gimp_layer_can_lock_alpha (iter->data))
diff --git a/app/core/gimpgrouplayer.c b/app/core/gimpgrouplayer.c
index 202c46388c..9b2e447389 100644
--- a/app/core/gimpgrouplayer.c
+++ b/app/core/gimpgrouplayer.c
@@ -102,7 +102,9 @@ static gboolean        gimp_group_layer_get_expanded (GimpViewable    *viewable)
 static void            gimp_group_layer_set_expanded (GimpViewable    *viewable,
                                                       gboolean         expanded);
 
-static gboolean  gimp_group_layer_is_position_locked (GimpItem        *item);
+static gboolean  gimp_group_layer_is_position_locked (GimpItem        *item,
+                                                      GimpItem       **locked_item,
+                                                      gboolean         check_children);
 static GimpItem      * gimp_group_layer_duplicate    (GimpItem        *item,
                                                       GType            new_type);
 static void            gimp_group_layer_convert      (GimpItem        *item,
@@ -517,22 +519,47 @@ gimp_group_layer_set_expanded (GimpViewable *viewable,
 }
 
 static gboolean
-gimp_group_layer_is_position_locked (GimpItem *item)
+gimp_group_layer_is_position_locked (GimpItem  *item,
+                                     GimpItem **locked_item,
+                                     gboolean   check_children)
 {
-  GimpGroupLayerPrivate *private = GET_PRIVATE (item);
-  GList                 *list;
-
-  for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children));
-       list;
-       list = g_list_next (list))
+  /* Lock position is particular because a locked child locks the group
+   * too.
+   */
+  if (check_children)
     {
-      GimpItem *child = list->data;
+      GimpGroupLayerPrivate *private = GET_PRIVATE (item);
+      GList                 *list;
 
-      if (gimp_item_is_position_locked (child))
-        return TRUE;
+      for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children));
+           list;
+           list = g_list_next (list))
+        {
+          GimpItem *child = list->data;
+
+          if (gimp_item_get_lock_position (child))
+            {
+              if (locked_item)
+                *locked_item = child;
+
+              return TRUE;
+            }
+          else if (GIMP_IS_GROUP_LAYER (child) &&
+                   gimp_group_layer_is_position_locked (child,
+                                                        locked_item,
+                                                        TRUE))
+            {
+              return TRUE;
+            }
+        }
     }
 
-  return GIMP_ITEM_CLASS (parent_class)->is_position_locked (item);
+  /* And a locked parent locks the group too! Which is handled by parent
+   * implementation of the method.
+   */
+  return GIMP_ITEM_CLASS (parent_class)->is_position_locked (item,
+                                                             locked_item,
+                                                             FALSE);
 }
 
 static GimpItem *
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index cf117f694a..6918d3cb54 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -127,7 +127,9 @@ static gint64     gimp_item_get_memsize             (GimpObject     *object,
 
 static gboolean   gimp_item_real_is_content_locked  (GimpItem       *item,
                                                      GimpItem      **locked_item);
-static gboolean   gimp_item_real_is_position_locked (GimpItem       *item);
+static gboolean   gimp_item_real_is_position_locked (GimpItem       *item,
+                                                     GimpItem      **locked_item,
+                                                     gboolean        check_children);
 static gboolean   gimp_item_real_is_visibility_locked (GimpItem       *item);
 static gboolean   gimp_item_real_bounds             (GimpItem       *item,
                                                      gdouble        *x,
@@ -477,18 +479,37 @@ gimp_item_real_is_content_locked (GimpItem  *item,
 {
   GimpItem *parent = gimp_item_get_parent (item);
 
-  if (parent && gimp_item_is_content_locked (parent, locked_item))
-    return TRUE;
-
-  if (GET_PRIVATE (item)->lock_content && locked_item)
-    *locked_item = item;
+  if (GET_PRIVATE (item)->lock_content)
+    {
+      if (locked_item)
+        *locked_item = item;
+    }
+  else if (parent && gimp_item_is_content_locked (parent, locked_item))
+    {
+      return TRUE;
+    }
 
   return GET_PRIVATE (item)->lock_content;
 }
 
 static gboolean
-gimp_item_real_is_position_locked (GimpItem *item)
+gimp_item_real_is_position_locked (GimpItem  *item,
+                                   GimpItem **locked_item,
+                                   gboolean   check_children)
 {
+  GimpItem *parent = gimp_item_get_parent (item);
+
+  if (GET_PRIVATE (item)->lock_position)
+    {
+      if (locked_item)
+        *locked_item = item;
+    }
+  else if (parent &&
+           GIMP_ITEM_GET_CLASS (item)->is_position_locked (parent, locked_item, FALSE))
+    {
+      return TRUE;
+    }
+
   return GET_PRIVATE (item)->lock_position;
 }
 
@@ -2514,18 +2535,16 @@ gimp_item_can_lock_position (GimpItem *item)
 {
   g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
 
-  if (gimp_viewable_get_children (GIMP_VIEWABLE (item)))
-    return FALSE;
-
   return TRUE;
 }
 
 gboolean
-gimp_item_is_position_locked (GimpItem *item)
+gimp_item_is_position_locked (GimpItem  *item,
+                              GimpItem **locked_item)
 {
   g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
 
-  return GIMP_ITEM_GET_CLASS (item)->is_position_locked (item);
+  return GIMP_ITEM_GET_CLASS (item)->is_position_locked (item, locked_item, TRUE);
 }
 
 void
diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h
index 0444023a55..ef66e14893 100644
--- a/app/core/gimpitem.h
+++ b/app/core/gimpitem.h
@@ -54,7 +54,9 @@ struct _GimpItemClass
   gboolean        (* is_attached)        (GimpItem               *item);
   gboolean        (* is_content_locked)  (GimpItem               *item,
                                           GimpItem              **locked_item);
-  gboolean        (* is_position_locked) (GimpItem               *item);
+  gboolean        (* is_position_locked) (GimpItem               *item,
+                                          GimpItem              **locked_item,
+                                          gboolean                checking_children);
   gboolean        (* is_visibility_locked) (GimpItem               *item);
   GimpItemTree  * (* get_tree)           (GimpItem               *item);
   gboolean        (* bounds)             (GimpItem               *item,
@@ -382,7 +384,8 @@ void            gimp_item_set_lock_position  (GimpItem          *item,
                                               gboolean           push_undo);
 gboolean        gimp_item_get_lock_position  (GimpItem          *item);
 gboolean        gimp_item_can_lock_position  (GimpItem          *item);
-gboolean        gimp_item_is_position_locked (GimpItem          *item);
+gboolean        gimp_item_is_position_locked (GimpItem          *item,
+                                              GimpItem         **locked_item);
 
 void            gimp_item_set_lock_visibility  (GimpItem        *item,
                                                 gboolean         lock_visibility,
diff --git a/app/core/gimplayermask.c b/app/core/gimplayermask.c
index 2660a29113..4d2879f3e1 100644
--- a/app/core/gimplayermask.c
+++ b/app/core/gimplayermask.c
@@ -38,7 +38,9 @@ static void            gimp_layer_mask_preview_thaw         (GimpViewable      *
 static gboolean        gimp_layer_mask_is_attached          (GimpItem          *item);
 static gboolean        gimp_layer_mask_is_content_locked    (GimpItem          *item,
                                                              GimpItem         **locked_item);
-static gboolean        gimp_layer_mask_is_position_locked   (GimpItem          *item);
+static gboolean        gimp_layer_mask_is_position_locked   (GimpItem          *item,
+                                                             GimpItem         **locked_item,
+                                                             gboolean           check_children);
 static GimpItemTree  * gimp_layer_mask_get_tree             (GimpItem          *item);
 static GimpItem      * gimp_layer_mask_duplicate            (GimpItem          *item,
                                                              GType              new_type);
@@ -145,13 +147,15 @@ gimp_layer_mask_is_content_locked (GimpItem  *item,
 }
 
 static gboolean
-gimp_layer_mask_is_position_locked (GimpItem *item)
+gimp_layer_mask_is_position_locked (GimpItem  *item,
+                                    GimpItem **locked_item,
+                                    gboolean   check_children)
 {
   GimpLayerMask *mask  = GIMP_LAYER_MASK (item);
   GimpLayer     *layer = gimp_layer_mask_get_layer (mask);
 
   if (layer)
-    return gimp_item_is_position_locked (GIMP_ITEM (layer));
+    return gimp_item_is_position_locked (GIMP_ITEM (layer), locked_item);
 
   return FALSE;
 }
diff --git a/app/display/gimptoolpath.c b/app/display/gimptoolpath.c
index ca8f06b735..cf2444aaf2 100644
--- a/app/display/gimptoolpath.c
+++ b/app/display/gimptoolpath.c
@@ -544,10 +544,10 @@ gimp_tool_path_check_writable (GimpToolPath *path)
   GimpItem            *locked_item = NULL;
 
   if (gimp_item_is_content_locked (GIMP_ITEM (private->vectors), &locked_item) ||
-      gimp_item_is_position_locked (GIMP_ITEM (private->vectors)))
+      gimp_item_is_position_locked (GIMP_ITEM (private->vectors), &locked_item))
     {
       gimp_tool_widget_message_literal (GIMP_TOOL_WIDGET (path),
-                                        _("The active path is locked."));
+                                        _("The selected path is locked."));
 
       if (locked_item == NULL)
         locked_item = GIMP_ITEM (private->vectors);
diff --git a/app/pdb/gimppdb-utils.c b/app/pdb/gimppdb-utils.c
index 49b9482b37..dbd4e42b48 100644
--- a/app/pdb/gimppdb-utils.c
+++ b/app/pdb/gimppdb-utils.c
@@ -594,7 +594,7 @@ gimp_pdb_item_is_modifiable (GimpItem           *item,
       return FALSE;
     }
 
-  if ((modify & GIMP_PDB_ITEM_POSITION) && gimp_item_is_position_locked (item))
+  if ((modify & GIMP_PDB_ITEM_POSITION) && gimp_item_is_position_locked (item, NULL))
     {
       g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT,
                    _("Item '%s' (%d) cannot be modified because its "
diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c
index e1c09caf79..c0cef46ff9 100644
--- a/app/tools/gimpeditselectiontool.c
+++ b/app/tools/gimpeditselectiontool.c
@@ -1062,7 +1062,8 @@ gimp_edit_selection_tool_translate (GimpTool          *tool,
           /* cannot happen, don't translate this message */
           null_message = "There is no selection to move.";
         }
-      else if (gimp_item_is_position_locked (active_item))
+      else if (gimp_item_is_position_locked (active_item,
+                                             &locked_item))
         {
           /* cannot happen, don't translate this message */
           locked_message = "The selection's position is locked.";
@@ -1079,9 +1080,10 @@ gimp_edit_selection_tool_translate (GimpTool          *tool,
         {
           null_message = _("There is no path to move.");
         }
-      else if (gimp_item_is_position_locked (active_item))
+      else if (gimp_item_is_position_locked (active_item,
+                                             &locked_item))
         {
-          locked_message = _("The active path's position is locked.");
+          locked_message = _("The selected path's position is locked.");
         }
       break;
 
@@ -1098,9 +1100,10 @@ gimp_edit_selection_tool_translate (GimpTool          *tool,
         {
           edit_mode = GIMP_TRANSLATE_MODE_LAYER_MASK;
 
-          if (gimp_item_is_position_locked (selected_items->data))
+          if (gimp_item_is_position_locked (selected_items->data,
+                                            &locked_item))
             {
-              locked_message = _("The active layer's position is locked.");
+              locked_message = _("The selected layer's position is locked.");
             }
           else if (gimp_item_is_content_locked (selected_items->data,
                                                 &locked_item))
@@ -1115,7 +1118,7 @@ gimp_edit_selection_tool_translate (GimpTool          *tool,
           edit_mode = GIMP_TRANSLATE_MODE_CHANNEL;
 
           for (iter = selected_items; iter; iter = iter->next)
-            if (! gimp_item_is_position_locked (iter->data) &&
+            if (! gimp_item_is_position_locked (iter->data, NULL) &&
                 ! gimp_item_is_content_locked (iter->data, NULL))
               n_items++;
 
@@ -1126,9 +1129,10 @@ gimp_edit_selection_tool_translate (GimpTool          *tool,
         {
           edit_mode = GIMP_TRANSLATE_MODE_FLOATING_SEL;
 
-          if (gimp_item_is_position_locked (selected_items->data))
+          if (gimp_item_is_position_locked (selected_items->data,
+                                            &locked_item))
             {
-              locked_message = _("The active layer's position is locked.");
+              locked_message = _("The selected layer's position is locked.");
             }
         }
       else
@@ -1138,7 +1142,7 @@ gimp_edit_selection_tool_translate (GimpTool          *tool,
           edit_mode = GIMP_TRANSLATE_MODE_LAYER;
 
           for (iter = selected_items; iter; iter = iter->next)
-            if (! gimp_item_is_position_locked (iter->data))
+            if (! gimp_item_is_position_locked (iter->data, NULL))
               n_items++;
 
           if (n_items == 0)
diff --git a/app/tools/gimpmovetool.c b/app/tools/gimpmovetool.c
index cb2b499576..71a16c35a9 100644
--- a/app/tools/gimpmovetool.c
+++ b/app/tools/gimpmovetool.c
@@ -189,6 +189,7 @@ gimp_move_tool_button_press (GimpTool            *tool,
   GimpTranslateMode  translate_mode = GIMP_TRANSLATE_MODE_MASK;
   const gchar       *null_message   = NULL;
   const gchar       *locked_message = NULL;
+  GimpItem          *locked_item    = NULL;
 
   tool->display = display;
 
@@ -297,7 +298,7 @@ gimp_move_tool_button_press (GimpTool            *tool,
 
             for (iter = selected_items; iter; iter = iter->next)
               {
-                if (! gimp_item_is_position_locked (iter->data))
+                if (! gimp_item_is_position_locked (iter->data, &locked_item))
                   n_items++;
               }
 
@@ -321,7 +322,7 @@ gimp_move_tool_button_press (GimpTool            *tool,
             /* cannot happen, don't translate this message */
             null_message  = "There is no selection to move.";
           }
-        else if (gimp_item_is_position_locked (active_item))
+        else if (gimp_item_is_position_locked (active_item, &locked_item))
           {
             locked_message = "The selection's position is locked.";
           }
@@ -342,37 +343,27 @@ gimp_move_tool_button_press (GimpTool            *tool,
 
             translate_mode = GIMP_TRANSLATE_MODE_LAYER_MASK;
 
-            if (gimp_item_is_position_locked (selected_items->data))
+            if (gimp_item_is_position_locked (selected_items->data, &locked_item))
               locked_message = _("The selected layer's position is locked.");
             else if (gimp_item_is_content_locked (selected_items->data, NULL))
               locked_message = _("The selected layer's pixels are locked.");
           }
         else if (GIMP_IS_CHANNEL (selected_items->data))
           {
-            gint n_items = 0;
-
             translate_mode = GIMP_TRANSLATE_MODE_CHANNEL;
 
             for (iter = selected_items; iter; iter = iter->next)
-              if (! gimp_item_is_position_locked (iter->data) &&
-                  ! gimp_item_is_content_locked (iter->data, NULL))
-                n_items++;
-
-            if (n_items == 0)
-              locked_message = _("All selected channels' positions or pixels are locked.");
+              if (gimp_item_is_position_locked (iter->data, &locked_item) ||
+                  gimp_item_is_content_locked (iter->data, &locked_item))
+              locked_message = _("A selected channel's position or pixels are locked.");
           }
         else
           {
-            gint n_items = 0;
-
             translate_mode = GIMP_TRANSLATE_MODE_LAYER;
 
             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 layers' positions are locked.");
+              if (gimp_item_is_position_locked (iter->data, &locked_item))
+              locked_message = _("A selected layers' position is locked.");
           }
       }
       break;
@@ -391,8 +382,11 @@ gimp_move_tool_button_press (GimpTool            *tool,
   else if (locked_message)
     {
       gimp_tool_message_literal (tool, display, locked_message);
-      gimp_tools_blink_lock_box (display->gimp,
-                                 active_item ? active_item : selected_items->data);
+
+      if (locked_item == NULL)
+        locked_item = active_item ? active_item : selected_items->data;
+
+      gimp_tools_blink_lock_box (display->gimp, locked_item);
       gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
       g_list_free (selected_items);
       return;
@@ -603,7 +597,7 @@ gimp_move_tool_cursor_update (GimpTool         *tool,
 
           for (iter = selected; iter; iter = iter->next)
             {
-              if (! gimp_item_is_position_locked (iter->data))
+              if (! gimp_item_is_position_locked (iter->data, NULL))
                 n_items++;
             }
 
@@ -640,7 +634,7 @@ gimp_move_tool_cursor_update (GimpTool         *tool,
       gint   n_items = 0;
 
       for (iter = items; iter; iter = iter->next)
-        if (! gimp_item_is_position_locked (iter->data))
+        if (! gimp_item_is_position_locked (iter->data, NULL))
           n_items++;
       if (n_items == 0)
         modifier = GIMP_CURSOR_MODIFIER_BAD;
@@ -670,7 +664,7 @@ gimp_move_tool_cursor_update (GimpTool         *tool,
               tool_cursor = GIMP_TOOL_CURSOR_MOVE;
               modifier    = GIMP_CURSOR_MODIFIER_ANCHOR;
             }
-          else if (gimp_item_is_position_locked (GIMP_ITEM (layer)))
+          else if (gimp_item_is_position_locked (GIMP_ITEM (layer), NULL))
             {
               modifier = GIMP_CURSOR_MODIFIER_BAD;
             }
diff --git a/app/tools/gimptransformtool.c b/app/tools/gimptransformtool.c
index 1f39aca065..1eee63db19 100644
--- a/app/tools/gimptransformtool.c
+++ b/app/tools/gimptransformtool.c
@@ -680,7 +680,7 @@ gimp_transform_tool_check_selected_objects (GimpTransformTool  *tr_tool,
 
           if (gimp_item_is_content_locked (item, &locked_item))
             locked_message = _("A selected layer's pixels are locked.");
-          else if (gimp_item_is_position_locked (item))
+          else if (gimp_item_is_position_locked (item, &locked_item))
             locked_message = _("A selected layer's position and size are locked.");
 
           if (! gimp_item_is_visible (item) &&
@@ -711,7 +711,7 @@ gimp_transform_tool_check_selected_objects (GimpTransformTool  *tr_tool,
           /* cannot happen, so don't translate these messages */
           if (gimp_item_is_content_locked (item, &locked_item))
             locked_message = "The selection's pixels are locked.";
-          else if (gimp_item_is_position_locked (item))
+          else if (gimp_item_is_position_locked (item, &locked_item))
             locked_message = "The selection's position and size are locked.";
         }
       break;
@@ -725,10 +725,10 @@ gimp_transform_tool_check_selected_objects (GimpTransformTool  *tr_tool,
 
           if (gimp_item_is_content_locked (item, &locked_item))
             locked_message = _("The selected path's strokes are locked.");
-          else if (gimp_item_is_position_locked (item))
-            locked_message = _("The active path's position is locked.");
+          else if (gimp_item_is_position_locked (item, &locked_item))
+            locked_message = _("The selected path's position is locked.");
           else if (! gimp_vectors_get_n_strokes (GIMP_VECTORS (item)))
-            locked_message = _("The active path has no strokes.");
+            locked_message = _("The selected path has no strokes.");
         }
       break;
 


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