Index: gimp/menus/image-menu.xml.in
===================================================================
RCS file: /cvs/gnome/gimp/menus/image-menu.xml.in,v
retrieving revision 1.40
diff -u -p -r1.40 image-menu.xml.in
--- gimp/menus/image-menu.xml.in	5 Mar 2005 00:10:40 -0000	1.40
+++ gimp/menus/image-menu.xml.in	17 Mar 2005 18:22:30 -0000
@@ -148,6 +148,7 @@
       <placeholder name="Undo">
         <menuitem action="edit-undo" />
         <menuitem action="edit-redo" />
+        <menuitem action="edit-undo-fade" />
         <menuitem action="dialogs-undo-history" />
       </placeholder>
       <separator />
Index: gimp/app/dialogs/Makefile.am
===================================================================
RCS file: /cvs/gnome/gimp/app/dialogs/Makefile.am,v
retrieving revision 1.17
diff -u -p -r1.17 Makefile.am
--- gimp/app/dialogs/Makefile.am	13 Feb 2005 15:08:04 -0000	1.17
+++ gimp/app/dialogs/Makefile.am	17 Mar 2005 18:22:30 -0000
@@ -28,6 +28,8 @@ libappdialogs_a_sources = \
 	channel-options-dialog.h	\
 	convert-dialog.c		\
 	convert-dialog.h		\
+	fade-undo-dialog.h		\
+	fade-undo-dialog.c		\
 	file-open-dialog.c		\
 	file-open-dialog.h		\
 	file-open-location-dialog.c	\
