[gimp] Fix undoing a group layer type conversion



commit 717b4e6a07b5a30e4e303695e34ac1a1929e6e4d
Author: Michael Natterer <mitch gimp org>
Date:   Sun Sep 13 19:24:19 2009 +0200

    Fix undoing a group layer type conversion
    
    * app/core/gimpdrawable.[ch]: add "gboolean push_undo" to
      GimpDrawable::convert_type().
    
    * app/core/gimpdrawable-convert.[ch]: same here for the gray and rgb
      conversion functions.
    
    * app/core/gimpchannel.c
    * app/core/gimplayer.c: pass FALSE when called from GimpItem::convert()
      because it can be called on unattached items only.
    
    * app/core/gimpimage-convert.c: pass TRUE.
    
    * app/core/core-enums.[ch]
    * app/core/gimpgrouplayerundo.[ch]
    * app/core/gimpimage-undo-push.[ch]: add GIMP_UNDO_GROUP_LAYER_CONVERT
      which simply calls gimp_drawable_convert_type() with the old type
      when undone/redone.
    
    * app/core/gimpgrouplayer.c: push a group layer convert undo so this
      can be properly undone/redone.

 app/core/core-enums.c           |    2 +
 app/core/core-enums.h           |    1 +
 app/core/gimpchannel.c          |    2 +-
 app/core/gimpdrawable-convert.c |   12 +++---
 app/core/gimpdrawable-convert.h |    6 ++-
 app/core/gimpdrawable.c         |   18 ++++++---
 app/core/gimpdrawable.h         |    6 ++-
 app/core/gimpgrouplayer.c       |   13 ++++++-
 app/core/gimpgrouplayerundo.c   |   77 ++++++++++++++++++++++++++++++---------
 app/core/gimpgrouplayerundo.h   |    4 ++-
 app/core/gimpimage-convert.c    |    3 +-
 app/core/gimpimage-undo-push.c  |   16 ++++++++
 app/core/gimpimage-undo-push.h  |    3 ++
 app/core/gimplayer.c            |   15 ++++----
 14 files changed, 133 insertions(+), 45 deletions(-)
---
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 7e33d61..0f8f6fd 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -841,6 +841,7 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_LAYER_LOCK_ALPHA, "GIMP_UNDO_LAYER_LOCK_ALPHA", "layer-lock-alpha" },
     { GIMP_UNDO_GROUP_LAYER_SUSPEND, "GIMP_UNDO_GROUP_LAYER_SUSPEND", "group-layer-suspend" },
     { GIMP_UNDO_GROUP_LAYER_RESUME, "GIMP_UNDO_GROUP_LAYER_RESUME", "group-layer-resume" },
+    { GIMP_UNDO_GROUP_LAYER_CONVERT, "GIMP_UNDO_GROUP_LAYER_CONVERT", "group-layer-convert" },
     { GIMP_UNDO_TEXT_LAYER, "GIMP_UNDO_TEXT_LAYER", "text-layer" },
     { GIMP_UNDO_TEXT_LAYER_MODIFIED, "GIMP_UNDO_TEXT_LAYER_MODIFIED", "text-layer-modified" },
     { GIMP_UNDO_LAYER_MASK_ADD, "GIMP_UNDO_LAYER_MASK_ADD", "layer-mask-add" },
@@ -928,6 +929,7 @@ gimp_undo_type_get_type (void)
     { GIMP_UNDO_LAYER_LOCK_ALPHA, NC_("undo-type", "Lock/Unlock alpha channel"), NULL },
     { GIMP_UNDO_GROUP_LAYER_SUSPEND, NC_("undo-type", "Suspend group layer resize"), NULL },
     { GIMP_UNDO_GROUP_LAYER_RESUME, NC_("undo-type", "Resume group layer resize"), NULL },
