[gimp/wip/Jehan/layers-dockable-refresh: 9/70] app: add an item visibility lock.




commit 18899803f19b8577fa98c8e7b83e50cc3b636ae3
Author: Jehan <jehan girinstud io>
Date:   Sat Dec 23 23:57:12 2017 +0100

    app: add an item visibility lock.
    
    Sometimes one may want to lock visibility of a given layer. This is very
    useful in particular when shift-clicking a layer visibility. In this
    case, it won't be included in the list of layer to update. This can be
    used for instance if you want some layers always visible (or always
    hidden) while setting exclusive visibility of some other layers only.

 app/core/core-enums.c              |   2 +
 app/core/core-enums.h              |   1 +
 app/core/gimpimage-undo-push.c     |  16 ++++
 app/core/gimpimage-undo-push.h     |   3 +
 app/core/gimpitem-exclusive.c      |  25 +++----
 app/core/gimpitem.c                |  93 +++++++++++++++++++++++-
 app/core/gimpitem.h                |   9 +++
 app/core/gimpitempropundo.c        |  14 ++++
 app/core/gimpitempropundo.h        |   9 ++-
 app/widgets/gimpdrawabletreeview.c |  10 ++-
 app/widgets/gimphelp-ids.h         |   2 +
 app/widgets/gimpitemtreeview.c     | 145 ++++++++++++++++++++++++++++++++++---
 app/widgets/gimpitemtreeview.h     |   5 ++
 13 files changed, 302 insertions(+), 32 deletions(-)
---
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 9b459c9320..1c55ae0f23 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -1224,6 +1224,7 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_ITEM_COLOR_TAG, "GIMP_UNDO_ITEM_COLOR_TAG", "item-color-tag" },
     { GIMP_UNDO_ITEM_LOCK_CONTENT, "GIMP_UNDO_ITEM_LOCK_CONTENT", "item-lock-content" },
     { GIMP_UNDO_ITEM_LOCK_POSITION, "GIMP_UNDO_ITEM_LOCK_POSITION", "item-lock-position" },
+    { GIMP_UNDO_ITEM_LOCK_VISIBILITY, "GIMP_UNDO_ITEM_LOCK_VISIBILITY", "item-lock-visibility" },
     { GIMP_UNDO_LAYER_ADD, "GIMP_UNDO_LAYER_ADD", "layer-add" },
     { GIMP_UNDO_LAYER_REMOVE, "GIMP_UNDO_LAYER_REMOVE", "layer-remove" },
     { GIMP_UNDO_LAYER_MODE, "GIMP_UNDO_LAYER_MODE", "layer-mode" },
@@ -1331,6 +1332,7 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_ITEM_COLOR_TAG, NC_("undo-type", "Item color tag"), NULL },
     { GIMP_UNDO_ITEM_LOCK_CONTENT, NC_("undo-type", "Lock/Unlock content"), NULL },
     { GIMP_UNDO_ITEM_LOCK_POSITION, NC_("undo-type", "Lock/Unlock position"), NULL },
+    { GIMP_UNDO_ITEM_LOCK_VISIBILITY, NC_("undo-type", "Lock/Unlock visibility"), NULL },
     { GIMP_UNDO_LAYER_ADD, NC_("undo-type", "New layer"), NULL },
     { GIMP_UNDO_LAYER_REMOVE, NC_("undo-type", "Delete layer"), NULL },
     { GIMP_UNDO_LAYER_MODE, NC_("undo-type", "Set layer mode"), NULL },
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index ead4a09fc8..e55729acd9 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -596,6 +596,7 @@ typedef enum /*< pdb-skip >*/
   GIMP_UNDO_ITEM_COLOR_TAG,              /*< desc="Item color tag"                 >*/
   GIMP_UNDO_ITEM_LOCK_CONTENT,           /*< desc="Lock/Unlock content"            >*/
   GIMP_UNDO_ITEM_LOCK_POSITION,          /*< desc="Lock/Unlock position"           >*/
+  GIMP_UNDO_ITEM_LOCK_VISIBILITY,        /*< desc="Lock/Unlock visibility"      >*/
   GIMP_UNDO_LAYER_ADD,                   /*< desc="New layer"                      >*/
   GIMP_UNDO_LAYER_REMOVE,                /*< desc="Delete layer"                   >*/
   GIMP_UNDO_LAYER_MODE,                  /*< desc="Set layer mode"                 >*/
diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c
index aeb293c380..c2f9190114 100644
--- a/app/core/gimpimage-undo-push.c
+++ b/app/core/gimpimage-undo-push.c
@@ -482,6 +482,22 @@ gimp_image_undo_push_item_lock_position (GimpImage   *image,
                                NULL);
 }
 
+GimpUndo *
+gimp_image_undo_push_item_lock_visibility (GimpImage   *image,
+                                           const gchar *undo_desc,
+                                           GimpItem    *item)
+{
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
+  g_return_val_if_fail (gimp_item_is_attached (item), NULL);
+
+  return gimp_image_undo_push (image, GIMP_TYPE_ITEM_PROP_UNDO,
+                               GIMP_UNDO_ITEM_LOCK_VISIBILITY, undo_desc,
+                               GIMP_DIRTY_ITEM_META,
+                               "item", item,
+                               NULL);
+}
+
 GimpUndo *
 gimp_image_undo_push_item_parasite (GimpImage          *image,
                                     const gchar        *undo_desc,
diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h
index 3aea6e4a1f..57a3ec9fc0 100644
--- a/app/core/gimpimage-undo-push.h
+++ b/app/core/gimpimage-undo-push.h
@@ -113,6 +113,9 @@ GimpUndo * gimp_image_undo_push_item_lock_content   (GimpImage     *image,
 GimpUndo * gimp_image_undo_push_item_lock_position  (GimpImage     *image,
                                                      const gchar   *undo_desc,
                                                      GimpItem      *item);
+GimpUndo * gimp_image_undo_push_item_lock_visibility (GimpImage    *image,
+                                                      const gchar  *undo_desc,
+                                                      GimpItem     *item);
 GimpUndo * gimp_image_undo_push_item_parasite       (GimpImage     *image,
                                                      const gchar   *undo_desc,
                                                      GimpItem      *item,
diff --git a/app/core/gimpitem-exclusive.c b/app/core/gimpitem-exclusive.c
index 5cdb45f32f..6b07c268f3 100644
--- a/app/core/gimpitem-exclusive.c
+++ b/app/core/gimpitem-exclusive.c
@@ -253,22 +253,21 @@ gimp_item_exclusive_get_lists (GimpItem     *item,
     {
       GimpItem *other = list->data;
 
-      if (other != item)
+      if (other != item                            &&
+          /* Don't include item with visibility locks. */
+          ! gimp_item_is_visibility_locked (other) &&
+          /* We are only interested in same level items. */
+          gimp_viewable_get_parent (GIMP_VIEWABLE (other)) ==
+          gimp_viewable_get_parent (GIMP_VIEWABLE (item)))
         {
-          /* we are only interested in same level items.
-           */
-          if (gimp_viewable_get_parent (GIMP_VIEWABLE (other)) ==
-              gimp_viewable_get_parent (GIMP_VIEWABLE (item)))
-            {
-              gboolean value;
+          gboolean value;
 
-              g_object_get (other, property, &value, NULL);
+          g_object_get (other, property, &value, NULL);
 
-              if (value)
-                *on = g_list_prepend (*on, other);
-              else
-                *off = g_list_prepend (*off, other);
-            }
+          if (value)
+            *on = g_list_prepend (*on, other);
+          else
+            *off = g_list_prepend (*off, other);
         }
     }
 
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index 16d75b7dd2..98257f33a6 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -58,6 +58,7 @@ enum
   COLOR_TAG_CHANGED,
   LOCK_CONTENT_CHANGED,
   LOCK_POSITION_CHANGED,
+  LOCK_VISIBILITY_CHANGED,
   LAST_SIGNAL
 };
 
@@ -75,6 +76,7 @@ enum
   PROP_COLOR_TAG,
   PROP_LOCK_CONTENT,
   PROP_LOCK_POSITION,
+  PROP_LOCK_VISIBILITY,
   N_PROPS
 };
 
@@ -99,6 +101,7 @@ struct _GimpItemPrivate
   guint             linked                 : 1;  /*  control linkage             */
   guint             lock_content           : 1;  /*  content editability         */
   guint             lock_position          : 1;  /*  content movability          */
+  guint             lock_visibility        : 1;  /*  automatic visibility change */
 
   guint             removed                : 1;  /*  removed from the image?     */
 
@@ -128,6 +131,7 @@ static gint64     gimp_item_get_memsize             (GimpObject     *object,
 
 static gboolean   gimp_item_real_is_content_locked  (GimpItem       *item);
 static gboolean   gimp_item_real_is_position_locked (GimpItem       *item);
+static gboolean   gimp_item_real_is_visibility_locked (GimpItem       *item);
 static gboolean   gimp_item_real_bounds             (GimpItem       *item,
                                                      gdouble        *x,
                                                      gdouble        *y,
@@ -233,6 +237,14 @@ gimp_item_class_init (GimpItemClass *klass)
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
 
+  gimp_item_signals[LOCK_VISIBILITY_CHANGED] =
+    g_signal_new ("lock-visibility-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpItemClass, lock_visibility_changed),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   object_class->constructed        = gimp_item_constructed;
   object_class->finalize           = gimp_item_finalize;
   object_class->set_property       = gimp_item_set_property;
@@ -250,11 +262,13 @@ gimp_item_class_init (GimpItemClass *klass)
   klass->color_tag_changed         = NULL;
   klass->lock_content_changed      = NULL;
   klass->lock_position_changed     = NULL;
+  klass->lock_visibility_changed   = NULL;
 
   klass->unset_removed             = NULL;
   klass->is_attached               = NULL;
   klass->is_content_locked         = gimp_item_real_is_content_locked;
   klass->is_position_locked        = gimp_item_real_is_position_locked;
+  klass->is_visibility_locked      = gimp_item_real_is_visibility_locked;
   klass->get_tree                  = NULL;
   klass->bounds                    = gimp_item_real_bounds;
   klass->duplicate                 = gimp_item_real_duplicate;
@@ -335,6 +349,11 @@ gimp_item_class_init (GimpItemClass *klass)
                                                               FALSE,
                                                               GIMP_PARAM_READABLE);
 
+  gimp_item_props[PROP_LOCK_VISIBILITY] = g_param_spec_boolean ("lock-visibility",
+                                                                NULL, NULL,
+                                                                FALSE,
+                                                                GIMP_PARAM_READABLE);
+
   g_object_class_install_properties (object_class, N_PROPS, gimp_item_props);
 }
 
@@ -447,6 +466,9 @@ gimp_item_get_property (GObject    *object,
     case PROP_LOCK_POSITION:
       g_value_set_boolean (value, private->lock_position);
       break;
+    case PROP_LOCK_VISIBILITY:
+      g_value_set_boolean (value, private->lock_visibility);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -489,6 +511,18 @@ gimp_item_real_is_position_locked (GimpItem *item)
   return GET_PRIVATE (item)->lock_position;
 }
 
+static gboolean
+gimp_item_real_is_visibility_locked (GimpItem *item)
+{
+  GimpItem *parent = gimp_item_get_parent (item);
+
+  /* Locking visibility of a group item locks all child items. */
+  if (parent && gimp_item_is_visibility_locked (parent))
+    return TRUE;
+
+  return GET_PRIVATE (item)->lock_visibility;
+}
+
 static gboolean
 gimp_item_real_bounds (GimpItem *item,
                        gdouble  *x,
@@ -571,6 +605,10 @@ gimp_item_real_duplicate (GimpItem *item,
     gimp_item_set_lock_position (new_item, gimp_item_get_lock_position (item),
                                  FALSE);
 
+  if (gimp_item_can_lock_visibility (new_item))
+    gimp_item_set_lock_visibility (new_item, gimp_item_get_lock_visibility (item),
+                                   FALSE);
+
   return new_item;
 }
 
@@ -2068,6 +2106,7 @@ gimp_item_replace_item (GimpItem *item,
   gimp_item_set_color_tag     (item, gimp_item_get_color_tag (replace), FALSE);
   gimp_item_set_lock_content  (item, gimp_item_get_lock_content (replace), FALSE);
   gimp_item_set_lock_position (item, gimp_item_get_lock_position (replace), FALSE);
+  gimp_item_set_lock_visibility (item, gimp_item_get_lock_visibility (replace), FALSE);
 }
 
 /**
@@ -2280,7 +2319,8 @@ gimp_item_set_visible (GimpItem *item,
 
   visible = visible ? TRUE : FALSE;
 
-  if (gimp_item_get_visible (item) != visible)
+  if (gimp_item_get_visible (item) != visible &&
+      ! gimp_item_is_visibility_locked (item))
     {
       if (push_undo && gimp_item_is_attached (item))
         {
@@ -2539,6 +2579,57 @@ gimp_item_is_position_locked (GimpItem *item)
   return GIMP_ITEM_GET_CLASS (item)->is_position_locked (item);
 }
 
+void
+gimp_item_set_lock_visibility (GimpItem *item,
+                               gboolean  lock_visibility,
+                               gboolean  push_undo)
+{
+  g_return_if_fail (GIMP_IS_ITEM (item));
+  g_return_if_fail (gimp_item_can_lock_visibility (item));
+
+  lock_visibility = lock_visibility ? TRUE : FALSE;
+
+  if (gimp_item_get_lock_visibility (item) != lock_visibility)
+    {
+      if (push_undo && gimp_item_is_attached (item))
+        {
+          GimpImage *image = gimp_item_get_image (item);
+
+          gimp_image_undo_push_item_lock_visibility (image, NULL, item);
+        }
+
+      GET_PRIVATE (item)->lock_visibility = lock_visibility;
+
+      g_signal_emit (item, gimp_item_signals[LOCK_VISIBILITY_CHANGED], 0);
+
+      g_object_notify (G_OBJECT (item), "lock-visibility");
+    }
+}
+
+gboolean
+gimp_item_get_lock_visibility (GimpItem *item)
+{
+  g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
+
+  return GET_PRIVATE (item)->lock_visibility;
+}
+
+gboolean
+gimp_item_can_lock_visibility (GimpItem *item)
+{
+  g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
+
+  return TRUE;
+}
+
+gboolean
+gimp_item_is_visibility_locked (GimpItem *item)
+{
+  g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
+
+  return GIMP_ITEM_GET_CLASS (item)->is_visibility_locked (item);
+}
+
 gboolean
 gimp_item_mask_bounds (GimpItem *item,
                        gint     *x1,
diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h
index f71e32b017..2c9794c9ed 100644
--- a/app/core/gimpitem.h
+++ b/app/core/gimpitem.h
@@ -48,12 +48,14 @@ struct _GimpItemClass
   void            (* color_tag_changed)     (GimpItem            *item);
   void            (* lock_content_changed)  (GimpItem            *item);
   void            (* lock_position_changed) (GimpItem            *item);
+  void            (* lock_visibility_changed) (GimpItem            *item);
 
   /*  virtual functions  */
   void            (* unset_removed)      (GimpItem               *item);
   gboolean        (* is_attached)        (GimpItem               *item);
   gboolean        (* is_content_locked)  (GimpItem               *item);
   gboolean        (* is_position_locked) (GimpItem               *item);
+  gboolean        (* is_visibility_locked) (GimpItem               *item);
   GimpItemTree  * (* get_tree)           (GimpItem               *item);
   gboolean        (* bounds)             (GimpItem               *item,
                                           gdouble                *x,
@@ -387,6 +389,13 @@ gboolean        gimp_item_get_lock_position  (GimpItem          *item);
 gboolean        gimp_item_can_lock_position  (GimpItem          *item);
 gboolean        gimp_item_is_position_locked (GimpItem          *item);
 
+void            gimp_item_set_lock_visibility  (GimpItem        *item,
+                                                gboolean         lock_visibility,
+                                                gboolean         push_undo);
+gboolean        gimp_item_get_lock_visibility  (GimpItem        *item);
+gboolean        gimp_item_can_lock_visibility  (GimpItem        *item);
+gboolean        gimp_item_is_visibility_locked (GimpItem        *item);
+
 gboolean        gimp_item_mask_bounds        (GimpItem           *item,
                                               gint               *x1,
                                               gint               *y1,
diff --git a/app/core/gimpitempropundo.c b/app/core/gimpitempropundo.c
index 241b8aa73f..4c96c203e5 100644
--- a/app/core/gimpitempropundo.c
+++ b/app/core/gimpitempropundo.c
@@ -139,6 +139,10 @@ gimp_item_prop_undo_constructed (GObject *object)
       item_prop_undo->lock_position = gimp_item_get_lock_position (item);
       break;
 
+    case GIMP_UNDO_ITEM_LOCK_VISIBILITY:
+      item_prop_undo->lock_visibility = gimp_item_get_lock_visibility (item);
+      break;
+
     case GIMP_UNDO_PARASITE_ATTACH:
     case GIMP_UNDO_PARASITE_REMOVE:
       gimp_assert (item_prop_undo->parasite_name != NULL);
@@ -319,6 +323,16 @@ gimp_item_prop_undo_pop (GimpUndo            *undo,
       }
       break;
 
+    case GIMP_UNDO_ITEM_LOCK_VISIBILITY:
+      {
+        gboolean lock_visibility;
+
+        lock_visibility = gimp_item_get_lock_visibility (item);
+        gimp_item_set_lock_visibility (item, item_prop_undo->lock_visibility, FALSE);
+        item_prop_undo->lock_visibility = lock_visibility;
+      }
+      break;
+
     case GIMP_UNDO_PARASITE_ATTACH:
     case GIMP_UNDO_PARASITE_REMOVE:
       {
diff --git a/app/core/gimpitempropundo.h b/app/core/gimpitempropundo.h
index 8f96e46519..8f5a8c79f5 100644
--- a/app/core/gimpitempropundo.h
+++ b/app/core/gimpitempropundo.h
@@ -42,10 +42,11 @@ struct _GimpItemPropUndo
   gchar        *name;
   gint          offset_x;
   gint          offset_y;
-  guint         visible       : 1;
-  guint         linked        : 1;
-  guint         lock_content  : 1;
-  guint         lock_position : 1;
+  guint         visible         : 1;
+  guint         linked          : 1;
+  guint         lock_content    : 1;
+  guint         lock_position   : 1;
+  guint         lock_visibility : 1;
   GimpColorTag  color_tag;
   gchar        *parasite_name;
   GimpParasite *parasite;
diff --git a/app/widgets/gimpdrawabletreeview.c b/app/widgets/gimpdrawabletreeview.c
index b3465fa5c9..ad3ae0b7d9 100644
--- a/app/widgets/gimpdrawabletreeview.c
+++ b/app/widgets/gimpdrawabletreeview.c
@@ -118,10 +118,12 @@ gimp_drawable_tree_view_class_init (GimpDrawableTreeViewClass *klass)
 
   item_view_class->set_image     = gimp_drawable_tree_view_set_image;
 
-  item_view_class->lock_content_icon_name  = GIMP_ICON_TOOL_PAINTBRUSH;
-  item_view_class->lock_content_tooltip    = _("Lock pixels");
-  item_view_class->lock_position_icon_name = GIMP_ICON_TOOL_MOVE;
-  item_view_class->lock_position_tooltip   = _("Lock position and size");
+  item_view_class->lock_content_icon_name    = GIMP_ICON_TOOL_PAINTBRUSH;
+  item_view_class->lock_content_tooltip      = _("Lock pixels");
+  item_view_class->lock_position_icon_name   = GIMP_ICON_TOOL_MOVE;
+  item_view_class->lock_position_tooltip     = _("Lock position and size");
+  item_view_class->lock_visibility_icon_name = GIMP_ICON_VISIBLE;
+  item_view_class->lock_visibility_tooltip   = _("Lock visibility");
 }
 
 static void
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index 96b8c1fe0c..60ebd9ecc0 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -201,6 +201,7 @@
 #define GIMP_HELP_LAYER_LOCK_ALPHA                "gimp-layer-lock-alpha"
 #define GIMP_HELP_LAYER_LOCK_PIXELS               "gimp-layer-lock-pixels"
 #define GIMP_HELP_LAYER_LOCK_POSITION             "gimp-layer-lock-position"
+#define GIMP_HELP_LAYER_LOCK_VISIBILITY           "gimp-layer-lock-visibility"
 #define GIMP_HELP_LAYER_MASK_ADD                  "gimp-layer-mask-add"
 #define GIMP_HELP_LAYER_MASK_APPLY                "gimp-layer-mask-apply"
 #define GIMP_HELP_LAYER_MASK_DELETE               "gimp-layer-mask-delete"
@@ -245,6 +246,7 @@
 #define GIMP_HELP_CHANNEL_COLOR_TAG               "gimp-channel-color-tag"
 #define GIMP_HELP_CHANNEL_LOCK_PIXELS             "gimp-channel-lock-pixels"
 #define GIMP_HELP_CHANNEL_LOCK_POSITION           "gimp-channel-lock-position"
+#define GIMP_HELP_CHANNEL_LOCK_VISIBILITY         "gimp-channel-lock-visibility"
 #define GIMP_HELP_CHANNEL_SELECTION_REPLACE       "gimp-channel-selection-replace"
 #define GIMP_HELP_CHANNEL_SELECTION_ADD           "gimp-channel-selection-add"
 #define GIMP_HELP_CHANNEL_SELECTION_SUBTRACT      "gimp-channel-selection-subtract"
diff --git a/app/widgets/gimpitemtreeview.c b/app/widgets/gimpitemtreeview.c
index 5f163db569..844cd98679 100644
--- a/app/widgets/gimpitemtreeview.c
+++ b/app/widgets/gimpitemtreeview.c
@@ -76,6 +76,7 @@ struct _GimpItemTreeViewPrivate
   GtkWidget       *multi_selection_label;
   GtkWidget       *lock_content_toggle;
   GtkWidget       *lock_position_toggle;
+  GtkWidget       *lock_visibility_toggle;
 
   GtkWidget       *new_button;
   GtkWidget       *raise_button;
@@ -95,6 +96,7 @@ struct _GimpItemTreeViewPrivate
   GimpTreeHandler *color_tag_changed_handler;
   GimpTreeHandler *lock_content_changed_handler;
   GimpTreeHandler *lock_position_changed_handler;
+  GimpTreeHandler *lock_visibility_changed_handler;
 
   gboolean         inserting_item; /* EEK */
 };
@@ -172,16 +174,18 @@ static void   gimp_item_tree_view_name_edited       (GtkCellRendererText *cell,
                                                      const gchar       *new_name,
                                                      GimpItemTreeView  *view);
 
-static void   gimp_item_tree_view_visible_changed      (GimpItem          *item,
-                                                        GimpItemTreeView  *view);
-static void   gimp_item_tree_view_linked_changed       (GimpItem          *item,
-                                                        GimpItemTreeView  *view);
-static void   gimp_item_tree_view_color_tag_changed    (GimpItem          *item,
-                                                        GimpItemTreeView  *view);
-static void   gimp_item_tree_view_lock_content_changed (GimpItem          *item,
-                                                        GimpItemTreeView  *view);
-static void   gimp_item_tree_view_lock_position_changed(GimpItem          *item,
-                                                        GimpItemTreeView  *view);
+static void   gimp_item_tree_view_visible_changed         (GimpItem          *item,
+                                                           GimpItemTreeView  *view);
+static void   gimp_item_tree_view_linked_changed          (GimpItem          *item,
+                                                           GimpItemTreeView  *view);
+static void   gimp_item_tree_view_color_tag_changed       (GimpItem          *item,
+                                                           GimpItemTreeView  *view);
+static void   gimp_item_tree_view_lock_content_changed    (GimpItem          *item,
+                                                           GimpItemTreeView  *view);
+static void   gimp_item_tree_view_lock_position_changed   (GimpItem          *item,
+                                                           GimpItemTreeView  *view);
+static void   gimp_item_tree_view_lock_visibility_changed (GimpItem          *item,
+                                                           GimpItemTreeView  *view);
 
 static void   gimp_item_tree_view_eye_clicked       (GtkCellRendererToggle *toggle,
                                                      gchar             *path,
@@ -197,6 +201,9 @@ static void   gimp_item_tree_view_lock_content_toggled
 static void   gimp_item_tree_view_lock_position_toggled
                                                     (GtkWidget         *widget,
                                                      GimpItemTreeView  *view);
+static void   gimp_item_tree_view_lock_visibility_toggled
+                                                    (GtkWidget         *widget,
+                                                     GimpItemTreeView  *view);
 static void   gimp_item_tree_view_update_options    (GimpItemTreeView  *view,
                                                      GList             *items);
 
@@ -293,6 +300,10 @@ gimp_item_tree_view_class_init (GimpItemTreeViewClass *klass)
   klass->lock_position_icon_name  = NULL;
   klass->lock_position_tooltip    = NULL;
   klass->lock_position_help_id    = NULL;
+
+  klass->lock_visibility_icon_name = NULL;
+  klass->lock_visibility_tooltip   = NULL;
+  klass->lock_visibility_help_id   = NULL;
 }
 
 static void
@@ -537,6 +548,28 @@ gimp_item_tree_view_constructed (GObject *object)
   gtk_container_add (GTK_CONTAINER (item_view->priv->lock_position_toggle),
                      image);
   gtk_widget_show (image);
+
+  /*  Lock visibility toggle  */
+  item_view->priv->lock_visibility_toggle = gtk_toggle_button_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), item_view->priv->lock_visibility_toggle,
+                      FALSE, FALSE, 0);
+  gtk_box_reorder_child (GTK_BOX (hbox),
+                         item_view->priv->lock_visibility_toggle, 2);
+  gtk_widget_show (item_view->priv->lock_visibility_toggle);
+
+  g_signal_connect (item_view->priv->lock_visibility_toggle, "toggled",
+                    G_CALLBACK (gimp_item_tree_view_lock_visibility_toggled),
+                    item_view);
+
+  gimp_help_set_help_data (item_view->priv->lock_visibility_toggle,
+                           item_view_class->lock_visibility_tooltip,
+                           item_view_class->lock_visibility_help_id);
+
+  image = gtk_image_new_from_icon_name (item_view_class->lock_visibility_icon_name,
+                                        icon_size);
+  gtk_container_add (GTK_CONTAINER (item_view->priv->lock_visibility_toggle),
+                     image);
+  gtk_widget_show (image);
 }
 
 static void
@@ -935,6 +968,9 @@ gimp_item_tree_view_set_container (GimpContainerView *view,
 
       gimp_tree_handler_disconnect (item_view->priv->lock_position_changed_handler);
       item_view->priv->lock_position_changed_handler = NULL;
+
+      gimp_tree_handler_disconnect (item_view->priv->lock_visibility_changed_handler);
+      item_view->priv->lock_visibility_changed_handler = NULL;
     }
 
   parent_view_iface->set_container (view, container);
@@ -965,6 +1001,11 @@ gimp_item_tree_view_set_container (GimpContainerView *view,
         gimp_tree_handler_connect (container, "lock-position-changed",
                                    G_CALLBACK (gimp_item_tree_view_lock_position_changed),
                                    view);
+
+      item_view->priv->lock_visibility_changed_handler =
+        gimp_tree_handler_connect (container, "lock-visibility-changed",
+                                   G_CALLBACK (gimp_item_tree_view_lock_visibility_changed),
+                                   view);
     }
 }
 
@@ -1787,6 +1828,60 @@ gimp_item_tree_view_lock_position_toggled (GtkWidget         *widget,
   gimp_image_undo_group_end (image);
 }
 
+static void
+gimp_item_tree_view_lock_visibility_changed (GimpItem         *item,
+                                             GimpItemTreeView *view)
+{
+  GimpImage *image = view->priv->image;
+  GimpItem  *active_item;
+
+  active_item = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_active_item (image);
+
+  if (active_item == item)
+    gimp_item_tree_view_update_options (view, item);
+}
+
+static void
+gimp_item_tree_view_lock_visibility_toggled (GtkWidget        *widget,
+                                             GimpItemTreeView *view)
+{
+  GimpImage *image = view->priv->image;
+  GimpItem  *item;
+
+  item = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_active_item (image);
+
+  if (item)
+    {
+      gboolean lock_visibility;
+
+      lock_visibility = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+      if (gimp_item_get_lock_visibility (item) != lock_visibility)
+        {
+          GimpUndo *undo;
+          gboolean  push_undo = TRUE;
+
+          /*  compress lock visibilities undos  */
+          undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
+                                               GIMP_UNDO_ITEM_LOCK_VISIBILITY);
+
+          if (undo && GIMP_ITEM_UNDO (undo)->item == item)
+            push_undo = FALSE;
+
+          g_signal_handlers_block_by_func (item,
+                                           gimp_item_tree_view_lock_visibility_changed,
+                                           view);
+
+          gimp_item_set_lock_visibility (item, lock_visibility, push_undo);
+
+          g_signal_handlers_unblock_by_func (item,
+                                             gimp_item_tree_view_lock_visibility_changed,
+                                             view);
+          gimp_image_flush (image);
+        }
+    }
+}
+
 static gboolean
 gimp_item_tree_view_item_pre_clicked (GimpCellRendererViewable *cell,
                                       const gchar              *path_str,
@@ -1857,8 +1952,11 @@ gimp_item_tree_view_update_options (GimpItemTreeView *view,
   gboolean  some_can_lock_content      = FALSE;
   gboolean  all_have_lock_position     = TRUE;
   gboolean  some_can_lock_position     = FALSE;
+  gboolean  all_have_lock_visibility   = TRUE;
+  gboolean  some_can_lock_visibility   = FALSE;
   gboolean  inconsistent_lock_content  = FALSE;
   gboolean  inconsistent_lock_position = FALSE;
+  gboolean  inconsistent_lock_visibility = FALSE;
 
   for (iter = items; iter; iter = iter->next)
     {
@@ -1877,9 +1975,18 @@ gimp_item_tree_view_update_options (GimpItemTreeView *view,
 
       if (gimp_item_can_lock_position (iter->data))
         some_can_lock_position = TRUE;
+
+      if (! gimp_item_get_lock_visibility (iter->data))
+        all_have_lock_visibility = FALSE;
+      else
+        inconsistent_lock_visibility = TRUE;
+
+      if (gimp_item_can_lock_visibility (iter->data))
+        some_can_lock_visibility = TRUE;
     }
   inconsistent_lock_content  = (! all_have_lock_content && inconsistent_lock_content);
   inconsistent_lock_position = (! all_have_lock_position && inconsistent_lock_position);
+  inconsistent_lock_visibility = (! all_have_lock_visibility && inconsistent_lock_visibility);
 
   if (all_have_lock_content !=
       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->lock_content_toggle)))
@@ -1915,8 +2022,26 @@ gimp_item_tree_view_update_options (GimpItemTreeView *view,
   gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (view->priv->lock_position_toggle),
                                       inconsistent_lock_position);
 
+  if (all_have_lock_visibility !=
+      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (view->priv->lock_visibility_toggle)))
+    {
+      g_signal_handlers_block_by_func (view->priv->lock_visibility_toggle,
+                                       gimp_item_tree_view_lock_visibility_toggled,
+                                       view);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->lock_visibility_toggle),
+                                    all_have_lock_visibility);
+
+      g_signal_handlers_unblock_by_func (view->priv->lock_visibility_toggle,
+                                         gimp_item_tree_view_lock_visibility_toggled,
+                                         view);
+    }
+  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (view->priv->lock_visibility_toggle),
+                                      inconsistent_lock_visibility);
+
   gtk_widget_set_sensitive (view->priv->lock_content_toggle, some_can_lock_content);
   gtk_widget_set_sensitive (view->priv->lock_position_toggle, some_can_lock_position);
+  gtk_widget_set_sensitive (view->priv->lock_position_toggle, some_can_lock_visibility);
 }
 
 
diff --git a/app/widgets/gimpitemtreeview.h b/app/widgets/gimpitemtreeview.h
index 5c7ab29165..951d6b4b8f 100644
--- a/app/widgets/gimpitemtreeview.h
+++ b/app/widgets/gimpitemtreeview.h
@@ -104,6 +104,11 @@ struct _GimpItemTreeViewClass
   const gchar          *lock_position_icon_name;
   const gchar          *lock_position_tooltip;
   const gchar          *lock_position_help_id;
+
+  /* lock visibility button appearance */
+  const gchar          *lock_visibility_icon_name;
+  const gchar          *lock_visibility_tooltip;
+  const gchar          *lock_visibility_help_id;
 };
 
 


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