Index: gimp/app/dialogs/fade-undo-dialog.c
===================================================================
RCS file: gimp/app/dialogs/fade-undo-dialog.c
diff -N gimp/app/dialogs/fade-undo-dialog.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gimp/app/dialogs/fade-undo-dialog.c	17 Mar 2005 18:22:30 -0000
@@ -0,0 +1,233 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "dialogs-types.h"
+
+#include "base/pixel-region.h"
+
+#include "paint-funcs/paint-funcs.h"
+
+#include "core/gimpimage.h"
+#include "core/gimpimage-undo.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpdrawable-combine.h"
+#include "core/gimpchannel.h"
+#include "core/gimplayer.h"
+#include "core/gimpundo.h"
+#include "core/gimpundostack.h"
+#include "core/gimpitemundo.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "fade-undo-dialog.h"
+
+#include "gimp-intl.h"
+
+
+typedef struct _FadeUndoDialog FadeUndoDialog;
+
+struct _FadeUndoDialog
+{
+  GimpImage    *image;
+  GimpDrawable *drawable;
+  GimpDrawable *drawable2;
+  GimpChannel  *mask;
+  gdouble       opacity;
+  gint          width;
+  gint          height;
+  gchar        *undo_name;
+};
+
+static void   fade_undo_dialog_response (GtkWidget      *dialog,
+                                         gint            response_id,
+                                         FadeUndoDialog *private);
+
+static void   fade_drawable_callback    (GtkAdjustment  *adjustment,
+                                         gpointer        data);
+
+static void   fade_drawable             (FadeUndoDialog *private);
+
+
+GtkWidget *
+fade_undo_dialog_new (GimpImage      *image)
+{
+  GtkWidget      *dialog;
+  GtkWidget      *main_vbox;
+  GtkWidget      *table;
+  GtkObject      *entry;
+  FadeUndoDialog *private;
+  GimpUndo       *undo;
+  GimpDrawable   *drawable;
+  GimpItem       *item;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+
+  undo = gimp_undo_stack_peek (image->undo_stack);
+
+  if (! undo)
+    return NULL;
+
+  switch (undo->undo_type)
+    {
+    case GIMP_UNDO_PAINT:
+    case GIMP_UNDO_INK:
+      /* FIXME: how to get the drawable for a paint or ink undo? */
+      return NULL;
+      break;
+    case GIMP_UNDO_DRAWABLE:
+      item = GIMP_ITEM_UNDO (undo)->item;
+/*       if (! GIMP_IS_LAYER (item)) */
+/*         return NULL; */
+
+      drawable  = GIMP_DRAWABLE (item);
+      break;
+    default:
+      return NULL;
+      break;
+    }
+
+  private = g_new0 (FadeUndoDialog, 1);
+
+  private->undo_name = g_strdup_printf (_("Fade %s"),
+                                        gimp_object_get_name (GIMP_OBJECT (undo)));
+
+  private->drawable  = drawable;
+
+  private->image     = image;
+
+  /* get the undone drawable */
+  gimp_image_undo (image);
+  private->drawable2 = GIMP_DRAWABLE (gimp_item_duplicate (GIMP_ITEM (drawable),
+                                                           G_TYPE_FROM_INSTANCE (drawable),
+                                                           FALSE));
+  gimp_image_redo (image);
+
+  private->opacity   = 0;
+  private->width  = gimp_item_width (GIMP_ITEM (private->drawable2));
+  private->height = gimp_item_height (GIMP_ITEM (private->drawable2));
+
+  /* mask needed by gimp_drawable_replace_region */
+  private->mask = gimp_channel_new (image, private->width, private->height,
+                                    "tmp", NULL);
+  gimp_channel_all (private->mask, FALSE);
+
+  dialog = gimp_dialog_new (private->undo_name, "gimp-edit-fade", NULL, GTK_DIALOG_MODAL,
+                            gimp_standard_help_func, NULL,
+
+                            GTK_STOCK_CANCEL,  GTK_RESPONSE_CANCEL,
+                            GTK_STOCK_OK,      GTK_RESPONSE_OK,
+
+                            NULL);
+
+  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+  g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_free, private);
+
+  g_signal_connect (dialog, "response",
+                    G_CALLBACK (fade_undo_dialog_response),
+                    private);
+
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
+
+  main_vbox = gtk_vbox_new (FALSE, 12);
+  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
+  gtk_widget_show (main_vbox);
+
+  table = gtk_table_new (1, 3, FALSE);
+  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
+  gtk_widget_show (table);
+
+  entry = gimp_scale_entry_new (GTK_TABLE (table), 0, 0, _("Opacity"), 50, 4,
+                                100, 0, 100, 1, 10, 0, TRUE, FALSE, FALSE,
+                                _("Strength of effect"), NULL);
+
+  g_signal_connect (entry, "value_changed",
+                    G_CALLBACK (fade_drawable_callback),
+                    private);
+
+  fade_drawable (private);
+
+  return dialog;
+}
+
+static void
+fade_undo_dialog_response (GtkWidget      *dialog,
+                           gint            response_id,
+                           FadeUndoDialog *private)
+{
+  switch (response_id)
+    {
+    case GTK_RESPONSE_OK:
+      /* just leave as is */
+      break;
+
+    default: /* cancel */
+      gimp_image_undo (private->image);
+      gimp_image_flush (private->image);
+      break;
+    }
+
+  g_object_unref (private->drawable2);
+  g_object_unref (private->mask);
+  g_free (private->undo_name);
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+fade_drawable_callback (GtkAdjustment *adjustment,
+                        gpointer       data)
+{
+  FadeUndoDialog *private = data;
+
+  private->opacity = 1 - 0.01 * gtk_adjustment_get_value (adjustment);
+
+  gimp_image_undo (private->image);
+  fade_drawable (private);
+}
+
+static void
+fade_drawable (FadeUndoDialog  *private)
+{
+  PixelRegion   srcPR;
+  PixelRegion   maskPR;
+
+  pixel_region_init (&srcPR, gimp_drawable_data (private->drawable2), 0, 0,
+                     private->width, private->height, FALSE);
+
+  pixel_region_init (&maskPR,
+                     gimp_drawable_data (GIMP_DRAWABLE (private->mask)),
+                     0, 0, private->width, private->height, TRUE);
+
+  gimp_drawable_replace_region (private->drawable, &srcPR,
+                                TRUE, private->undo_name,
+                                private->opacity, &maskPR, 0, 0);
+
+  gimp_image_flush (private->image);
+}
Index: gimp/app/dialogs/fade-undo-dialog.h
===================================================================
RCS file: gimp/app/dialogs/fade-undo-dialog.h
diff -N gimp/app/dialogs/fade-undo-dialog.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gimp/app/dialogs/fade-undo-dialog.h	17 Mar 2005 18:22:30 -0000
@@ -0,0 +1,29 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __FADE_UNDO_DIALOG_H__
+#define __FADE_UNDO_DIALOG_H__
+
+
+typedef void (* GimpFadeUndoCallback) (GtkWidget             *dialog,
+                                       GimpDrawable          *drawable,
+                                       gdouble                opacity);
+
+GtkWidget * fade_undo_dialog_new (GimpImage          *gimage);
+
+#endif  /*  __FADE_UNDO_DIALOG_H__  */
Index: gimp/app/actions/edit-actions.c
===================================================================
RCS file: /cvs/gnome/gimp/app/actions/edit-actions.c,v
retrieving revision 1.19
diff -u -p -r1.19 edit-actions.c
--- gimp/app/actions/edit-actions.c	12 Dec 2004 14:01:07 -0000	1.19
+++ gimp/app/actions/edit-actions.c	17 Mar 2005 18:22:30 -0000
@@ -79,6 +79,12 @@ static GimpActionEntry edit_actions[] =
     G_CALLBACK (edit_undo_clear_cmd_callback),
     GIMP_HELP_EDIT_UNDO_CLEAR },
 