+    { GIMP_UNDO_GROUP_LAYER_CONVERT, NC_("undo-type", "Convert group layer"), NULL },
     { GIMP_UNDO_TEXT_LAYER, NC_("undo-type", "Text layer"), NULL },
     { GIMP_UNDO_TEXT_LAYER_MODIFIED, NC_("undo-type", "Text layer modification"), NULL },
     { GIMP_UNDO_LAYER_MASK_ADD, NC_("undo-type", "Add layer mask"), NULL },
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index d35751f..17a5d71 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -422,6 +422,7 @@ typedef enum /*< pdb-skip >*/
   GIMP_UNDO_LAYER_LOCK_ALPHA,         /*< desc="Lock/Unlock alpha channel"   >*/
   GIMP_UNDO_GROUP_LAYER_SUSPEND,      /*< desc="Suspend group layer resize"  >*/
   GIMP_UNDO_GROUP_LAYER_RESUME,       /*< desc="Resume group layer resize"   >*/
+  GIMP_UNDO_GROUP_LAYER_CONVERT,      /*< desc="Convert group layer"         >*/
   GIMP_UNDO_TEXT_LAYER,               /*< desc="Text layer"                  >*/
   GIMP_UNDO_TEXT_LAYER_MODIFIED,      /*< desc="Text layer modification"     >*/
   GIMP_UNDO_LAYER_MASK_ADD,           /*< desc="Add layer mask"              >*/
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index 7d57c02..16f72ce 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -434,7 +434,7 @@ gimp_channel_convert (GimpItem  *item,
 
   if (! gimp_drawable_is_gray (drawable))
     {
-      gimp_drawable_convert_type (drawable, NULL, GIMP_GRAY);
+      gimp_drawable_convert_type (drawable, NULL, GIMP_GRAY, FALSE);
     }
 
   if (gimp_drawable_has_alpha (drawable))
diff --git a/app/core/gimpdrawable-convert.c b/app/core/gimpdrawable-convert.c
index d084834..dd09bfb 100644
--- a/app/core/gimpdrawable-convert.c
+++ b/app/core/gimpdrawable-convert.c
@@ -33,7 +33,8 @@
 
 
 void
-gimp_drawable_convert_rgb (GimpDrawable *drawable)
+gimp_drawable_convert_rgb (GimpDrawable *drawable,
+                           gboolean      push_undo)
 {
   GimpImageType  type;
   TileManager   *tiles;
@@ -52,14 +53,14 @@ gimp_drawable_convert_rgb (GimpDrawable *drawable)
 
   gimp_drawable_convert_tiles_rgb (drawable, tiles);
 
-  gimp_drawable_set_tiles (drawable,
-                           gimp_item_is_attached (GIMP_ITEM (drawable)), NULL,
+  gimp_drawable_set_tiles (drawable, push_undo, NULL,
                            tiles, type);
   tile_manager_unref (tiles);
 }
 
 void
-gimp_drawable_convert_grayscale (GimpDrawable *drawable)
+gimp_drawable_convert_grayscale (GimpDrawable *drawable,
+                                 gboolean      push_undo)
 {
   GimpImageType  type;
   TileManager   *tiles;
@@ -78,8 +79,7 @@ gimp_drawable_convert_grayscale (GimpDrawable *drawable)
 
   gimp_drawable_convert_tiles_grayscale (drawable, tiles);
 
-  gimp_drawable_set_tiles (drawable,
-                           gimp_item_is_attached (GIMP_ITEM (drawable)), NULL,
+  gimp_drawable_set_tiles (drawable, push_undo, NULL,
                            tiles, type);
   tile_manager_unref (tiles);
 }
diff --git a/app/core/gimpdrawable-convert.h b/app/core/gimpdrawable-convert.h
index 12d20c7..2ae8ae7 100644
--- a/app/core/gimpdrawable-convert.h
+++ b/app/core/gimpdrawable-convert.h
@@ -19,8 +19,10 @@
 #define __GIMP_DRAWABLE_CONVERT_H__
 
 
-void   gimp_drawable_convert_rgb             (GimpDrawable *drawable);
-void   gimp_drawable_convert_grayscale       (GimpDrawable *drawable);
+void   gimp_drawable_convert_rgb             (GimpDrawable *drawable,
+                                              gboolean      push_undo);
+void   gimp_drawable_convert_grayscale       (GimpDrawable *drawable,
+                                              gboolean      push_undo);
 
 void   gimp_drawable_convert_tiles_rgb       (GimpDrawable *drawable,
                                               TileManager  *new_tiles);
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 0be4f5c..a80a06d 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -128,7 +128,8 @@ static gint64  gimp_drawable_real_estimate_memsize (const GimpDrawable *drawable
 
 static void       gimp_drawable_real_convert_type  (GimpDrawable      *drawable,
                                                     GimpImage         *dest_image,
-                                                    GimpImageBaseType  new_base_type);
+                                                    GimpImageBaseType  new_base_type,
+                                                    gboolean           push_undo);
 
 static TileManager * gimp_drawable_real_get_tiles  (GimpDrawable      *drawable);
 static void       gimp_drawable_real_set_tiles     (GimpDrawable      *drawable,
@@ -728,18 +729,19 @@ gimp_drawable_real_estimate_memsize (const GimpDrawable *drawable,
 static void
 gimp_drawable_real_convert_type (GimpDrawable      *drawable,
                                  GimpImage         *dest_image,
-                                 GimpImageBaseType  new_base_type)
+                                 GimpImageBaseType  new_base_type,
+                                 gboolean           push_undo)
 {
   g_return_if_fail (new_base_type != GIMP_INDEXED);
 
   switch (new_base_type)
     {
     case GIMP_RGB:
-      gimp_drawable_convert_rgb (drawable);
+      gimp_drawable_convert_rgb (drawable, push_undo);
       break;
 
     case GIMP_GRAY:
-      gimp_drawable_convert_grayscale (drawable);
+      gimp_drawable_convert_grayscale (drawable, push_undo);
       break;
 
     default:
@@ -1230,7 +1232,8 @@ gimp_drawable_get_active_components (const GimpDrawable *drawable,
 void
 gimp_drawable_convert_type (GimpDrawable      *drawable,
                             GimpImage         *dest_image,
-                            GimpImageBaseType  new_base_type)
+                            GimpImageBaseType  new_base_type,
+                            gboolean           push_undo)
 {
   GimpImageType type;
 
@@ -1238,12 +1241,15 @@ gimp_drawable_convert_type (GimpDrawable      *drawable,
   g_return_if_fail (dest_image == NULL || GIMP_IS_IMAGE (dest_image));
   g_return_if_fail (new_base_type != GIMP_INDEXED || GIMP_IS_IMAGE (dest_image));
 
+  if (! gimp_item_is_attached (GIMP_ITEM (drawable)))
+    push_undo = FALSE;
+
   type = gimp_drawable_type (drawable);
 
   g_return_if_fail (new_base_type != GIMP_IMAGE_TYPE_BASE_TYPE (type));
 
   GIMP_DRAWABLE_GET_CLASS (drawable)->convert_type (drawable, dest_image,
-                                                    new_base_type);
+                                                    new_base_type, push_undo);
 }
 
 void
diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h
index 3b338ab..caeed82 100644
--- a/app/core/gimpdrawable.h
+++ b/app/core/gimpdrawable.h
@@ -65,7 +65,8 @@ struct _GimpDrawableClass
                                            gboolean             *active);
   void          (* convert_type)          (GimpDrawable         *drawable,
                                            GimpImage            *dest_image,
-                                           GimpImageBaseType     new_base_type);
+                                           GimpImageBaseType     new_base_type,
+                                           gboolean              push_undo);
   void          (* apply_region)          (GimpDrawable         *drawable,
                                            PixelRegion          *src2PR,
                                            gboolean              push_undo,
@@ -145,7 +146,8 @@ void         gimp_drawable_get_active_components (const GimpDrawable *drawable,
 
 void            gimp_drawable_convert_type       (GimpDrawable       *drawable,
                                                   GimpImage          *dest_image,
-                                                  GimpImageBaseType   new_base_type);
+                                                  GimpImageBaseType   new_base_type,
+                                                  gboolean            push_undo);
 
 void            gimp_drawable_apply_region       (GimpDrawable       *drawable,
                                                   PixelRegion        *src2PR,
diff --git a/app/core/gimpgrouplayer.c b/app/core/gimpgrouplayer.c
index 190b87f..31aba68 100644
--- a/app/core/gimpgrouplayer.c
+++ b/app/core/gimpgrouplayer.c
@@ -105,7 +105,8 @@ static gint64      gimp_group_layer_estimate_memsize (const GimpDrawable *drawab
                                                       gint             height);
 static void            gimp_group_layer_convert_type (GimpDrawable      *drawable,
                                                       GimpImage         *dest_image,
-                                                      GimpImageBaseType  new_base_type);
+                                                      GimpImageBaseType  new_base_type,
+                                                      gboolean           push_undo);
 
 static GeglNode      * gimp_group_layer_get_graph    (GimpProjectable *projectable);
 static GList         * gimp_group_layer_get_layers   (GimpProjectable *projectable);
@@ -724,12 +725,20 @@ gimp_group_layer_estimate_memsize (const GimpDrawable *drawable,
 static void
 gimp_group_layer_convert_type (GimpDrawable      *drawable,
                                GimpImage         *dest_image,
-                               GimpImageBaseType  new_base_type)
+                               GimpImageBaseType  new_base_type,
+                               gboolean           push_undo)
 {
   GimpGroupLayer *group = GIMP_GROUP_LAYER (drawable);
   TileManager    *tiles;
   GimpImageType   new_type;
 
+  if (push_undo)
+    {
+      GimpImage *image = gimp_item_get_image (GIMP_ITEM (group));
+
+      gimp_image_undo_push_group_layer_convert (image, NULL, group);
+    }
+
   new_type = GIMP_IMAGE_TYPE_FROM_BASE_TYPE (new_base_type);
 
   if (gimp_drawable_has_alpha (drawable))
diff --git a/app/core/gimpgrouplayerundo.c b/app/core/gimpgrouplayerundo.c
index 7295284..b7c199b 100644
--- a/app/core/gimpgrouplayerundo.c
+++ b/app/core/gimpgrouplayerundo.c
@@ -61,37 +61,80 @@ gimp_group_layer_undo_constructor (GType                  type,
                                    guint                  n_params,
                                    GObjectConstructParam *params)
 {
-  GObject *object;
+  GObject            *object;
+  GimpGroupLayerUndo *group_layer_undo;
+  GimpGroupLayer     *group;
 
   object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
+  group_layer_undo = GIMP_GROUP_LAYER_UNDO (object);
+
   g_assert (GIMP_IS_GROUP_LAYER (GIMP_ITEM_UNDO (object)->item));
 
+  group = GIMP_GROUP_LAYER (GIMP_ITEM_UNDO (object)->item);
+
+  switch (GIMP_UNDO (object)->undo_type)
+    {
+    case GIMP_UNDO_GROUP_LAYER_SUSPEND:
+    case GIMP_UNDO_GROUP_LAYER_RESUME:
+      break;
+
+    case GIMP_UNDO_GROUP_LAYER_CONVERT:
+      group_layer_undo->prev_type = GIMP_IMAGE_TYPE_BASE_TYPE (gimp_drawable_type (GIMP_DRAWABLE (group)));
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
   return object;
 }
 
 static void
 gimp_group_layer_undo_pop (GimpUndo            *undo,
-                          GimpUndoMode         undo_mode,
-                          GimpUndoAccumulator *accum)
+                           GimpUndoMode         undo_mode,
+                           GimpUndoAccumulator *accum)
 {
-  GimpGroupLayer *group = GIMP_GROUP_LAYER (GIMP_ITEM_UNDO (undo)->item);
+  GimpGroupLayerUndo *group_layer_undo = GIMP_GROUP_LAYER_UNDO (undo);
+  GimpGroupLayer     *group;
 
-  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
+  group = GIMP_GROUP_LAYER (GIMP_ITEM_UNDO (undo)->item);
 
-  if ((undo_mode       == GIMP_UNDO_MODE_UNDO &&
-       undo->undo_type == GIMP_UNDO_GROUP_LAYER_SUSPEND) ||
-      (undo_mode       == GIMP_UNDO_MODE_REDO &&
-       undo->undo_type == GIMP_UNDO_GROUP_LAYER_RESUME))
-    {
-      /*  resume group layer auto-resizing  */
+  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
 
-      gimp_group_layer_resume_resize (group, FALSE);
-    }
-  else
+  switch (undo->undo_type)
     {
-      /*  suspend group layer auto-resizing  */
-
-      gimp_group_layer_suspend_resize (group, FALSE);
+    case GIMP_UNDO_GROUP_LAYER_SUSPEND:
+    case GIMP_UNDO_GROUP_LAYER_RESUME:
+      if ((undo_mode       == GIMP_UNDO_MODE_UNDO &&
+           undo->undo_type == GIMP_UNDO_GROUP_LAYER_SUSPEND) ||
+          (undo_mode       == GIMP_UNDO_MODE_REDO &&
+           undo->undo_type == GIMP_UNDO_GROUP_LAYER_RESUME))
+        {
+          /*  resume group layer auto-resizing  */
+
+          gimp_group_layer_resume_resize (group, FALSE);
+        }
+      else
+        {
+          /*  suspend group layer auto-resizing  */
+
+          gimp_group_layer_suspend_resize (group, FALSE);
+        }
+      break;
+
+    case GIMP_UNDO_GROUP_LAYER_CONVERT:
+      {
+        GimpImageBaseType type;
+
+        type = GIMP_IMAGE_TYPE_BASE_TYPE (gimp_drawable_type (GIMP_DRAWABLE (group)));
+        gimp_drawable_convert_type (GIMP_DRAWABLE (group), NULL,
+                                    group_layer_undo->prev_type, FALSE);
+        group_layer_undo->prev_type = type;
+      }
+      break;
+
+    default:
+      g_assert_not_reached ();
     }
 }
diff --git a/app/core/gimpgrouplayerundo.h b/app/core/gimpgrouplayerundo.h
index f3b8168..a6a271d 100644
--- a/app/core/gimpgrouplayerundo.h
+++ b/app/core/gimpgrouplayerundo.h
@@ -34,7 +34,9 @@ typedef struct _GimpGroupLayerUndoClass GimpGroupLayerUndoClass;
 
 struct _GimpGroupLayerUndo
 {
-  GimpItemUndo   parent_instance;
+  GimpItemUndo       parent_instance;
+
+  GimpImageBaseType  prev_type;
 };
 
 struct _GimpGroupLayerUndoClass
diff --git a/app/core/gimpimage-convert.c b/app/core/gimpimage-convert.c
index 74b5daf..1671c4c 100644
--- a/app/core/gimpimage-convert.c
+++ b/app/core/gimpimage-convert.c
@@ -963,7 +963,8 @@ gimp_image_convert (GimpImage               *image,
         {
         case GIMP_RGB:
         case GIMP_GRAY:
-          gimp_drawable_convert_type (GIMP_DRAWABLE (layer), NULL, new_type);
+          gimp_drawable_convert_type (GIMP_DRAWABLE (layer), NULL, new_type,
+                                      TRUE);
           break;
 
         case GIMP_INDEXED:
diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c
index 47949bd..51a4b55 100644
--- a/app/core/gimpimage-undo-push.c
+++ b/app/core/gimpimage-undo-push.c
@@ -551,6 +551,22 @@ gimp_image_undo_push_group_layer_resume (GimpImage      *image,
                                NULL);
 }
 
+GimpUndo *
+gimp_image_undo_push_group_layer_convert (GimpImage      *image,
+                                          const gchar    *undo_desc,
+                                          GimpGroupLayer *group)
+{
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (GIMP_IS_GROUP_LAYER (group), NULL);
+  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (group)), NULL);
+
+  return gimp_image_undo_push (image, GIMP_TYPE_GROUP_LAYER_UNDO,
+                               GIMP_UNDO_GROUP_LAYER_CONVERT, undo_desc,
+                               GIMP_DIRTY_ITEM | GIMP_DIRTY_DRAWABLE,
+                               "item", group,
+                               NULL);
+}
+
 
 /**********************/
 /*  Text Layer Undos  */
diff --git a/app/core/gimpimage-undo-push.h b/app/core/gimpimage-undo-push.h
index e933e70..6c21c6a 100644
--- a/app/core/gimpimage-undo-push.h
+++ b/app/core/gimpimage-undo-push.h
@@ -136,6 +136,9 @@ GimpUndo * gimp_image_undo_push_group_layer_suspend (GimpImage      *image,
 GimpUndo * gimp_image_undo_push_group_layer_resume  (GimpImage      *image,
                                                      const gchar    *undo_desc,
                                                      GimpGroupLayer *group);
+GimpUndo * gimp_image_undo_push_group_layer_convert (GimpImage      *image,
+                                                     const gchar    *undo_desc,
+                                                     GimpGroupLayer *group);
 
 
 /*  text layer undos  */
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index a2c3e11..64d263e 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -153,7 +153,8 @@ static void    gimp_layer_get_active_components (const GimpDrawable *drawable,
                                                  gboolean           *active);
 static void    gimp_layer_convert_type          (GimpDrawable       *drawable,
                                                  GimpImage          *dest_image,
-                                                 GimpImageBaseType   new_base_type);
+                                                 GimpImageBaseType   new_base_type,
+                                                 gboolean            push_undo);
 
 static gint    gimp_layer_get_opacity_at        (GimpPickable       *pickable,
                                                  gint                x,
@@ -545,7 +546,7 @@ gimp_layer_convert (GimpItem  *item,
   new_base_type = gimp_image_base_type (dest_image);
 
   if (old_base_type != new_base_type)
-    gimp_drawable_convert_type (drawable, dest_image, new_base_type);
+    gimp_drawable_convert_type (drawable, dest_image, new_base_type, FALSE);
 
   if (layer->mask)
     gimp_item_set_image (GIMP_ITEM (layer->mask), dest_image);
@@ -858,14 +859,16 @@ gimp_layer_get_active_components (const GimpDrawable *drawable,
 static void
 gimp_layer_convert_type (GimpDrawable      *drawable,
                          GimpImage         *dest_image,
-                         GimpImageBaseType  new_base_type)
+                         GimpImageBaseType  new_base_type,
+                         gboolean           push_undo)
 {
   switch (new_base_type)
     {
     case GIMP_RGB:
     case GIMP_GRAY:
       GIMP_DRAWABLE_CLASS (parent_class)->convert_type (drawable, dest_image,
-                                                        new_base_type);
+                                                        new_base_type,
+                                                        push_undo);
       break;
 
     case GIMP_INDEXED:
@@ -900,9 +903,7 @@ gimp_layer_convert_type (GimpDrawable      *drawable,
                                     &layerPR, gimp_drawable_type (drawable),
                                     &newPR,   new_type);
 
-        gimp_drawable_set_tiles (drawable,
-                                 gimp_item_is_attached (GIMP_ITEM (drawable)),
-                                 NULL,
+        gimp_drawable_set_tiles (drawable, push_undo, NULL,
                                  new_tiles, new_type);
         tile_manager_unref (new_tiles);
       }



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