mirror of https://github.com/GNOME/gimp.git
Honest, guv, it's not a feature - it's a tightly integrated package of
Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org> Honest, guv, it's not a feature - it's a tightly integrated package of undo system cleanups and fixes. NEW FILES: * app/undo_history.c: window showing recent undo (and redo) steps available. * app/undo_types.h: broken out of undo.h to fix circular includes. MODIFIED FILES: * app/Makefile.am: compile undo_history.c * app/channel.h: use enum for channel undo type, not just magic numbers. * app/layer.h: same for layer undos. * app/commands.c: edit_show_undo_history_cmd_callback() function to pull up undo history window. * app/commands.h: prototype for above. * app/gdisplay.c: make undo / redo menu items sensitive according to whether they would do anything. Would be easy to change the text to say what would be undone/redone, but I don't know the GTK. * app/gimpimage.c: new signal emitted by gimage: UNDO_EVENT. gimp_image_undo_event() function to emit it. * app/gimpimage.h: prototype for above. * app/gimpimageP.h: pushing_undo_group member is now an undo_type, not an int. Keep undo history widget here too (if created). * app/menus.c: add "Edit/Undo history..." to image menu. * app/undo.c: new types: enums undo_type and undo_state rather than ints and magic numbers. All undo_pop_* and undo_free_* functions made static. New static function undo_type_to_name(). Issue undo event signals on various important events (eg undo pushed, undo popped etc). undo_push() now takes a "dirties_image" arg to say whether image should be dirtied. Layer moves now dirty the image. A couple of g_return_if_fails () on undo_pop and undo_redo to assert we're not in the middle of an undo group. undo_get_{undo,redo}_name() to peek at names of top items on undo and redo stacks resp. undo_map_over_{undo,redo}_stack() to run a function for each item or group on stack. Layer and channel undos use symbolic names rather than 0 or 1. Array mapping undo types to names. * app/undo.h: split out undo types to undo_types.h. Prototypes for functions described above. undo_event_t enum. undo_history_new() prototype lives here too. Random other fixes: * app/gimpdrawable.c * app/image_render.c: default labels in switches to keep egcs happy. * app/nav_window.c: some fixes to (sort of) cope with image res != screen res. Still needs work to handle non-square pixels properly. * app/paths_dialog.c: bad idea to call gimp_image_dirty() directly. Even though it's currently commented out.
This commit is contained in:
parent
dae8fd9d6d
commit
bf8db4adc8
57
ChangeLog
57
ChangeLog
|
@ -1,3 +1,60 @@
|
|||
Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org>
|
||||
|
||||
Honest, guv, it's not a feature - it's a tightly integrated
|
||||
package of undo system cleanups and fixes.
|
||||
|
||||
NEW FILES:
|
||||
* app/undo_history.c: window showing recent undo (and redo) steps
|
||||
available.
|
||||
* app/undo_types.h: broken out of undo.h to fix circular includes.
|
||||
|
||||
MODIFIED FILES:
|
||||
* app/Makefile.am: compile undo_history.c
|
||||
* app/channel.h: use enum for channel undo type, not just magic
|
||||
numbers.
|
||||
* app/layer.h: same for layer undos.
|
||||
* app/commands.c: edit_show_undo_history_cmd_callback() function to
|
||||
pull up undo history window.
|
||||
* app/commands.h: prototype for above.
|
||||
* app/gdisplay.c: make undo / redo menu items sensitive according
|
||||
to whether they would do anything. Would be easy to change
|
||||
the text to say what would be undone/redone, but I don't know
|
||||
the GTK.
|
||||
* app/gimpimage.c: new signal emitted by gimage:
|
||||
UNDO_EVENT. gimp_image_undo_event() function to emit it.
|
||||
* app/gimpimage.h: prototype for above.
|
||||
* app/gimpimageP.h: pushing_undo_group member is now an undo_type,
|
||||
not an int. Keep undo history widget here too (if created).
|
||||
* app/menus.c: add "Edit/Undo history..." to image menu.
|
||||
* app/undo.c: new types: enums undo_type and undo_state rather than
|
||||
ints and magic numbers. All undo_pop_* and undo_free_*
|
||||
functions made static. New static function
|
||||
undo_type_to_name(). Issue undo event signals on various
|
||||
important events (eg undo pushed, undo popped etc).
|
||||
undo_push() now takes a "dirties_image" arg to say whether
|
||||
image should be dirtied. Layer moves now dirty the image. A
|
||||
couple of g_return_if_fails () on undo_pop and undo_redo to
|
||||
assert we're not in the middle of an undo group.
|
||||
undo_get_{undo,redo}_name() to peek at names of top items on
|
||||
undo and redo stacks resp. undo_map_over_{undo,redo}_stack()
|
||||
to run a function for each item or group on stack. Layer and
|
||||
channel undos use symbolic names rather than 0 or 1. Array
|
||||
mapping undo types to names.
|
||||
* app/undo.h: split out undo types to undo_types.h. Prototypes
|
||||
for functions described above. undo_event_t enum.
|
||||
undo_history_new() prototype lives here too.
|
||||
|
||||
Random other fixes:
|
||||
* app/gimpdrawable.c
|
||||
* app/image_render.c: default labels in switches to keep egcs happy.
|
||||
|
||||
* app/nav_window.c: some fixes to (sort of) cope with image res !=
|
||||
screen res. Still needs work to handle non-square pixels
|
||||
properly.
|
||||
|
||||
* app/paths_dialog.c: bad idea to call gimp_image_dirty()
|
||||
directly. Even though it's currently commented out.
|
||||
|
||||
Mon Sep 20 18:23:18 1999 ape@gandalf.spacetec.no (Asbjorn Pettersen)
|
||||
|
||||
* configure.in: Add app/unittest/Makefile
|
||||
|
|
|
@ -418,6 +418,7 @@ gimp_SOURCES = \
|
|||
undo.c \
|
||||
undo.h \
|
||||
undo_cmds.c \
|
||||
undo_history.c \
|
||||
unitrc.h \
|
||||
unit_cmds.c \
|
||||
wilber.h \
|
||||
|
|
|
@ -236,6 +236,25 @@ edit_redo_cmd_callback (GtkWidget *widget,
|
|||
undo_redo (gdisp->gimage);
|
||||
}
|
||||
|
||||
void
|
||||
edit_show_undo_history_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
GDisplay * gdisp;
|
||||
GImage * gimage;
|
||||
return_if_no_display (gdisp);
|
||||
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
if (!gimage->undo_history)
|
||||
gimage->undo_history = undo_history_new (gimage);
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (gimage->undo_history))
|
||||
gtk_widget_show (gimage->undo_history);
|
||||
else
|
||||
gdk_window_raise (gimage->undo_history->window);
|
||||
}
|
||||
|
||||
void
|
||||
edit_named_cut_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
|
|
|
@ -22,6 +22,7 @@ void edit_fill_cmd_callback (GtkWidget *, gpointer);
|
|||
void edit_stroke_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_undo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_redo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_show_undo_history_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_cut_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_copy_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_paste_cmd_callback (GtkWidget *, gpointer);
|
||||
|
|
|
@ -48,16 +48,22 @@ typedef enum
|
|||
|
||||
GtkType gimp_channel_get_type (void);
|
||||
|
||||
typedef enum {
|
||||
CHANNEL_ADD_UNDO,
|
||||
CHANNEL_REMOVE_UNDO
|
||||
} channel_undo_type;
|
||||
|
||||
|
||||
/* Special undo type */
|
||||
typedef struct _ChannelUndo ChannelUndo;
|
||||
|
||||
struct _ChannelUndo
|
||||
{
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
gint undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
channel_undo_type undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
};
|
||||
|
||||
/* Special undo type */
|
||||
|
|
|
@ -236,6 +236,25 @@ edit_redo_cmd_callback (GtkWidget *widget,
|
|||
undo_redo (gdisp->gimage);
|
||||
}
|
||||
|
||||
void
|
||||
edit_show_undo_history_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
GDisplay * gdisp;
|
||||
GImage * gimage;
|
||||
return_if_no_display (gdisp);
|
||||
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
if (!gimage->undo_history)
|
||||
gimage->undo_history = undo_history_new (gimage);
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (gimage->undo_history))
|
||||
gtk_widget_show (gimage->undo_history);
|
||||
else
|
||||
gdk_window_raise (gimage->undo_history->window);
|
||||
}
|
||||
|
||||
void
|
||||
edit_named_cut_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
|
|
|
@ -22,6 +22,7 @@ void edit_fill_cmd_callback (GtkWidget *, gpointer);
|
|||
void edit_stroke_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_undo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_redo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_show_undo_history_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_cut_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_copy_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_paste_cmd_callback (GtkWidget *, gpointer);
|
||||
|
|
|
@ -48,16 +48,22 @@ typedef enum
|
|||
|
||||
GtkType gimp_channel_get_type (void);
|
||||
|
||||
typedef enum {
|
||||
CHANNEL_ADD_UNDO,
|
||||
CHANNEL_REMOVE_UNDO
|
||||
} channel_undo_type;
|
||||
|
||||
|
||||
/* Special undo type */
|
||||
typedef struct _ChannelUndo ChannelUndo;
|
||||
|
||||
struct _ChannelUndo
|
||||
{
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
gint undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
channel_undo_type undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
};
|
||||
|
||||
/* Special undo type */
|
||||
|
|
|
@ -48,16 +48,22 @@ typedef enum
|
|||
|
||||
GtkType gimp_channel_get_type (void);
|
||||
|
||||
typedef enum {
|
||||
CHANNEL_ADD_UNDO,
|
||||
CHANNEL_REMOVE_UNDO
|
||||
} channel_undo_type;
|
||||
|
||||
|
||||
/* Special undo type */
|
||||
typedef struct _ChannelUndo ChannelUndo;
|
||||
|
||||
struct _ChannelUndo
|
||||
{
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
gint undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
channel_undo_type undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
};
|
||||
|
||||
/* Special undo type */
|
||||
|
|
|
@ -309,6 +309,9 @@ gimp_drawable_type_with_alpha (GimpDrawable *drawable)
|
|||
return GRAYA_GIMAGE; break;
|
||||
case INDEXED_GIMAGE:
|
||||
return INDEXEDA_GIMAGE; break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,49 +18,15 @@
|
|||
#ifndef __UNDO_H__
|
||||
#define __UNDO_H__
|
||||
|
||||
|
||||
#include "undo_types.h"
|
||||
|
||||
#include "gimage.h"
|
||||
|
||||
/* Undo types */
|
||||
#define IMAGE_UNDO 1
|
||||
#define IMAGE_MOD_UNDO 2
|
||||
#define MASK_UNDO 3
|
||||
#define LAYER_DISPLACE_UNDO 4
|
||||
#define TRANSFORM_UNDO 5
|
||||
#define PAINT_UNDO 6
|
||||
#define LAYER_UNDO 7
|
||||
#define LAYER_MOD 8
|
||||
#define LAYER_MASK_UNDO 9
|
||||
#define LAYER_CHANGE 10
|
||||
#define LAYER_POSITION 11
|
||||
#define CHANNEL_UNDO 12
|
||||
#define CHANNEL_MOD 13
|
||||
#define FS_TO_LAYER_UNDO 14
|
||||
#define GIMAGE_MOD 15
|
||||
#define FS_RIGOR 16
|
||||
#define FS_RELAX 17
|
||||
#define GUIDE_UNDO 18
|
||||
|
||||
/* Aggregate undo types */
|
||||
#define FLOAT_MASK_UNDO 20
|
||||
#define EDIT_PASTE_UNDO 21
|
||||
#define EDIT_CUT_UNDO 22
|
||||
#define TRANSFORM_CORE_UNDO 23
|
||||
#define PAINT_CORE_UNDO 24
|
||||
#define FLOATING_LAYER_UNDO 25
|
||||
#define LINKED_LAYER_UNDO 26
|
||||
#define LAYER_APPLY_MASK_UNDO 27
|
||||
#define LAYER_MERGE_UNDO 28
|
||||
#define FS_ANCHOR_UNDO 29
|
||||
#define GIMAGE_MOD_UNDO 30
|
||||
#define CROP_UNDO 31
|
||||
#define LAYER_SCALE_UNDO 32
|
||||
#define LAYER_RESIZE_UNDO 33
|
||||
#define QMASK_UNDO 34
|
||||
#define MISC_UNDO 100
|
||||
|
||||
/* Undo interface functions */
|
||||
|
||||
int undo_push_group_start (GImage *, int);
|
||||
int undo_push_group_start (GImage *, undo_type);
|
||||
int undo_push_group_end (GImage *);
|
||||
int undo_push_image (GImage *, GimpDrawable *, int, int, int, int);
|
||||
int undo_push_image_mod (GImage *, GimpDrawable *, int, int, int, int, void *, int);
|
||||
|
@ -93,5 +59,28 @@ int undo_pop (GImage *);
|
|||
int undo_redo (GImage *);
|
||||
void undo_free (GImage *);
|
||||
|
||||
const char *undo_get_undo_name (GImage *);
|
||||
const char *undo_get_redo_name (GImage *);
|
||||
|
||||
/* Stack peeking functions */
|
||||
typedef int (*undo_map_fn) (const char *undoitemname, void *data);
|
||||
void undo_map_over_undo_stack (GImage *, undo_map_fn, void *data);
|
||||
void undo_map_over_redo_stack (GImage *, undo_map_fn, void *data);
|
||||
|
||||
|
||||
/* Not really appropriate here, since undo_history_new is not defined
|
||||
* in undo.c, but it saves on having a full header file for just one
|
||||
* function prototype. */
|
||||
GtkWidget *undo_history_new (GImage *gimage);
|
||||
|
||||
|
||||
/* Argument to undo_event signal emitted by gimages: */
|
||||
typedef enum {
|
||||
UNDO_PUSHED, /* a new undo has been added to the undo stack */
|
||||
UNDO_EXPIRED, /* an undo has been freed from the undo stack */
|
||||
UNDO_POPPED, /* an undo has been executed and moved to redo stack */
|
||||
UNDO_REDO, /* a redo has been executed and moved to undo stack */
|
||||
UNDO_FREE /* all undo and redo info has been cleared */
|
||||
} undo_event_t;
|
||||
|
||||
#endif /* __UNDO_H__ */
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -46,25 +46,30 @@ GtkType gimp_layer_mask_get_type (void);
|
|||
|
||||
/* Special undo types */
|
||||
|
||||
typedef enum {
|
||||
LAYER_ADD_UNDO = 0,
|
||||
LAYER_REMOVE_UNDO = 1
|
||||
} layer_undo_type;
|
||||
|
||||
struct _layer_undo
|
||||
{
|
||||
Layer *layer; /* the actual layer */
|
||||
gint prev_position; /* former position in list */
|
||||
Layer *prev_layer; /* previous active layer */
|
||||
gint undo_type; /* is this a new layer undo *
|
||||
* or a remove layer undo? */
|
||||
Layer *layer; /* the actual layer */
|
||||
gint prev_position; /* former position in list */
|
||||
Layer *prev_layer; /* previous active layer */
|
||||
layer_undo_type undo_type; /* is this a new layer undo *
|
||||
* or a remove layer undo? */
|
||||
};
|
||||
|
||||
struct _layer_mask_undo
|
||||
{
|
||||
Layer *layer; /* the layer */
|
||||
gboolean apply_mask; /* apply mask? */
|
||||
gboolean edit_mask; /* edit mask or layer? */
|
||||
gboolean show_mask; /* show the mask? */
|
||||
LayerMask *mask; /* the layer mask */
|
||||
gint mode; /* the application mode */
|
||||
gint undo_type; /* is this a new layer mask */
|
||||
/* or a remove layer mask */
|
||||
Layer *layer; /* the layer */
|
||||
gboolean apply_mask; /* apply mask? */
|
||||
gboolean edit_mask; /* edit mask or layer? */
|
||||
gboolean show_mask; /* show the mask? */
|
||||
LayerMask *mask; /* the layer mask */
|
||||
gint mode; /* the application mode */
|
||||
layer_undo_type undo_type; /* is this a new layer mask */
|
||||
/* or a remove layer mask */
|
||||
};
|
||||
|
||||
struct _fs_to_layer_undo
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -1645,6 +1645,8 @@ gdisplay_set_menu_sensitivity (GDisplay *gdisp)
|
|||
SET_SENSITIVE (N_("/Edit/Clear"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Fill"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Stroke"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Undo"), undo_get_undo_name (gdisp->gimage));
|
||||
SET_SENSITIVE (N_("/Edit/Redo"), undo_get_redo_name (gdisp->gimage));
|
||||
SET_SENSITIVE (N_("/Edit/Cut Named"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Copy Named"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Paste Named"), lp);
|
||||
|
|
|
@ -744,6 +744,9 @@ render_image_init_info (RenderInfo *info,
|
|||
case INDEXEDA_GIMAGE:
|
||||
info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
|
||||
break;
|
||||
default:
|
||||
/* nothing special needs doing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1645,6 +1645,8 @@ gdisplay_set_menu_sensitivity (GDisplay *gdisp)
|
|||
SET_SENSITIVE (N_("/Edit/Clear"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Fill"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Stroke"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Undo"), undo_get_undo_name (gdisp->gimage));
|
||||
SET_SENSITIVE (N_("/Edit/Redo"), undo_get_redo_name (gdisp->gimage));
|
||||
SET_SENSITIVE (N_("/Edit/Cut Named"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Copy Named"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Paste Named"), lp);
|
||||
|
|
|
@ -744,6 +744,9 @@ render_image_init_info (RenderInfo *info,
|
|||
case INDEXEDA_GIMAGE:
|
||||
info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
|
||||
break;
|
||||
default:
|
||||
/* nothing special needs doing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,18 +167,20 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp)
|
|||
GimpImage *gimage;
|
||||
gint newwidth;
|
||||
gint newheight;
|
||||
gdouble ratio; /* Screen res ratio */
|
||||
gdouble xratio;
|
||||
gdouble yratio; /* Screen res ratio */
|
||||
gboolean need_update = FALSE;
|
||||
|
||||
/* Calculate preview size */
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
xratio = SCALEFACTOR_X(gdisp);
|
||||
yratio = SCALEFACTOR_Y(gdisp);
|
||||
|
||||
iwd->dispx = gdisp->offset_x*iwd->ratio/ratio;
|
||||
iwd->dispy = gdisp->offset_y*iwd->ratio/ratio;
|
||||
iwd->dispwidth = (gdisp->disp_width*iwd->ratio)/ratio;
|
||||
iwd->dispheight = (gdisp->disp_height*iwd->ratio)/ratio;
|
||||
iwd->dispx = gdisp->offset_x*iwd->ratio/xratio;
|
||||
iwd->dispy = gdisp->offset_y*iwd->ratio/yratio;
|
||||
iwd->dispwidth = (gdisp->disp_width*iwd->ratio)/xratio;
|
||||
iwd->dispheight = (gdisp->disp_height*iwd->ratio)/yratio;
|
||||
|
||||
newwidth = gimage->width;
|
||||
newheight = gimage->height;
|
||||
|
@ -315,13 +317,10 @@ create_preview_widget(NavWinData *iwd)
|
|||
GtkWidget *hbox;
|
||||
GtkWidget *image;
|
||||
GtkWidget *frame;
|
||||
gdouble ratio;
|
||||
GDisplay *gdisp;
|
||||
|
||||
gdisp = (GDisplay *)(iwd->gdisp_ptr);
|
||||
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
|
||||
hbox = gtk_hbox_new(FALSE,0);
|
||||
iwd->previewBox = hbox;
|
||||
gtk_widget_show(hbox);
|
||||
|
@ -369,14 +368,17 @@ static void
|
|||
update_real_view(NavWinData *iwd,gint tx,gint ty)
|
||||
{
|
||||
GDisplay *gdisp;
|
||||
gdouble ratio;
|
||||
gdouble xratio;
|
||||
gdouble yratio;
|
||||
gint xoffset;
|
||||
gint yoffset;
|
||||
gint xpnt;
|
||||
gint ypnt;
|
||||
|
||||
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
|
||||
xratio = SCALEFACTOR_X(gdisp);
|
||||
yratio = SCALEFACTOR_Y(gdisp);
|
||||
|
||||
if((tx + iwd->dispwidth) >= iwd->pwidth)
|
||||
{
|
||||
|
@ -385,12 +387,12 @@ update_real_view(NavWinData *iwd,gint tx,gint ty)
|
|||
*/
|
||||
}
|
||||
|
||||
xpnt = (gint)(((gdouble)(tx)*ratio)/iwd->ratio);
|
||||
xpnt = (gint)(((gdouble)(tx)*xratio)/iwd->ratio);
|
||||
|
||||
if((ty + iwd->dispheight) >= iwd->pheight)
|
||||
ty = iwd->pheight; /* Same comment as for xpnt above. */
|
||||
|
||||
ypnt = (gint)(((gdouble)(ty)*ratio)/iwd->ratio);
|
||||
ypnt = (gint)(((gdouble)(ty)*yratio)/iwd->ratio);
|
||||
|
||||
xoffset = xpnt - gdisp->offset_x;
|
||||
yoffset = ypnt - gdisp->offset_y;
|
||||
|
|
|
@ -167,18 +167,20 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp)
|
|||
GimpImage *gimage;
|
||||
gint newwidth;
|
||||
gint newheight;
|
||||
gdouble ratio; /* Screen res ratio */
|
||||
gdouble xratio;
|
||||
gdouble yratio; /* Screen res ratio */
|
||||
gboolean need_update = FALSE;
|
||||
|
||||
/* Calculate preview size */
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
xratio = SCALEFACTOR_X(gdisp);
|
||||
yratio = SCALEFACTOR_Y(gdisp);
|
||||
|
||||
iwd->dispx = gdisp->offset_x*iwd->ratio/ratio;
|
||||
iwd->dispy = gdisp->offset_y*iwd->ratio/ratio;
|
||||
iwd->dispwidth = (gdisp->disp_width*iwd->ratio)/ratio;
|
||||
iwd->dispheight = (gdisp->disp_height*iwd->ratio)/ratio;
|
||||
iwd->dispx = gdisp->offset_x*iwd->ratio/xratio;
|
||||
iwd->dispy = gdisp->offset_y*iwd->ratio/yratio;
|
||||
iwd->dispwidth = (gdisp->disp_width*iwd->ratio)/xratio;
|
||||
iwd->dispheight = (gdisp->disp_height*iwd->ratio)/yratio;
|
||||
|
||||
newwidth = gimage->width;
|
||||
newheight = gimage->height;
|
||||
|
@ -315,13 +317,10 @@ create_preview_widget(NavWinData *iwd)
|
|||
GtkWidget *hbox;
|
||||
GtkWidget *image;
|
||||
GtkWidget *frame;
|
||||
gdouble ratio;
|
||||
GDisplay *gdisp;
|
||||
|
||||
gdisp = (GDisplay *)(iwd->gdisp_ptr);
|
||||
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
|
||||
hbox = gtk_hbox_new(FALSE,0);
|
||||
iwd->previewBox = hbox;
|
||||
gtk_widget_show(hbox);
|
||||
|
@ -369,14 +368,17 @@ static void
|
|||
update_real_view(NavWinData *iwd,gint tx,gint ty)
|
||||
{
|
||||
GDisplay *gdisp;
|
||||
gdouble ratio;
|
||||
gdouble xratio;
|
||||
gdouble yratio;
|
||||
gint xoffset;
|
||||
gint yoffset;
|
||||
gint xpnt;
|
||||
gint ypnt;
|
||||
|
||||
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
|
||||
xratio = SCALEFACTOR_X(gdisp);
|
||||
yratio = SCALEFACTOR_Y(gdisp);
|
||||
|
||||
if((tx + iwd->dispwidth) >= iwd->pwidth)
|
||||
{
|
||||
|
@ -385,12 +387,12 @@ update_real_view(NavWinData *iwd,gint tx,gint ty)
|
|||
*/
|
||||
}
|
||||
|
||||
xpnt = (gint)(((gdouble)(tx)*ratio)/iwd->ratio);
|
||||
xpnt = (gint)(((gdouble)(tx)*xratio)/iwd->ratio);
|
||||
|
||||
if((ty + iwd->dispheight) >= iwd->pheight)
|
||||
ty = iwd->pheight; /* Same comment as for xpnt above. */
|
||||
|
||||
ypnt = (gint)(((gdouble)(ty)*ratio)/iwd->ratio);
|
||||
ypnt = (gint)(((gdouble)(ty)*yratio)/iwd->ratio);
|
||||
|
||||
xoffset = xpnt - gdisp->offset_x;
|
||||
yoffset = ypnt - gdisp->offset_y;
|
||||
|
|
|
@ -1645,6 +1645,8 @@ gdisplay_set_menu_sensitivity (GDisplay *gdisp)
|
|||
SET_SENSITIVE (N_("/Edit/Clear"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Fill"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Stroke"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Undo"), undo_get_undo_name (gdisp->gimage));
|
||||
SET_SENSITIVE (N_("/Edit/Redo"), undo_get_redo_name (gdisp->gimage));
|
||||
SET_SENSITIVE (N_("/Edit/Cut Named"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Copy Named"), lp);
|
||||
SET_SENSITIVE (N_("/Edit/Paste Named"), lp);
|
||||
|
|
|
@ -48,16 +48,22 @@ typedef enum
|
|||
|
||||
GtkType gimp_channel_get_type (void);
|
||||
|
||||
typedef enum {
|
||||
CHANNEL_ADD_UNDO,
|
||||
CHANNEL_REMOVE_UNDO
|
||||
} channel_undo_type;
|
||||
|
||||
|
||||
/* Special undo type */
|
||||
typedef struct _ChannelUndo ChannelUndo;
|
||||
|
||||
struct _ChannelUndo
|
||||
{
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
gint undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
Channel *channel; /* the actual channel */
|
||||
gint prev_position; /* former position in list */
|
||||
Channel *prev_channel; /* previous active channel */
|
||||
channel_undo_type undo_type; /* is this a new channel undo */
|
||||
/* or a remove channel undo? */
|
||||
};
|
||||
|
||||
/* Special undo type */
|
||||
|
|
|
@ -309,6 +309,9 @@ gimp_drawable_type_with_alpha (GimpDrawable *drawable)
|
|||
return GRAYA_GIMAGE; break;
|
||||
case INDEXED_GIMAGE:
|
||||
return INDEXEDA_GIMAGE; break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ enum {
|
|||
RESIZE,
|
||||
RESTRUCTURE,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -140,6 +141,9 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
gimp_image_signals[COLORMAP_CHANGED] =
|
||||
gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
gimp_image_signals[UNDO_EVENT] =
|
||||
gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
|
||||
gimp_sigtype_int);
|
||||
|
||||
gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
@ -3359,6 +3363,12 @@ gimp_image_enable_undo (GimpImage *gimage)
|
|||
return gimp_image_thaw_undo (gimage);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_image_undo_event (GimpImage *gimage, int event)
|
||||
{
|
||||
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[UNDO_EVENT], event);
|
||||
}
|
||||
|
||||
|
||||
/* NOTE about the gimage->dirty counter:
|
||||
* If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
|
|
|
@ -249,6 +249,7 @@ gboolean gimp_image_enable_undo (GimpImage *);
|
|||
gboolean gimp_image_disable_undo (GimpImage *);
|
||||
gboolean gimp_image_freeze_undo (GimpImage *);
|
||||
gboolean gimp_image_thaw_undo (GimpImage *);
|
||||
void gimp_image_undo_event (GimpImage *, int);
|
||||
gint gimp_image_dirty (GimpImage *);
|
||||
gint gimp_image_clean (GimpImage *);
|
||||
void gimp_image_clean_all (GimpImage *);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "layer.h"
|
||||
#include "parasitelistF.h"
|
||||
#include "pathsP.h"
|
||||
#include "undo_types.h"
|
||||
|
||||
|
||||
#define MAX_CHANNELS 4
|
||||
|
@ -98,7 +99,8 @@ struct _GimpImage
|
|||
gint undo_bytes; /* bytes in undo stack */
|
||||
gint undo_levels; /* levels in undo stack */
|
||||
gint group_count; /* nested undo groups */
|
||||
gint pushing_undo_group; /* undo group status flag */
|
||||
undo_type pushing_undo_group; /* undo group status flag */
|
||||
GtkWidget *undo_history; /* history viewer, or NULL */
|
||||
|
||||
/* Composite preview */
|
||||
TempBuf *comp_preview; /* the composite preview */
|
||||
|
|
|
@ -46,25 +46,30 @@ GtkType gimp_layer_mask_get_type (void);
|
|||
|
||||
/* Special undo types */
|
||||
|
||||
typedef enum {
|
||||
LAYER_ADD_UNDO = 0,
|
||||
LAYER_REMOVE_UNDO = 1
|
||||
} layer_undo_type;
|
||||
|
||||
struct _layer_undo
|
||||
{
|
||||
Layer *layer; /* the actual layer */
|
||||
gint prev_position; /* former position in list */
|
||||
Layer *prev_layer; /* previous active layer */
|
||||
gint undo_type; /* is this a new layer undo *
|
||||
* or a remove layer undo? */
|
||||
Layer *layer; /* the actual layer */
|
||||
gint prev_position; /* former position in list */
|
||||
Layer *prev_layer; /* previous active layer */
|
||||
layer_undo_type undo_type; /* is this a new layer undo *
|
||||
* or a remove layer undo? */
|
||||
};
|
||||
|
||||
struct _layer_mask_undo
|
||||
{
|
||||
Layer *layer; /* the layer */
|
||||
gboolean apply_mask; /* apply mask? */
|
||||
gboolean edit_mask; /* edit mask or layer? */
|
||||
gboolean show_mask; /* show the mask? */
|
||||
LayerMask *mask; /* the layer mask */
|
||||
gint mode; /* the application mode */
|
||||
gint undo_type; /* is this a new layer mask */
|
||||
/* or a remove layer mask */
|
||||
Layer *layer; /* the layer */
|
||||
gboolean apply_mask; /* apply mask? */
|
||||
gboolean edit_mask; /* edit mask or layer? */
|
||||
gboolean show_mask; /* show the mask? */
|
||||
LayerMask *mask; /* the layer mask */
|
||||
gint mode; /* the application mode */
|
||||
layer_undo_type undo_type; /* is this a new layer mask */
|
||||
/* or a remove layer mask */
|
||||
};
|
||||
|
||||
struct _fs_to_layer_undo
|
||||
|
|
|
@ -236,6 +236,25 @@ edit_redo_cmd_callback (GtkWidget *widget,
|
|||
undo_redo (gdisp->gimage);
|
||||
}
|
||||
|
||||
void
|
||||
edit_show_undo_history_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
GDisplay * gdisp;
|
||||
GImage * gimage;
|
||||
return_if_no_display (gdisp);
|
||||
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
if (!gimage->undo_history)
|
||||
gimage->undo_history = undo_history_new (gimage);
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (gimage->undo_history))
|
||||
gtk_widget_show (gimage->undo_history);
|
||||
else
|
||||
gdk_window_raise (gimage->undo_history->window);
|
||||
}
|
||||
|
||||
void
|
||||
edit_named_cut_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
|
|
|
@ -22,6 +22,7 @@ void edit_fill_cmd_callback (GtkWidget *, gpointer);
|
|||
void edit_stroke_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_undo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_redo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_show_undo_history_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_cut_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_copy_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_paste_cmd_callback (GtkWidget *, gpointer);
|
||||
|
|
|
@ -236,6 +236,25 @@ edit_redo_cmd_callback (GtkWidget *widget,
|
|||
undo_redo (gdisp->gimage);
|
||||
}
|
||||
|
||||
void
|
||||
edit_show_undo_history_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
GDisplay * gdisp;
|
||||
GImage * gimage;
|
||||
return_if_no_display (gdisp);
|
||||
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
if (!gimage->undo_history)
|
||||
gimage->undo_history = undo_history_new (gimage);
|
||||
|
||||
if (!GTK_WIDGET_VISIBLE (gimage->undo_history))
|
||||
gtk_widget_show (gimage->undo_history);
|
||||
else
|
||||
gdk_window_raise (gimage->undo_history->window);
|
||||
}
|
||||
|
||||
void
|
||||
edit_named_cut_cmd_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
|
|
|
@ -22,6 +22,7 @@ void edit_fill_cmd_callback (GtkWidget *, gpointer);
|
|||
void edit_stroke_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_undo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_redo_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_show_undo_history_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_cut_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_copy_cmd_callback (GtkWidget *, gpointer);
|
||||
void edit_named_paste_cmd_callback (GtkWidget *, gpointer);
|
||||
|
|
|
@ -123,6 +123,7 @@ static GtkItemFactoryEntry image_entries[] =
|
|||
{ N_("/Edit/Stroke"), NULL, edit_stroke_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo"), "<control>Z", edit_undo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Redo"), "<control>R", edit_redo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo history..."), NULL, edit_show_undo_history_cmd_callback, 0},
|
||||
{ N_("/Edit/---"), NULL, NULL, 0, "<Separator>" },
|
||||
{ N_("/Edit/Cut Named"), "<control><shift>X", edit_named_cut_cmd_callback, 0 },
|
||||
{ N_("/Edit/Copy Named"), "<control><shift>C", edit_named_copy_cmd_callback, 0 },
|
||||
|
|
|
@ -2015,7 +2015,7 @@ paths_first_button_press(BezierSelect *bezier_sel,GDisplay * gdisp)
|
|||
plp = (PATHIMAGELISTP)gimp_image_get_paths(gdisp->gimage);
|
||||
|
||||
/* Since beziers are part of the save format.. make the image dirty */
|
||||
/* gimp_image_dirty(gdisp->gimage); */
|
||||
/* undo_push_cantundo(gdisp->gimage, _("path modification")); */
|
||||
|
||||
if(!paths_replaced_current(plp,bezier_sel))
|
||||
{
|
||||
|
|
|
@ -744,6 +744,9 @@ render_image_init_info (RenderInfo *info,
|
|||
case INDEXEDA_GIMAGE:
|
||||
info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
|
||||
break;
|
||||
default:
|
||||
/* nothing special needs doing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
31
app/layer.h
31
app/layer.h
|
@ -46,25 +46,30 @@ GtkType gimp_layer_mask_get_type (void);
|
|||
|
||||
/* Special undo types */
|
||||
|
||||
typedef enum {
|
||||
LAYER_ADD_UNDO = 0,
|
||||
LAYER_REMOVE_UNDO = 1
|
||||
} layer_undo_type;
|
||||
|
||||
struct _layer_undo
|
||||
{
|
||||
Layer *layer; /* the actual layer */
|
||||
gint prev_position; /* former position in list */
|
||||
Layer *prev_layer; /* previous active layer */
|
||||
gint undo_type; /* is this a new layer undo *
|
||||
* or a remove layer undo? */
|
||||
Layer *layer; /* the actual layer */
|
||||
gint prev_position; /* former position in list */
|
||||
Layer *prev_layer; /* previous active layer */
|
||||
layer_undo_type undo_type; /* is this a new layer undo *
|
||||
* or a remove layer undo? */
|
||||
};
|
||||
|
||||
struct _layer_mask_undo
|
||||
{
|
||||
Layer *layer; /* the layer */
|
||||
gboolean apply_mask; /* apply mask? */
|
||||
gboolean edit_mask; /* edit mask or layer? */
|
||||
gboolean show_mask; /* show the mask? */
|
||||
LayerMask *mask; /* the layer mask */
|
||||
gint mode; /* the application mode */
|
||||
gint undo_type; /* is this a new layer mask */
|
||||
/* or a remove layer mask */
|
||||
Layer *layer; /* the layer */
|
||||
gboolean apply_mask; /* apply mask? */
|
||||
gboolean edit_mask; /* edit mask or layer? */
|
||||
gboolean show_mask; /* show the mask? */
|
||||
LayerMask *mask; /* the layer mask */
|
||||
gint mode; /* the application mode */
|
||||
layer_undo_type undo_type; /* is this a new layer mask */
|
||||
/* or a remove layer mask */
|
||||
};
|
||||
|
||||
struct _fs_to_layer_undo
|
||||
|
|
|
@ -123,6 +123,7 @@ static GtkItemFactoryEntry image_entries[] =
|
|||
{ N_("/Edit/Stroke"), NULL, edit_stroke_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo"), "<control>Z", edit_undo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Redo"), "<control>R", edit_redo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo history..."), NULL, edit_show_undo_history_cmd_callback, 0},
|
||||
{ N_("/Edit/---"), NULL, NULL, 0, "<Separator>" },
|
||||
{ N_("/Edit/Cut Named"), "<control><shift>X", edit_named_cut_cmd_callback, 0 },
|
||||
{ N_("/Edit/Copy Named"), "<control><shift>C", edit_named_copy_cmd_callback, 0 },
|
||||
|
|
|
@ -123,6 +123,7 @@ static GtkItemFactoryEntry image_entries[] =
|
|||
{ N_("/Edit/Stroke"), NULL, edit_stroke_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo"), "<control>Z", edit_undo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Redo"), "<control>R", edit_redo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo history..."), NULL, edit_show_undo_history_cmd_callback, 0},
|
||||
{ N_("/Edit/---"), NULL, NULL, 0, "<Separator>" },
|
||||
{ N_("/Edit/Cut Named"), "<control><shift>X", edit_named_cut_cmd_callback, 0 },
|
||||
{ N_("/Edit/Copy Named"), "<control><shift>C", edit_named_copy_cmd_callback, 0 },
|
||||
|
|
|
@ -167,18 +167,20 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp)
|
|||
GimpImage *gimage;
|
||||
gint newwidth;
|
||||
gint newheight;
|
||||
gdouble ratio; /* Screen res ratio */
|
||||
gdouble xratio;
|
||||
gdouble yratio; /* Screen res ratio */
|
||||
gboolean need_update = FALSE;
|
||||
|
||||
/* Calculate preview size */
|
||||
gimage = gdisp->gimage;
|
||||
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
xratio = SCALEFACTOR_X(gdisp);
|
||||
yratio = SCALEFACTOR_Y(gdisp);
|
||||
|
||||
iwd->dispx = gdisp->offset_x*iwd->ratio/ratio;
|
||||
iwd->dispy = gdisp->offset_y*iwd->ratio/ratio;
|
||||
iwd->dispwidth = (gdisp->disp_width*iwd->ratio)/ratio;
|
||||
iwd->dispheight = (gdisp->disp_height*iwd->ratio)/ratio;
|
||||
iwd->dispx = gdisp->offset_x*iwd->ratio/xratio;
|
||||
iwd->dispy = gdisp->offset_y*iwd->ratio/yratio;
|
||||
iwd->dispwidth = (gdisp->disp_width*iwd->ratio)/xratio;
|
||||
iwd->dispheight = (gdisp->disp_height*iwd->ratio)/yratio;
|
||||
|
||||
newwidth = gimage->width;
|
||||
newheight = gimage->height;
|
||||
|
@ -315,13 +317,10 @@ create_preview_widget(NavWinData *iwd)
|
|||
GtkWidget *hbox;
|
||||
GtkWidget *image;
|
||||
GtkWidget *frame;
|
||||
gdouble ratio;
|
||||
GDisplay *gdisp;
|
||||
|
||||
gdisp = (GDisplay *)(iwd->gdisp_ptr);
|
||||
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
|
||||
hbox = gtk_hbox_new(FALSE,0);
|
||||
iwd->previewBox = hbox;
|
||||
gtk_widget_show(hbox);
|
||||
|
@ -369,14 +368,17 @@ static void
|
|||
update_real_view(NavWinData *iwd,gint tx,gint ty)
|
||||
{
|
||||
GDisplay *gdisp;
|
||||
gdouble ratio;
|
||||
gdouble xratio;
|
||||
gdouble yratio;
|
||||
gint xoffset;
|
||||
gint yoffset;
|
||||
gint xpnt;
|
||||
gint ypnt;
|
||||
|
||||
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
||||
ratio = ((gdouble)SCALEDEST(gdisp))/((gdouble)SCALESRC(gdisp));
|
||||
|
||||
xratio = SCALEFACTOR_X(gdisp);
|
||||
yratio = SCALEFACTOR_Y(gdisp);
|
||||
|
||||
if((tx + iwd->dispwidth) >= iwd->pwidth)
|
||||
{
|
||||
|
@ -385,12 +387,12 @@ update_real_view(NavWinData *iwd,gint tx,gint ty)
|
|||
*/
|
||||
}
|
||||
|
||||
xpnt = (gint)(((gdouble)(tx)*ratio)/iwd->ratio);
|
||||
xpnt = (gint)(((gdouble)(tx)*xratio)/iwd->ratio);
|
||||
|
||||
if((ty + iwd->dispheight) >= iwd->pheight)
|
||||
ty = iwd->pheight; /* Same comment as for xpnt above. */
|
||||
|
||||
ypnt = (gint)(((gdouble)(ty)*ratio)/iwd->ratio);
|
||||
ypnt = (gint)(((gdouble)(ty)*yratio)/iwd->ratio);
|
||||
|
||||
xoffset = xpnt - gdisp->offset_x;
|
||||
yoffset = ypnt - gdisp->offset_y;
|
||||
|
|
|
@ -2015,7 +2015,7 @@ paths_first_button_press(BezierSelect *bezier_sel,GDisplay * gdisp)
|
|||
plp = (PATHIMAGELISTP)gimp_image_get_paths(gdisp->gimage);
|
||||
|
||||
/* Since beziers are part of the save format.. make the image dirty */
|
||||
/* gimp_image_dirty(gdisp->gimage); */
|
||||
/* undo_push_cantundo(gdisp->gimage, _("path modification")); */
|
||||
|
||||
if(!paths_replaced_current(plp,bezier_sel))
|
||||
{
|
||||
|
|
812
app/undo.c
812
app/undo.c
File diff suppressed because it is too large
Load Diff
65
app/undo.h
65
app/undo.h
|
@ -18,49 +18,15 @@
|
|||
#ifndef __UNDO_H__
|
||||
#define __UNDO_H__
|
||||
|
||||
|
||||
#include "undo_types.h"
|
||||
|
||||
#include "gimage.h"
|
||||
|
||||
/* Undo types */
|
||||
#define IMAGE_UNDO 1
|
||||
#define IMAGE_MOD_UNDO 2
|
||||
#define MASK_UNDO 3
|
||||
#define LAYER_DISPLACE_UNDO 4
|
||||
#define TRANSFORM_UNDO 5
|
||||
#define PAINT_UNDO 6
|
||||
#define LAYER_UNDO 7
|
||||
#define LAYER_MOD 8
|
||||
#define LAYER_MASK_UNDO 9
|
||||
#define LAYER_CHANGE 10
|
||||
#define LAYER_POSITION 11
|
||||
#define CHANNEL_UNDO 12
|
||||
#define CHANNEL_MOD 13
|
||||
#define FS_TO_LAYER_UNDO 14
|
||||
#define GIMAGE_MOD 15
|
||||
#define FS_RIGOR 16
|
||||
#define FS_RELAX 17
|
||||
#define GUIDE_UNDO 18
|
||||
|
||||
/* Aggregate undo types */
|
||||
#define FLOAT_MASK_UNDO 20
|
||||
#define EDIT_PASTE_UNDO 21
|
||||
#define EDIT_CUT_UNDO 22
|
||||
#define TRANSFORM_CORE_UNDO 23
|
||||
#define PAINT_CORE_UNDO 24
|
||||
#define FLOATING_LAYER_UNDO 25
|
||||
#define LINKED_LAYER_UNDO 26
|
||||
#define LAYER_APPLY_MASK_UNDO 27
|
||||
#define LAYER_MERGE_UNDO 28
|
||||
#define FS_ANCHOR_UNDO 29
|
||||
#define GIMAGE_MOD_UNDO 30
|
||||
#define CROP_UNDO 31
|
||||
#define LAYER_SCALE_UNDO 32
|
||||
#define LAYER_RESIZE_UNDO 33
|
||||
#define QMASK_UNDO 34
|
||||
#define MISC_UNDO 100
|
||||
|
||||
/* Undo interface functions */
|
||||
|
||||
int undo_push_group_start (GImage *, int);
|
||||
int undo_push_group_start (GImage *, undo_type);
|
||||
int undo_push_group_end (GImage *);
|
||||
int undo_push_image (GImage *, GimpDrawable *, int, int, int, int);
|
||||
int undo_push_image_mod (GImage *, GimpDrawable *, int, int, int, int, void *, int);
|
||||
|
@ -93,5 +59,28 @@ int undo_pop (GImage *);
|
|||
int undo_redo (GImage *);
|
||||
void undo_free (GImage *);
|
||||
|
||||
const char *undo_get_undo_name (GImage *);
|
||||
const char *undo_get_redo_name (GImage *);
|
||||
|
||||
/* Stack peeking functions */
|
||||
typedef int (*undo_map_fn) (const char *undoitemname, void *data);
|
||||
void undo_map_over_undo_stack (GImage *, undo_map_fn, void *data);
|
||||
void undo_map_over_redo_stack (GImage *, undo_map_fn, void *data);
|
||||
|
||||
|
||||
/* Not really appropriate here, since undo_history_new is not defined
|
||||
* in undo.c, but it saves on having a full header file for just one
|
||||
* function prototype. */
|
||||
GtkWidget *undo_history_new (GImage *gimage);
|
||||
|
||||
|
||||
/* Argument to undo_event signal emitted by gimages: */
|
||||
typedef enum {
|
||||
UNDO_PUSHED, /* a new undo has been added to the undo stack */
|
||||
UNDO_EXPIRED, /* an undo has been freed from the undo stack */
|
||||
UNDO_POPPED, /* an undo has been executed and moved to redo stack */
|
||||
UNDO_REDO, /* a redo has been executed and moved to undo stack */
|
||||
UNDO_FREE /* all undo and redo info has been cleared */
|
||||
} undo_event_t;
|
||||
|
||||
#endif /* __UNDO_H__ */
|
||||
|
|
|
@ -0,0 +1,522 @@
|
|||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995-1999 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.
|
||||
*
|
||||
* Undo history browser by Austin Donnelly <austin@gimp.org>
|
||||
*/
|
||||
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* - previews of the image on each line (reuse the L&C previews?)
|
||||
*
|
||||
* - work out which (if any) is the clean image, and mark it as such
|
||||
* (eg floppy disk icon) Currently, its a "*" and it's on the
|
||||
* wrong line.
|
||||
*
|
||||
* - scroll to keep current selection visible. Can some GTK guru
|
||||
* help out?
|
||||
*
|
||||
* - window looks butt-ugly. As usual, my (lack) of graphic design
|
||||
* skills are showing through. Someone please prettify it!
|
||||
*
|
||||
* - undo names are less than useful. This isn't a problem with
|
||||
* undo_history.c itself, more with the rather chaotic way
|
||||
* people have of picking an undo type when pushing undos, and
|
||||
* inconsistent use of undo groups. Maybe rather than
|
||||
* specifying an (enum) type, it should be a const char * ?
|
||||
*
|
||||
* BUGS:
|
||||
* - clean star in wrong place
|
||||
* - window title not updated on image title change
|
||||
*
|
||||
* Initial rev 0.01, (c) 19 Sept 1999 Austin Donnelly <austin@gimp.org>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "undo.h"
|
||||
#include "actionarea.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
GImage *gimage; /* image we're tracking undo info for */
|
||||
GtkWidget *shell; /* dialog window */
|
||||
GtkWidget *clist; /* list of undo actions */
|
||||
GtkWidget *undo_button; /* button to undo an operation */
|
||||
GtkWidget *redo_button; /* button to redo an operation */
|
||||
int old_selection; /* previous selection in the clist */
|
||||
} undo_history_st;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Theory of operation.
|
||||
*
|
||||
* Keep a clist. Each row of the clist corresponds to an image as it
|
||||
* was at some time in the past, present or future. The selected row
|
||||
* is the present image. Rows below the selected one are in the
|
||||
* future - as redo operations are performed, they become the current
|
||||
* image. Rows above the selected one are in the past - undo
|
||||
* operations move the highlight up.
|
||||
*
|
||||
* The slight fly in the ointment is that if rows are images, then how
|
||||
* should they be labelled? An undo or redo operation goes _between_
|
||||
* two image states - it isn't an image state. It's a pretty
|
||||
* arbitrary decision, but I've chosen to label a row with the name of
|
||||
* the action that brought the image into the state represented by
|
||||
* that row. Thus, there is a special first row without a meaningful
|
||||
* label, which represents the image state before the first action has
|
||||
* been done to it. The choice is between a special first row or a
|
||||
* special last row. Since people mostly work near the leading edge,
|
||||
* not often going all the way back, I've chosen to put the special
|
||||
* case out of common sight.
|
||||
*
|
||||
* So, the undo stack contents appear above the selected row, and the
|
||||
* redo stack below it.
|
||||
*
|
||||
* The clist is initialised by mapping over the undo and redo stack.
|
||||
*
|
||||
* Once initialised, the dialog listens to undo_event signals from the
|
||||
* gimage. These undo events allow us to track changes to the undo
|
||||
* and redo stacks. We follow the events, making parallel changes to
|
||||
* the clist. If we ever get out of sync, there is no mechanism to
|
||||
* notice or re-sync. A few g_return_if_fails should catch some of
|
||||
* these cases.
|
||||
*
|
||||
* User clicks changing the selected row in the clist turn into
|
||||
* multiple calls to undo_pop or undo_redo, with appropriate signals
|
||||
* blocked so we don't get our own events back.
|
||||
*
|
||||
* The "Close" button hides the dialog, rather than destroying it.
|
||||
* This may well need to be changed, since the dialog will continue to
|
||||
* track updates, and if it's generating previews this might take too
|
||||
* long for large images.
|
||||
*
|
||||
* The dialog is destroyed when the gimage it is tracking is
|
||||
* destroyed. Note that a File/Revert destroys the current gimage and
|
||||
* so blows the undo/redo stacks.
|
||||
*
|
||||
* --austin, 19/9/1999
|
||||
*/
|
||||
|
||||
|
||||
/**************************************************************/
|
||||
/* Local functions */
|
||||
|
||||
|
||||
/* close button clicked */
|
||||
static void
|
||||
undo_history_close_callback (GtkWidget *w,
|
||||
gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
gtk_widget_hide (GTK_WIDGET (st->shell));
|
||||
}
|
||||
|
||||
/* WM_DELETE */
|
||||
static gint
|
||||
undo_history_delete_callback (GtkWidget *w,
|
||||
GdkEvent *e,
|
||||
gpointer data)
|
||||
{
|
||||
undo_history_close_callback (w, data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static ActionAreaItem action_items[] =
|
||||
{
|
||||
{ N_("Close"), undo_history_close_callback, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* The gimage and shell destroy callbacks are split so we can:
|
||||
* a) blow the shell when the image dissappears
|
||||
* b) disconnect from the image if the shell dissappears (we don't
|
||||
* want signals from the image to carry on using "st" once it's
|
||||
* been freed.
|
||||
*/
|
||||
|
||||
/* gimage destroyed */
|
||||
static void
|
||||
undo_history_gimage_destroy_callback (GtkWidget *w, gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
|
||||
st->gimage = NULL; /* not allowed to use this any more */
|
||||
gtk_widget_destroy (GTK_WIDGET (st->shell));
|
||||
/* which continues in the function below: */
|
||||
}
|
||||
|
||||
static void
|
||||
undo_history_shell_destroy_callback (GtkWidget *w, gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
|
||||
if (st->gimage)
|
||||
gtk_signal_disconnect_by_data (GTK_OBJECT (st->gimage), st);
|
||||
g_free (st);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* undo button clicked */
|
||||
static void
|
||||
undo_history_undo_callback (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
|
||||
undo_pop (st->gimage);
|
||||
}
|
||||
|
||||
/* redo button clicked */
|
||||
static void
|
||||
undo_history_redo_callback (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
|
||||
undo_redo (st->gimage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Always start clist with dummy entry for image state before
|
||||
* the first action on the undo stack */
|
||||
static void
|
||||
undo_history_append_special (GtkCList *clist)
|
||||
{
|
||||
char *name = _("[ base image ]");
|
||||
char *namelist[] = { NULL, name };
|
||||
|
||||
gtk_clist_append (clist, namelist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Recalculate which of the undo and redo buttons are meant to be sensitive */
|
||||
static void
|
||||
undo_history_set_sensitive (undo_history_st *st, int rows)
|
||||
{
|
||||
gtk_widget_set_sensitive (st->undo_button, (st->old_selection != 0));
|
||||
gtk_widget_set_sensitive (st->redo_button, (st->old_selection != rows-1));
|
||||
}
|
||||
|
||||
|
||||
/* Track undo_event signals, telling us of changes to the undo and
|
||||
* redo stacks. */
|
||||
static void
|
||||
undo_history_undo_event (GtkWidget *widget, int ev, gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
undo_event_t event = ev;
|
||||
const char *name;
|
||||
char *namelist[2];
|
||||
GList *list;
|
||||
int cur_selection;
|
||||
GtkCList *clist;
|
||||
|
||||
list = GTK_CLIST(st->clist)->selection;
|
||||
g_return_if_fail (list != NULL);
|
||||
cur_selection = GPOINTER_TO_INT (list->data);
|
||||
|
||||
clist = GTK_CLIST (st->clist);
|
||||
|
||||
/* block select events */
|
||||
gtk_signal_handler_block_by_data (GTK_OBJECT (st->clist), st);
|
||||
|
||||
switch (event) {
|
||||
case UNDO_PUSHED:
|
||||
/* clip everything after the current selection (ie, the
|
||||
* actions that are from the redo stack) */
|
||||
gtk_clist_freeze (clist);
|
||||
while (clist->rows > cur_selection + 1)
|
||||
gtk_clist_remove (clist, cur_selection + 1);
|
||||
|
||||
/* find out what's new */
|
||||
name = undo_get_undo_name (st->gimage);
|
||||
namelist[0] = NULL;
|
||||
namelist[1] = (char *) name;
|
||||
gtk_clist_append (clist, namelist);
|
||||
|
||||
g_assert (clist->rows == cur_selection+2);
|
||||
|
||||
/* always force selection to bottom, and scroll to it */
|
||||
gtk_clist_select_row (clist, clist->rows-1, -1);
|
||||
gtk_clist_moveto (clist, clist->rows-1, 0, 1.0, 0.0);
|
||||
gtk_clist_thaw (clist);
|
||||
cur_selection = clist->rows-1;
|
||||
break;
|
||||
|
||||
|
||||
case UNDO_EXPIRED:
|
||||
/* remove earliest row, but not our special first one */
|
||||
gtk_clist_remove (clist, 1);
|
||||
break;
|
||||
|
||||
|
||||
case UNDO_POPPED:
|
||||
/* move hilight up one */
|
||||
g_return_if_fail (cur_selection >= 1);
|
||||
gtk_clist_select_row (clist, cur_selection-1, -1);
|
||||
cur_selection--;
|
||||
break;
|
||||
|
||||
|
||||
case UNDO_REDO:
|
||||
/* move hilight down one */
|
||||
g_return_if_fail (cur_selection+1 < clist->rows);
|
||||
gtk_clist_select_row (clist, cur_selection+1, -1);
|
||||
cur_selection++;
|
||||
break;
|
||||
|
||||
|
||||
case UNDO_FREE:
|
||||
/* clear all info other that the special first line */
|
||||
gtk_clist_freeze (clist);
|
||||
gtk_clist_clear (clist);
|
||||
undo_history_append_special (clist);
|
||||
gtk_clist_thaw (clist);
|
||||
cur_selection = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_signal_handler_unblock_by_data (GTK_OBJECT (st->clist), st);
|
||||
|
||||
st->old_selection = cur_selection;
|
||||
undo_history_set_sensitive (st, clist->rows);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
undo_history_select_row_callback (GtkWidget *w,
|
||||
gint row, gint column, gpointer event,
|
||||
gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
int cur_selection;
|
||||
|
||||
cur_selection = row;
|
||||
|
||||
if (cur_selection == st->old_selection)
|
||||
return;
|
||||
|
||||
/* Disable undo_event signals while we do these multiple undo or
|
||||
* redo actions. */
|
||||
gtk_signal_handler_block_by_func (GTK_OBJECT (st->gimage),
|
||||
undo_history_undo_event, st);
|
||||
|
||||
while (cur_selection < st->old_selection)
|
||||
{
|
||||
undo_pop (st->gimage);
|
||||
st->old_selection--;
|
||||
}
|
||||
while (cur_selection > st->old_selection)
|
||||
{
|
||||
undo_redo (st->gimage);
|
||||
st->old_selection++;
|
||||
}
|
||||
|
||||
gtk_signal_handler_unblock_by_func (GTK_OBJECT (st->gimage),
|
||||
undo_history_undo_event, st);
|
||||
|
||||
undo_history_set_sensitive (st, GTK_CLIST(st->clist)->rows);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
undo_history_clean_callback (GtkWidget *w, gpointer data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
int i;
|
||||
int nrows;
|
||||
GtkCList *clist;
|
||||
|
||||
if (st->gimage->dirty != 0)
|
||||
return;
|
||||
|
||||
/* The image is clean, so this is the version on disc. Remove the
|
||||
* clean star from all other entries, and add it to the current
|
||||
* one. */
|
||||
|
||||
/* XXX currently broken, since "clean" signal is emitted before
|
||||
* UNDO_POPPED event. I don't want to change the order of the
|
||||
* signals. So I'm a little stuck. --austin */
|
||||
|
||||
clist = GTK_CLIST (st->clist);
|
||||
nrows = clist->rows;
|
||||
|
||||
gtk_clist_freeze (clist);
|
||||
for (i=0; i < nrows; i++)
|
||||
gtk_clist_set_text (clist, i, 0, NULL);
|
||||
gtk_clist_set_text (clist, st->old_selection, 0, "*");
|
||||
gtk_clist_thaw (clist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Used to build up initial contents of clist */
|
||||
static int
|
||||
undo_history_init_undo (const char *undoitemname, void *data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
char *namelist[2];
|
||||
|
||||
namelist[0] = NULL;
|
||||
namelist[1] = (char *) undoitemname;
|
||||
gtk_clist_append (GTK_CLIST (st->clist), namelist);
|
||||
|
||||
/* force selection to bottom */
|
||||
gtk_clist_select_row (GTK_CLIST (st->clist),
|
||||
GTK_CLIST (st->clist)->rows - 1, -1);
|
||||
st->old_selection = GTK_CLIST(st->clist)->rows - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ditto, but doesn't change selection */
|
||||
static int
|
||||
undo_history_init_redo (const char *undoitemname, void *data)
|
||||
{
|
||||
undo_history_st *st = data;
|
||||
char *namelist[2];
|
||||
|
||||
namelist[0] = NULL;
|
||||
namelist[1] = (char *) undoitemname;
|
||||
gtk_clist_append (GTK_CLIST (st->clist), namelist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************/
|
||||
/* Publicly exported function */
|
||||
|
||||
GtkWidget *
|
||||
undo_history_new (GImage *gimage)
|
||||
{
|
||||
undo_history_st *st;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
GtkWidget *scrolled_win;
|
||||
|
||||
st = g_new0 (undo_history_st, 1);
|
||||
st->gimage = gimage;
|
||||
|
||||
/* gimage signals */
|
||||
gtk_signal_connect (GTK_OBJECT (gimage), "undo_event",
|
||||
undo_history_undo_event, st);
|
||||
gtk_signal_connect (GTK_OBJECT (gimage), "destroy",
|
||||
undo_history_gimage_destroy_callback, st);
|
||||
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
|
||||
undo_history_clean_callback, st);
|
||||
|
||||
/* The shell and main vbox */
|
||||
st->shell = gtk_dialog_new ();
|
||||
|
||||
gtk_window_set_wmclass (GTK_WINDOW (st->shell), "undohistory", "Gimp");
|
||||
gtk_window_set_policy (GTK_WINDOW (st->shell), FALSE, TRUE, FALSE);
|
||||
|
||||
{
|
||||
char *title = g_strdup_printf (_("%s: undo history"),
|
||||
g_basename (gimage_filename (gimage)));
|
||||
gtk_window_set_title (GTK_WINDOW (st->shell), title);
|
||||
g_free (title);
|
||||
}
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 1);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 1);
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (st->shell)->vbox),
|
||||
vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
/* handle the wm close event */
|
||||
gtk_signal_connect (GTK_OBJECT (st->shell), "delete_event",
|
||||
GTK_SIGNAL_FUNC (undo_history_delete_callback), st);
|
||||
gtk_signal_connect (GTK_OBJECT (st->shell), "destroy",
|
||||
GTK_SIGNAL_FUNC (undo_history_shell_destroy_callback),
|
||||
st);
|
||||
|
||||
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
|
||||
|
||||
/* clist of undo actions */
|
||||
st->clist = gtk_clist_new (2);
|
||||
gtk_clist_set_shadow_type (GTK_CLIST (st->clist), GTK_SHADOW_IN);
|
||||
gtk_clist_set_selection_mode (GTK_CLIST (st->clist), GTK_SELECTION_BROWSE);
|
||||
gtk_clist_set_reorderable (GTK_CLIST (st->clist), FALSE);
|
||||
gtk_clist_set_column_width (GTK_CLIST (st->clist), 0, 52);
|
||||
undo_history_append_special (GTK_CLIST (st->clist));
|
||||
|
||||
/* work out the initial contents */
|
||||
undo_map_over_undo_stack (st->gimage, undo_history_init_undo, st);
|
||||
undo_map_over_redo_stack (st->gimage, undo_history_init_redo, st);
|
||||
|
||||
st->old_selection = GPOINTER_TO_INT(GTK_CLIST(st->clist)->selection->data);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (st->clist), "select_row",
|
||||
undo_history_select_row_callback, st);
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (st->clist));
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
|
||||
gtk_widget_show (GTK_WIDGET (scrolled_win));
|
||||
gtk_container_add (GTK_CONTAINER (scrolled_win), st->clist);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_ALWAYS);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 8);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
button = gtk_button_new_with_label (_("<< Undo"));
|
||||
st->undo_button = button;
|
||||
gtk_widget_show (GTK_WIDGET (button));
|
||||
gtk_signal_connect (GTK_OBJECT (button), "clicked",
|
||||
undo_history_undo_callback, st);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
||||
|
||||
button = gtk_button_new_with_label (_("Redo >>"));
|
||||
st->redo_button = button;
|
||||
gtk_widget_show (GTK_WIDGET (button));
|
||||
gtk_signal_connect (GTK_OBJECT (button), "clicked",
|
||||
undo_history_redo_callback, st);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
||||
|
||||
action_items[0].user_data = st;
|
||||
build_action_area (GTK_DIALOG (st->shell), action_items, 1, 0);
|
||||
|
||||
undo_history_set_sensitive (st, GTK_CLIST (st->clist)->rows);
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (st->shell));
|
||||
|
||||
return st->shell;
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/* 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 __UNDO_TYPES_H__
|
||||
#define __UNDO_TYPES_H__
|
||||
|
||||
|
||||
/* Undo types */
|
||||
typedef enum {
|
||||
/* Type 0 is special - in the gimpimage structure it means
|
||||
* there is no undo group currently being added to. */
|
||||
IMAGE_UNDO = 1,
|
||||
IMAGE_MOD_UNDO,
|
||||
MASK_UNDO,
|
||||
LAYER_DISPLACE_UNDO,
|
||||
TRANSFORM_UNDO,
|
||||
PAINT_UNDO,
|
||||
LAYER_UNDO,
|
||||
LAYER_MOD,
|
||||
LAYER_MASK_UNDO,
|
||||
LAYER_CHANGE,
|
||||
LAYER_POSITION,
|
||||
CHANNEL_UNDO,
|
||||
CHANNEL_MOD,
|
||||
FS_TO_LAYER_UNDO,
|
||||
GIMAGE_MOD,
|
||||
FS_RIGOR,
|
||||
FS_RELAX,
|
||||
GUIDE_UNDO, /* 18 */
|
||||
|
||||
/* Aggregate undo types */
|
||||
FLOAT_MASK_UNDO = 20,
|
||||
EDIT_PASTE_UNDO,
|
||||
EDIT_CUT_UNDO,
|
||||
TRANSFORM_CORE_UNDO,
|
||||
|
||||
PAINT_CORE_UNDO,
|
||||
FLOATING_LAYER_UNDO,
|
||||
LINKED_LAYER_UNDO,
|
||||
LAYER_APPLY_MASK_UNDO,
|
||||
LAYER_MERGE_UNDO, /* 28 */
|
||||
FS_ANCHOR_UNDO,
|
||||
GIMAGE_MOD_UNDO,
|
||||
CROP_UNDO,
|
||||
LAYER_SCALE_UNDO,
|
||||
LAYER_RESIZE_UNDO,
|
||||
QMASK_UNDO, /* 34 */
|
||||
|
||||
MISC_UNDO = 100
|
||||
} undo_type;
|
||||
|
||||
|
||||
#endif /* __UNDO_TYPES_H__ */
|
|
@ -123,6 +123,7 @@ static GtkItemFactoryEntry image_entries[] =
|
|||
{ N_("/Edit/Stroke"), NULL, edit_stroke_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo"), "<control>Z", edit_undo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Redo"), "<control>R", edit_redo_cmd_callback, 0 },
|
||||
{ N_("/Edit/Undo history..."), NULL, edit_show_undo_history_cmd_callback, 0},
|
||||
{ N_("/Edit/---"), NULL, NULL, 0, "<Separator>" },
|
||||
{ N_("/Edit/Cut Named"), "<control><shift>X", edit_named_cut_cmd_callback, 0 },
|
||||
{ N_("/Edit/Copy Named"), "<control><shift>C", edit_named_copy_cmd_callback, 0 },
|
||||
|
|
Loading…
Reference in New Issue