+  { "edit-undo-fade", GTK_STOCK_UNDO,
+    N_("_Fade"), "",
+    N_("Fade last action..."),
+    G_CALLBACK (edit_undo_fade_cmd_callback),
+    GIMP_HELP_EDIT_UNDO },
+
   { "edit-cut", GTK_STOCK_CUT,
     N_("Cu_t"), "<control>X", NULL,
     G_CALLBACK (edit_cut_cmd_callback),
@@ -193,8 +199,9 @@ edit_actions_update (GimpActionGroup *gr
   GimpDrawable *drawable     = NULL;
   gchar        *undo_name    = NULL;
   gchar        *redo_name    = NULL;
+  gchar        *fade_name    = NULL;
   gboolean      undo_enabled = FALSE;
-
+  gboolean      fade_enabled = FALSE;
   if (gimage)
     {
       GimpUndo *undo;
@@ -218,6 +225,14 @@ edit_actions_update (GimpActionGroup *gr
             redo_name =
               g_strdup_printf (_("_Redo %s"),
                                gimp_object_get_name (GIMP_OBJECT (redo)));
+
+          if (undo)
+            fade_enabled = (undo->undo_type == GIMP_UNDO_DRAWABLE);
+
+          if (fade_enabled)
+            fade_name =
+              g_strdup_printf (_("_Fade %s"),
+                               gimp_object_get_name (GIMP_OBJECT (undo)));
         }
     }
 
@@ -227,12 +242,14 @@ edit_actions_update (GimpActionGroup *gr
 #define SET_SENSITIVE(action,condition) \
         gimp_action_group_set_action_sensitive (group, action, (condition) != 0)
 
-  SET_LABEL ("edit-undo", undo_name ? undo_name : _("_Undo"));
-  SET_LABEL ("edit-redo", redo_name ? redo_name : _("_Redo"));
+  SET_LABEL ("edit-undo",      undo_name ? undo_name : _("_Undo"));
+  SET_LABEL ("edit-redo",      redo_name ? redo_name : _("_Redo"));
+  SET_LABEL ("edit-undo-fade", fade_name ? fade_name : _("_Fade"));
 
   SET_SENSITIVE ("edit-undo",       undo_enabled && undo_name);
   SET_SENSITIVE ("edit-redo",       undo_enabled && redo_name);
   SET_SENSITIVE ("edit-undo-clear", undo_enabled && (undo_name || redo_name));
+  SET_SENSITIVE ("edit-undo-fade",  fade_enabled && fade_name);
 
   g_free (undo_name);
   g_free (redo_name);
Index: gimp/app/actions/edit-commands.c
===================================================================
RCS file: /cvs/gnome/gimp/app/actions/edit-commands.c,v
retrieving revision 1.59
diff -u -p -r1.59 edit-commands.c
--- gimp/app/actions/edit-commands.c	10 Feb 2005 11:00:44 -0000	1.59
+++ gimp/app/actions/edit-commands.c	17 Mar 2005 18:22:30 -0000
@@ -45,6 +45,7 @@
 #include "widgets/gimpmessagedialog.h"
 
 #include "dialogs/dialogs.h"
+#include "dialogs/fade-undo-dialog.h"
 
 #include "actions.h"
 #include "edit-commands.h"
@@ -127,6 +128,27 @@ edit_undo_clear_cmd_callback (GtkAction 
                                      _("Really clear image's undo history?"));
 
   gtk_widget_show (dialog);
+}
+
+void
+edit_undo_fade_cmd_callback (GtkAction *action,
+                             gpointer   data)
+{
+  GimpImage *gimage;
+  GtkWidget *dialog;
+
+  return_if_no_image (gimage, data);
+
+  dialog = fade_undo_dialog_new (gimage);
+
+  if (dialog)
+    {
+      g_signal_connect_object (gimage, "disconnect",
+                               G_CALLBACK (gtk_widget_destroy),
+                               dialog, G_CONNECT_SWAPPED);
+
+      gtk_widget_show (dialog);
+    }
 }
 
 void
Index: gimp/app/actions/edit-commands.h
===================================================================
RCS file: /cvs/gnome/gimp/app/actions/edit-commands.h,v
retrieving revision 1.8
diff -u -p -r1.8 edit-commands.h
--- gimp/app/actions/edit-commands.h	12 Dec 2004 14:01:07 -0000	1.8
+++ gimp/app/actions/edit-commands.h	17 Mar 2005 18:22:30 -0000
@@ -26,6 +26,8 @@ void   edit_redo_cmd_callback         (G
                                        gpointer   data);
 void   edit_undo_clear_cmd_callback   (GtkAction *action,
                                        gpointer   data);
+void   edit_undo_fade_cmd_callback    (GtkAction *action,
+                                       gpointer   data);
 void   edit_cut_cmd_callback          (GtkAction *action,
                                        gpointer   data);
 void   edit_copy_cmd_callback         (GtkAction *action,
