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.
This commit is contained in:
Michael Natterer 2009-09-13 19:24:19 +02:00
parent 2ac7cedbfc
commit 717b4e6a07
14 changed files with 131 additions and 43 deletions

View File

@ -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 },

View File

@ -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" >*/

View File

@ -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))

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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))

View File

@ -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;
group = GIMP_GROUP_LAYER (GIMP_ITEM_UNDO (undo)->item);
GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
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))
switch (undo->undo_type)
{
/* resume group layer auto-resizing */
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_resume_resize (group, FALSE);
}
else
{
/* suspend group layer auto-resizing */
gimp_group_layer_suspend_resize (group, FALSE);
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 ();
}
}

View File

@ -34,7 +34,9 @@ typedef struct _GimpGroupLayerUndoClass GimpGroupLayerUndoClass;
struct _GimpGroupLayerUndo
{
GimpItemUndo parent_instance;
GimpItemUndo parent_instance;
GimpImageBaseType prev_type;
};
struct _GimpGroupLayerUndoClass

View File

@ -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:

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}