Reimplemented the undo history:
2003-02-20 Michael Natterer <mitch@gimp.org> Reimplemented the undo history: * app/Makefile.am * app/undo_history.[ch]: removed. Changes/cleanups to the undo system to enable/simplify the new undo history implementation: * app/core/core-types.h: removed enum undo_event_t. Removed the GimpImage parameter from GimpUndoPopFunc and GimpUndoFreeFunc because GimpUndo has a GimpImage pointer now (see below). * app/core/core-enums.[ch]: added enum GimpUndoEvent. Added an enum value for REDO_EXPIRED. * app/core/gimpimage.[ch]: added a GimpUndo pointer to the "undo_event" signal which needs to be passed for all events except UNDO_FREE. * app/display/gimpdisplayshell-handlers.c: changed accordingly. * app/core/gimpundo.[ch]: added a GimpImage pointer to the GimpUndo struct. Removed GimpImage parameters all over the place. Added preview stuff. The preview creation needs to be triggered explicitly using gimp_undo_create_preview() because the GimpUndo can't know when it's possible to create the preview. * app/core/gimpimage-undo-push.c * app/paint/gimppaintcore-undo.c * app/tools/gimptransformtool-undo.c: changed accordingly, cleanup. * app/core/gimpundostack.[ch]: ditto. Return the freed undo from gimp_undo_stack_free_bottom(). Removed unused container signal handlers. * app/core/gimpimage-undo.c: free the redo stack the same way old undos are freed (from bottom up). Emit "undo_event" with event == REDO_EXPIRED for each removed redo. * app/core/gimpmarshal.list: added new marshallers. New undo history implementation: * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpundoeditor.[ch] * app/widgets/gimpundopreview.[ch]: new widgets for the undo step previews and the history itself. * app/widgets/gimppreview-utils.c: added GimpUndoPreview to the list of possible preview types. * app/gui/dialogs-constructors.[ch] * app/gui/dialogs-menu.c * app/gui/dialogs.c * app/gui/image-menu.c * app/gui/toolbox-menu.c: removed the old and added the new undo history to the dialog factory and the various dialog menus. * app/widgets/gimpdnd.[ch]: don't warn if a GType has no corresponding DND type. Instead, return FALSE from the function that failed. * app/widgets/gimppreview.c: check the return value of gimpdnd functions. Not only add drag sources but also remove them when no longer needed. * app/widgets/gimpselectioneditor.h: removed unneeded inclusion of "gui/gui-types.h".
This commit is contained in:

committed by
Michael Natterer

parent
a20fc0fb51
commit
c8b4394d71
72
ChangeLog
72
ChangeLog
@ -1,3 +1,75 @@
|
|||||||
|
2003-02-20 Michael Natterer <mitch@gimp.org>
|
||||||
|
|
||||||
|
Reimplemented the undo history:
|
||||||
|
|
||||||
|
* app/Makefile.am
|
||||||
|
* app/undo_history.[ch]: removed.
|
||||||
|
|
||||||
|
Changes/cleanups to the undo system to enable/simplify the new
|
||||||
|
undo history implementation:
|
||||||
|
|
||||||
|
* app/core/core-types.h: removed enum undo_event_t. Removed the
|
||||||
|
GimpImage parameter from GimpUndoPopFunc and GimpUndoFreeFunc
|
||||||
|
because GimpUndo has a GimpImage pointer now (see below).
|
||||||
|
|
||||||
|
* app/core/core-enums.[ch]: added enum GimpUndoEvent. Added an
|
||||||
|
enum value for REDO_EXPIRED.
|
||||||
|
|
||||||
|
* app/core/gimpimage.[ch]: added a GimpUndo pointer to the
|
||||||
|
"undo_event" signal which needs to be passed for all events except
|
||||||
|
UNDO_FREE.
|
||||||
|
|
||||||
|
* app/display/gimpdisplayshell-handlers.c: changed accordingly.
|
||||||
|
|
||||||
|
* app/core/gimpundo.[ch]: added a GimpImage pointer to the
|
||||||
|
GimpUndo struct. Removed GimpImage parameters all over the
|
||||||
|
place. Added preview stuff. The preview creation needs to be
|
||||||
|
triggered explicitly using gimp_undo_create_preview() because the
|
||||||
|
GimpUndo can't know when it's possible to create the preview.
|
||||||
|
|
||||||
|
* app/core/gimpimage-undo-push.c
|
||||||
|
* app/paint/gimppaintcore-undo.c
|
||||||
|
* app/tools/gimptransformtool-undo.c: changed accordingly, cleanup.
|
||||||
|
|
||||||
|
* app/core/gimpundostack.[ch]: ditto. Return the freed undo from
|
||||||
|
gimp_undo_stack_free_bottom(). Removed unused container signal
|
||||||
|
handlers.
|
||||||
|
|
||||||
|
* app/core/gimpimage-undo.c: free the redo stack the same way old
|
||||||
|
undos are freed (from bottom up). Emit "undo_event" with event ==
|
||||||
|
REDO_EXPIRED for each removed redo.
|
||||||
|
|
||||||
|
* app/core/gimpmarshal.list: added new marshallers.
|
||||||
|
|
||||||
|
New undo history implementation:
|
||||||
|
|
||||||
|
* app/widgets/Makefile.am
|
||||||
|
* app/widgets/widgets-types.h
|
||||||
|
* app/widgets/gimpundoeditor.[ch]
|
||||||
|
* app/widgets/gimpundopreview.[ch]: new widgets for the undo
|
||||||
|
step previews and the history itself.
|
||||||
|
|
||||||
|
* app/widgets/gimppreview-utils.c: added GimpUndoPreview to the
|
||||||
|
list of possible preview types.
|
||||||
|
|
||||||
|
* app/gui/dialogs-constructors.[ch]
|
||||||
|
* app/gui/dialogs-menu.c
|
||||||
|
* app/gui/dialogs.c
|
||||||
|
* app/gui/image-menu.c
|
||||||
|
* app/gui/toolbox-menu.c: removed the old and added the new undo
|
||||||
|
history to the dialog factory and the various dialog menus.
|
||||||
|
|
||||||
|
* app/widgets/gimpdnd.[ch]: don't warn if a GType has no
|
||||||
|
corresponding DND type. Instead, return FALSE from the function
|
||||||
|
that failed.
|
||||||
|
|
||||||
|
* app/widgets/gimppreview.c: check the return value of gimpdnd
|
||||||
|
functions. Not only add drag sources but also remove them when no
|
||||||
|
longer needed.
|
||||||
|
|
||||||
|
* app/widgets/gimpselectioneditor.h: removed unneeded inclusion of
|
||||||
|
"gui/gui-types.h".
|
||||||
|
|
||||||
2003-02-19 Tor Lillqvist <tml@iki.fi>
|
2003-02-19 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
* libgimpbase/gimpbase.def: Add gimp_utf8_strtrim. Sort. Remove
|
* libgimpbase/gimpbase.def: Add gimp_utf8_strtrim. Sort. Remove
|
||||||
|
@ -35,13 +35,6 @@ scriptdata =
|
|||||||
|
|
||||||
bin_PROGRAMS = gimp-1.3
|
bin_PROGRAMS = gimp-1.3
|
||||||
|
|
||||||
##
|
|
||||||
## gui stuff for gui/, display/ or widgets/
|
|
||||||
##
|
|
||||||
gui_sources = \
|
|
||||||
undo_history.c \
|
|
||||||
undo_history.h
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## stuff which is about to be replaced by new subsystems
|
## stuff which is about to be replaced by new subsystems
|
||||||
##
|
##
|
||||||
@ -69,7 +62,6 @@ stuff_sources = \
|
|||||||
libgimp_glue.h
|
libgimp_glue.h
|
||||||
|
|
||||||
gimp_1_3_SOURCES = \
|
gimp_1_3_SOURCES = \
|
||||||
$(gui_sources) \
|
|
||||||
$(bye_sources) \
|
$(bye_sources) \
|
||||||
$(stuff_sources)
|
$(stuff_sources)
|
||||||
|
|
||||||
|
@ -381,6 +381,29 @@ gimp_undo_mode_get_type (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const GEnumValue gimp_undo_event_enum_values[] =
|
||||||
|
{
|
||||||
|
{ GIMP_UNDO_EVENT_UNDO_PUSHED, "GIMP_UNDO_EVENT_UNDO_PUSHED", "undo-pushed" },
|
||||||
|
{ GIMP_UNDO_EVENT_UNDO_EXPIRED, "GIMP_UNDO_EVENT_UNDO_EXPIRED", "undo-expired" },
|
||||||
|
{ GIMP_UNDO_EVENT_REDO_EXPIRED, "GIMP_UNDO_EVENT_REDO_EXPIRED", "redo-expired" },
|
||||||
|
{ GIMP_UNDO_EVENT_UNDO, "GIMP_UNDO_EVENT_UNDO", "undo" },
|
||||||
|
{ GIMP_UNDO_EVENT_REDO, "GIMP_UNDO_EVENT_REDO", "redo" },
|
||||||
|
{ GIMP_UNDO_EVENT_UNDO_FREE, "GIMP_UNDO_EVENT_UNDO_FREE", "undo-free" },
|
||||||
|
{ 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
gimp_undo_event_get_type (void)
|
||||||
|
{
|
||||||
|
static GType enum_type = 0;
|
||||||
|
|
||||||
|
if (!enum_type)
|
||||||
|
enum_type = g_enum_register_static ("GimpUndoEvent", gimp_undo_event_enum_values);
|
||||||
|
|
||||||
|
return enum_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const GEnumValue gimp_undo_type_enum_values[] =
|
static const GEnumValue gimp_undo_type_enum_values[] =
|
||||||
{
|
{
|
||||||
{ GIMP_UNDO_GROUP_NONE, N_("<<invalid>>"), "group-none" },
|
{ GIMP_UNDO_GROUP_NONE, N_("<<invalid>>"), "group-none" },
|
||||||
|
@ -280,6 +280,21 @@ typedef enum /*< pdb-skip >*/
|
|||||||
} GimpUndoMode;
|
} GimpUndoMode;
|
||||||
|
|
||||||
|
|
||||||
|
#define GIMP_TYPE_UNDO_EVENT (gimp_undo_event_get_type ())
|
||||||
|
|
||||||
|
GType gimp_undo_event_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
typedef enum /*< pdb-skip >*/
|
||||||
|
{
|
||||||
|
GIMP_UNDO_EVENT_UNDO_PUSHED, /* a new undo has been added to the undo stack */
|
||||||
|
GIMP_UNDO_EVENT_UNDO_EXPIRED, /* an undo has been freed from the undo stack */
|
||||||
|
GIMP_UNDO_EVENT_REDO_EXPIRED, /* a redo has been freed from the redo stack */
|
||||||
|
GIMP_UNDO_EVENT_UNDO, /* an undo has been executed */
|
||||||
|
GIMP_UNDO_EVENT_REDO, /* a redo has been executed */
|
||||||
|
GIMP_UNDO_EVENT_UNDO_FREE /* all undo and redo info has been cleared */
|
||||||
|
} GimpUndoEvent;
|
||||||
|
|
||||||
|
|
||||||
#define GIMP_TYPE_UNDO_TYPE (gimp_undo_type_get_type ())
|
#define GIMP_TYPE_UNDO_TYPE (gimp_undo_type_get_type ())
|
||||||
|
|
||||||
GType gimp_undo_type_get_type (void) G_GNUC_CONST;
|
GType gimp_undo_type_get_type (void) G_GNUC_CONST;
|
||||||
|
@ -44,18 +44,6 @@ typedef enum
|
|||||||
GIMP_POINTS
|
GIMP_POINTS
|
||||||
} SizeType;
|
} SizeType;
|
||||||
|
|
||||||
/* Argument to undo_event signal emitted by images */
|
|
||||||
|
|
||||||
typedef enum /*< pdb-skip >*/ /*< skip >*/
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* base objects */
|
/* base objects */
|
||||||
|
|
||||||
@ -160,11 +148,9 @@ typedef void (* GimpInitStatusFunc) (const gchar *text1,
|
|||||||
typedef GimpData * (* GimpDataObjectLoaderFunc) (const gchar *filename);
|
typedef GimpData * (* GimpDataObjectLoaderFunc) (const gchar *filename);
|
||||||
|
|
||||||
typedef gboolean (* GimpUndoPopFunc) (GimpUndo *undo,
|
typedef gboolean (* GimpUndoPopFunc) (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum);
|
GimpUndoAccumulator *accum);
|
||||||
typedef void (* GimpUndoFreeFunc) (GimpUndo *undo,
|
typedef void (* GimpUndoFreeFunc) (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
GimpUndoMode undo_mode);
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@ static void gimp_image_undo_pop_stack (GimpImage *gimage,
|
|||||||
GimpUndoStack *redo_stack,
|
GimpUndoStack *redo_stack,
|
||||||
GimpUndoMode undo_mode);
|
GimpUndoMode undo_mode);
|
||||||
static void gimp_image_undo_free_space (GimpImage *gimage);
|
static void gimp_image_undo_free_space (GimpImage *gimage);
|
||||||
|
static void gimp_image_undo_free_redo (GimpImage *gimage);
|
||||||
static const gchar * gimp_image_undo_type_to_name (GimpUndoType type);
|
static const gchar * gimp_image_undo_type_to_name (GimpUndoType type);
|
||||||
|
|
||||||
|
|
||||||
@ -78,8 +79,13 @@ gimp_image_undo_free (GimpImage *gimage)
|
|||||||
{
|
{
|
||||||
g_return_if_fail (GIMP_IS_IMAGE (gimage));
|
g_return_if_fail (GIMP_IS_IMAGE (gimage));
|
||||||
|
|
||||||
gimp_undo_free (GIMP_UNDO (gimage->undo_stack), gimage, GIMP_UNDO_MODE_UNDO);
|
/* Emit the UNDO_FREE event before actually freeing everything
|
||||||
gimp_undo_free (GIMP_UNDO (gimage->redo_stack), gimage, GIMP_UNDO_MODE_REDO);
|
* so the views can properly detach from the undo items
|
||||||
|
*/
|
||||||
|
gimp_image_undo_event (gimage, GIMP_UNDO_EVENT_UNDO_FREE, NULL);
|
||||||
|
|
||||||
|
gimp_undo_free (GIMP_UNDO (gimage->undo_stack), GIMP_UNDO_MODE_UNDO);
|
||||||
|
gimp_undo_free (GIMP_UNDO (gimage->redo_stack), GIMP_UNDO_MODE_REDO);
|
||||||
|
|
||||||
/* If the image was dirty, but could become clean by redo-ing
|
/* If the image was dirty, but could become clean by redo-ing
|
||||||
* some actions, then it should now become 'infinitely' dirty.
|
* some actions, then it should now become 'infinitely' dirty.
|
||||||
@ -94,7 +100,6 @@ gimp_image_undo_free (GimpImage *gimage)
|
|||||||
* due to undo actions, but since user can't undo without an undo
|
* due to undo actions, but since user can't undo without an undo
|
||||||
* stack, that's not so much a problem.
|
* stack, that's not so much a problem.
|
||||||
*/
|
*/
|
||||||
gimp_image_undo_event (gimage, UNDO_FREE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -124,8 +129,7 @@ gimp_image_undo_group_start (GimpImage *gimage,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* nuke the redo stack */
|
/* nuke the redo stack */
|
||||||
gimp_undo_free (GIMP_UNDO (gimage->redo_stack), gimage,
|
gimp_image_undo_free_redo (gimage);
|
||||||
GIMP_UNDO_MODE_REDO);
|
|
||||||
|
|
||||||
/* If the image was dirty, but could become clean by redo-ing
|
/* If the image was dirty, but could become clean by redo-ing
|
||||||
* some actions, then it should now become 'infinitely' dirty.
|
* some actions, then it should now become 'infinitely' dirty.
|
||||||
@ -170,7 +174,8 @@ gimp_image_undo_group_end (GimpImage *gimage)
|
|||||||
/* Do it here, since undo_push doesn't emit this event while in
|
/* Do it here, since undo_push doesn't emit this event while in
|
||||||
* the middle of a group
|
* the middle of a group
|
||||||
*/
|
*/
|
||||||
gimp_image_undo_event (gimage, UNDO_PUSHED);
|
gimp_image_undo_event (gimage, GIMP_UNDO_EVENT_UNDO_PUSHED,
|
||||||
|
gimp_undo_stack_peek (gimage->undo_stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -205,8 +210,7 @@ gimp_image_undo_push (GimpImage *gimage,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* nuke the redo stack */
|
/* nuke the redo stack */
|
||||||
gimp_undo_free (GIMP_UNDO (gimage->redo_stack), gimage,
|
gimp_image_undo_free_redo (gimage);
|
||||||
GIMP_UNDO_MODE_REDO);
|
|
||||||
|
|
||||||
/* If the image was dirty, but could become clean by redo-ing
|
/* If the image was dirty, but could become clean by redo-ing
|
||||||
* some actions, then it should now become 'infinitely' dirty.
|
* some actions, then it should now become 'infinitely' dirty.
|
||||||
@ -220,7 +224,8 @@ gimp_image_undo_push (GimpImage *gimage,
|
|||||||
if (struct_size > 0)
|
if (struct_size > 0)
|
||||||
undo_struct = g_malloc0 (struct_size);
|
undo_struct = g_malloc0 (struct_size);
|
||||||
|
|
||||||
new = gimp_undo_new (type,
|
new = gimp_undo_new (gimage,
|
||||||
|
type,
|
||||||
name,
|
name,
|
||||||
undo_struct, size,
|
undo_struct, size,
|
||||||
dirties_image,
|
dirties_image,
|
||||||
@ -232,7 +237,7 @@ gimp_image_undo_push (GimpImage *gimage,
|
|||||||
|
|
||||||
gimp_image_undo_free_space (gimage);
|
gimp_image_undo_free_space (gimage);
|
||||||
|
|
||||||
gimp_image_undo_event (gimage, UNDO_PUSHED);
|
gimp_image_undo_event (gimage, GIMP_UNDO_EVENT_UNDO_PUSHED, new);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -292,7 +297,8 @@ gimp_image_undo_pop_stack (GimpImage *gimage,
|
|||||||
/* let others know that we just popped an action */
|
/* let others know that we just popped an action */
|
||||||
gimp_image_undo_event (gimage,
|
gimp_image_undo_event (gimage,
|
||||||
(undo_mode == GIMP_UNDO_MODE_UNDO) ?
|
(undo_mode == GIMP_UNDO_MODE_UNDO) ?
|
||||||
UNDO_POPPED : UNDO_REDO);
|
GIMP_UNDO_EVENT_UNDO : GIMP_UNDO_EVENT_REDO,
|
||||||
|
undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -322,7 +328,10 @@ gimp_image_undo_free_space (GimpImage *gimage)
|
|||||||
while ((gimp_object_get_memsize (GIMP_OBJECT (container)) > undo_size) ||
|
while ((gimp_object_get_memsize (GIMP_OBJECT (container)) > undo_size) ||
|
||||||
(gimp_container_num_children (container) > max_undo_levels))
|
(gimp_container_num_children (container) > max_undo_levels))
|
||||||
{
|
{
|
||||||
gimp_undo_stack_free_bottom (gimage->undo_stack, GIMP_UNDO_MODE_UNDO);
|
GimpUndo *freed;
|
||||||
|
|
||||||
|
freed = gimp_undo_stack_free_bottom (gimage->undo_stack,
|
||||||
|
GIMP_UNDO_MODE_UNDO);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
g_print ("freed one step: undo_steps: %d undo_bytes: %d\n",
|
g_print ("freed one step: undo_steps: %d undo_bytes: %d\n",
|
||||||
@ -330,13 +339,47 @@ gimp_image_undo_free_space (GimpImage *gimage)
|
|||||||
gimp_object_get_memsize (GIMP_OBJECT (container)));
|
gimp_object_get_memsize (GIMP_OBJECT (container)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gimp_image_undo_event (gimage, UNDO_EXPIRED);
|
gimp_image_undo_event (gimage, GIMP_UNDO_EVENT_UNDO_EXPIRED, freed);
|
||||||
|
|
||||||
|
g_object_unref (freed);
|
||||||
|
|
||||||
if (gimp_container_num_children (container) <= min_undo_levels)
|
if (gimp_container_num_children (container) <= min_undo_levels)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_image_undo_free_redo (GimpImage *gimage)
|
||||||
|
{
|
||||||
|
GimpContainer *container;
|
||||||
|
|
||||||
|
container = gimage->redo_stack->undos;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_print ("redo_steps: %d redo_bytes: %d\n",
|
||||||
|
gimp_container_num_children (container),
|
||||||
|
gimp_object_get_memsize (GIMP_OBJECT (container)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (gimp_container_num_children (container) > 0)
|
||||||
|
{
|
||||||
|
GimpUndo *freed;
|
||||||
|
|
||||||
|
freed = gimp_undo_stack_free_bottom (gimage->redo_stack,
|
||||||
|
GIMP_UNDO_MODE_REDO);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_print ("freed one step: redo_steps: %d redo_bytes: %d\n",
|
||||||
|
gimp_container_num_children (container),
|
||||||
|
gimp_object_get_memsize (GIMP_OBJECT (container)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gimp_image_undo_event (gimage, GIMP_UNDO_EVENT_REDO_EXPIRED, freed);
|
||||||
|
|
||||||
|
g_object_unref (freed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const gchar *
|
static const gchar *
|
||||||
gimp_image_undo_type_to_name (GimpUndoType type)
|
gimp_image_undo_type_to_name (GimpUndoType type)
|
||||||
{
|
{
|
||||||
|
@ -371,9 +371,10 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||||||
G_SIGNAL_RUN_FIRST,
|
G_SIGNAL_RUN_FIRST,
|
||||||
G_STRUCT_OFFSET (GimpImageClass, undo_event),
|
G_STRUCT_OFFSET (GimpImageClass, undo_event),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
gimp_marshal_VOID__INT,
|
gimp_marshal_VOID__ENUM_OBJECT,
|
||||||
G_TYPE_NONE, 1,
|
G_TYPE_NONE, 2,
|
||||||
G_TYPE_INT);
|
GIMP_TYPE_UNDO_EVENT,
|
||||||
|
GIMP_TYPE_UNDO);
|
||||||
|
|
||||||
gimp_image_signals[FLUSH] =
|
gimp_image_signals[FLUSH] =
|
||||||
g_signal_new ("flush",
|
g_signal_new ("flush",
|
||||||
@ -1574,10 +1575,14 @@ gimp_image_undo_start (GimpImage *gimage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_image_undo_event (GimpImage *gimage,
|
gimp_image_undo_event (GimpImage *gimage,
|
||||||
gint event)
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo)
|
||||||
{
|
{
|
||||||
g_signal_emit (gimage, gimp_image_signals[UNDO_EVENT], 0, event);
|
g_return_if_fail (GIMP_IS_IMAGE (gimage));
|
||||||
|
g_return_if_fail (event == GIMP_UNDO_EVENT_UNDO_FREE || GIMP_IS_UNDO (undo));
|
||||||
|
|
||||||
|
g_signal_emit (gimage, gimp_image_signals[UNDO_EVENT], 0, event, undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,7 +198,8 @@ struct _GimpImageClass
|
|||||||
gint color_index);
|
gint color_index);
|
||||||
void (* undo_start) (GimpImage *gimage);
|
void (* undo_start) (GimpImage *gimage);
|
||||||
void (* undo_event) (GimpImage *gimage,
|
void (* undo_event) (GimpImage *gimage,
|
||||||
gint event);
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo);
|
||||||
|
|
||||||
void (* flush) (GimpImage *gimage);
|
void (* flush) (GimpImage *gimage);
|
||||||
};
|
};
|
||||||
@ -299,7 +300,8 @@ gboolean gimp_image_undo_freeze (GimpImage *gimage);
|
|||||||
gboolean gimp_image_undo_thaw (GimpImage *gimage);
|
gboolean gimp_image_undo_thaw (GimpImage *gimage);
|
||||||
void gimp_image_undo_start (GimpImage *gimage);
|
void gimp_image_undo_start (GimpImage *gimage);
|
||||||
void gimp_image_undo_event (GimpImage *gimage,
|
void gimp_image_undo_event (GimpImage *gimage,
|
||||||
gint event);
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo);
|
||||||
gint gimp_image_dirty (GimpImage *gimage);
|
gint gimp_image_dirty (GimpImage *gimage);
|
||||||
gint gimp_image_clean (GimpImage *gimage);
|
gint gimp_image_clean (GimpImage *gimage);
|
||||||
void gimp_image_clean_all (GimpImage *gimage);
|
void gimp_image_clean_all (GimpImage *gimage);
|
||||||
|
@ -46,6 +46,8 @@ POINTER: VOID
|
|||||||
VOID: BOXED
|
VOID: BOXED
|
||||||
VOID: DOUBLE
|
VOID: DOUBLE
|
||||||
VOID: ENUM
|
VOID: ENUM
|
||||||
|
VOID: ENUM, OBJECT
|
||||||
|
VOID: ENUM, POINTER
|
||||||
VOID: INT
|
VOID: INT
|
||||||
VOID: INT, BOOLEAN, INT, OBJECT
|
VOID: INT, BOOLEAN, INT, OBJECT
|
||||||
VOID: INT, INT
|
VOID: INT, INT
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "gimpimage.h"
|
#include "gimpimage.h"
|
||||||
#include "gimpmarshal.h"
|
#include "gimpmarshal.h"
|
||||||
#include "gimpundo.h"
|
#include "gimpundo.h"
|
||||||
|
#include "gimpundostack.h"
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -37,24 +38,25 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void gimp_undo_class_init (GimpUndoClass *klass);
|
static void gimp_undo_class_init (GimpUndoClass *klass);
|
||||||
static void gimp_undo_init (GimpUndo *undo);
|
static void gimp_undo_init (GimpUndo *undo);
|
||||||
|
|
||||||
static void gimp_undo_finalize (GObject *object);
|
static void gimp_undo_finalize (GObject *object);
|
||||||
|
|
||||||
static gsize gimp_undo_get_memsize (GimpObject *object);
|
static gsize gimp_undo_get_memsize (GimpObject *object);
|
||||||
|
|
||||||
static TempBuf * gimp_undo_get_preview (GimpViewable *viewable,
|
static TempBuf * gimp_undo_get_preview (GimpViewable *viewable,
|
||||||
gint width,
|
gint width,
|
||||||
gint height);
|
gint height);
|
||||||
|
|
||||||
static void gimp_undo_real_pop (GimpUndo *undo,
|
static void gimp_undo_real_pop (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoAccumulator *accum);
|
||||||
GimpUndoAccumulator *accum);
|
static void gimp_undo_real_free (GimpUndo *undo,
|
||||||
static void gimp_undo_real_free (GimpUndo *undo,
|
GimpUndoMode undo_mode);
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
static gboolean gimp_undo_create_preview_idle (gpointer data);
|
||||||
|
static void gimp_undo_create_preview_private (GimpUndo *undo);
|
||||||
|
|
||||||
|
|
||||||
static guint undo_signals[LAST_SIGNAL] = { 0 };
|
static guint undo_signals[LAST_SIGNAL] = { 0 };
|
||||||
@ -109,9 +111,8 @@ gimp_undo_class_init (GimpUndoClass *klass)
|
|||||||
G_SIGNAL_RUN_FIRST,
|
G_SIGNAL_RUN_FIRST,
|
||||||
G_STRUCT_OFFSET (GimpUndoClass, pop),
|
G_STRUCT_OFFSET (GimpUndoClass, pop),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
gimp_marshal_VOID__OBJECT_ENUM_POINTER,
|
gimp_marshal_VOID__ENUM_POINTER,
|
||||||
G_TYPE_NONE, 3,
|
G_TYPE_NONE, 2,
|
||||||
GIMP_TYPE_IMAGE,
|
|
||||||
GIMP_TYPE_UNDO_MODE,
|
GIMP_TYPE_UNDO_MODE,
|
||||||
G_TYPE_POINTER);
|
G_TYPE_POINTER);
|
||||||
|
|
||||||
@ -121,9 +122,8 @@ gimp_undo_class_init (GimpUndoClass *klass)
|
|||||||
G_SIGNAL_RUN_FIRST,
|
G_SIGNAL_RUN_FIRST,
|
||||||
G_STRUCT_OFFSET (GimpUndoClass, free),
|
G_STRUCT_OFFSET (GimpUndoClass, free),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
gimp_marshal_VOID__OBJECT_ENUM,
|
gimp_marshal_VOID__ENUM,
|
||||||
G_TYPE_NONE, 2,
|
G_TYPE_NONE, 1,
|
||||||
GIMP_TYPE_IMAGE,
|
|
||||||
GIMP_TYPE_UNDO_MODE);
|
GIMP_TYPE_UNDO_MODE);
|
||||||
|
|
||||||
object_class->finalize = gimp_undo_finalize;
|
object_class->finalize = gimp_undo_finalize;
|
||||||
@ -139,6 +139,8 @@ gimp_undo_class_init (GimpUndoClass *klass)
|
|||||||
static void
|
static void
|
||||||
gimp_undo_init (GimpUndo *undo)
|
gimp_undo_init (GimpUndo *undo)
|
||||||
{
|
{
|
||||||
|
undo->gimage = NULL;
|
||||||
|
undo->undo_type = 0;
|
||||||
undo->data = NULL;
|
undo->data = NULL;
|
||||||
undo->dirties_image = FALSE;
|
undo->dirties_image = FALSE;
|
||||||
undo->pop_func = NULL;
|
undo->pop_func = NULL;
|
||||||
@ -153,6 +155,12 @@ gimp_undo_finalize (GObject *object)
|
|||||||
|
|
||||||
undo = GIMP_UNDO (object);
|
undo = GIMP_UNDO (object);
|
||||||
|
|
||||||
|
if (undo->preview_idle_id)
|
||||||
|
{
|
||||||
|
g_source_remove (undo->preview_idle_id);
|
||||||
|
undo->preview_idle_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (undo->preview)
|
if (undo->preview)
|
||||||
{
|
{
|
||||||
temp_buf_free (undo->preview);
|
temp_buf_free (undo->preview);
|
||||||
@ -183,11 +191,29 @@ gimp_undo_get_preview (GimpViewable *viewable,
|
|||||||
gint width,
|
gint width,
|
||||||
gint height)
|
gint height)
|
||||||
{
|
{
|
||||||
return (GIMP_UNDO (viewable)->preview);
|
return GIMP_UNDO (viewable)->preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_real_pop (GimpUndo *undo,
|
||||||
|
GimpUndoMode undo_mode,
|
||||||
|
GimpUndoAccumulator *accum)
|
||||||
|
{
|
||||||
|
if (undo->pop_func)
|
||||||
|
undo->pop_func (undo, undo_mode, accum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_real_free (GimpUndo *undo,
|
||||||
|
GimpUndoMode undo_mode)
|
||||||
|
{
|
||||||
|
if (undo->free_func)
|
||||||
|
undo->free_func (undo, undo_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
GimpUndo *
|
GimpUndo *
|
||||||
gimp_undo_new (GimpUndoType undo_type,
|
gimp_undo_new (GimpImage *gimage,
|
||||||
|
GimpUndoType undo_type,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gsize size,
|
gsize size,
|
||||||
@ -197,13 +223,15 @@ gimp_undo_new (GimpUndoType undo_type,
|
|||||||
{
|
{
|
||||||
GimpUndo *undo;
|
GimpUndo *undo;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
|
||||||
g_return_val_if_fail (name != NULL, NULL);
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
//g_return_val_if_fail (size == 0 || data != NULL, NULL);
|
g_return_val_if_fail (size == 0 || data != NULL, NULL);
|
||||||
|
|
||||||
undo = g_object_new (GIMP_TYPE_UNDO,
|
undo = g_object_new (GIMP_TYPE_UNDO,
|
||||||
"name", name,
|
"name", name,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
undo->gimage = gimage;
|
||||||
undo->undo_type = undo_type;
|
undo->undo_type = undo_type;
|
||||||
undo->data = data;
|
undo->data = data;
|
||||||
undo->size = size;
|
undo->size = size;
|
||||||
@ -216,26 +244,24 @@ gimp_undo_new (GimpUndoType undo_type,
|
|||||||
|
|
||||||
void
|
void
|
||||||
gimp_undo_pop (GimpUndo *undo,
|
gimp_undo_pop (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum)
|
GimpUndoAccumulator *accum)
|
||||||
{
|
{
|
||||||
g_return_if_fail (GIMP_IS_UNDO (undo));
|
g_return_if_fail (GIMP_IS_UNDO (undo));
|
||||||
g_return_if_fail (GIMP_IS_IMAGE (gimage));
|
|
||||||
g_return_if_fail (accum != NULL);
|
g_return_if_fail (accum != NULL);
|
||||||
|
|
||||||
g_signal_emit (undo, undo_signals[POP], 0, gimage, undo_mode, accum);
|
g_signal_emit (undo, undo_signals[POP], 0, undo_mode, accum);
|
||||||
|
|
||||||
if (undo->dirties_image)
|
if (undo->dirties_image)
|
||||||
{
|
{
|
||||||
switch (undo_mode)
|
switch (undo_mode)
|
||||||
{
|
{
|
||||||
case GIMP_UNDO_MODE_UNDO:
|
case GIMP_UNDO_MODE_UNDO:
|
||||||
gimp_image_clean (gimage);
|
gimp_image_clean (undo->gimage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_UNDO_MODE_REDO:
|
case GIMP_UNDO_MODE_REDO:
|
||||||
gimp_image_dirty (gimage);
|
gimp_image_dirty (undo->gimage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,30 +269,86 @@ gimp_undo_pop (GimpUndo *undo,
|
|||||||
|
|
||||||
void
|
void
|
||||||
gimp_undo_free (GimpUndo *undo,
|
gimp_undo_free (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode)
|
GimpUndoMode undo_mode)
|
||||||
{
|
{
|
||||||
g_return_if_fail (GIMP_IS_UNDO (undo));
|
g_return_if_fail (GIMP_IS_UNDO (undo));
|
||||||
g_return_if_fail (GIMP_IS_IMAGE (gimage));
|
|
||||||
|
|
||||||
g_signal_emit (undo, undo_signals[FREE], 0, gimage, undo_mode);
|
g_signal_emit (undo, undo_signals[FREE], 0, undo_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
gimp_undo_real_pop (GimpUndo *undo,
|
gimp_undo_create_preview (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
gboolean create_now)
|
||||||
GimpUndoMode undo_mode,
|
|
||||||
GimpUndoAccumulator *accum)
|
|
||||||
{
|
{
|
||||||
if (undo->pop_func)
|
g_return_if_fail (GIMP_IS_UNDO (undo));
|
||||||
undo->pop_func (undo, gimage, undo_mode, accum);
|
|
||||||
|
if (undo->preview || undo->preview_idle_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (create_now)
|
||||||
|
gimp_undo_create_preview_private (undo);
|
||||||
|
else
|
||||||
|
undo->preview_idle_id = g_idle_add (gimp_undo_create_preview_idle, undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
gimp_undo_real_free (GimpUndo *undo,
|
gimp_undo_create_preview_idle (gpointer data)
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode)
|
|
||||||
{
|
{
|
||||||
if (undo->free_func)
|
GimpUndo *undo;
|
||||||
undo->free_func (undo, gimage, undo_mode);
|
|
||||||
|
undo = GIMP_UNDO (data);
|
||||||
|
|
||||||
|
if (undo == gimp_undo_stack_peek (undo->gimage->undo_stack))
|
||||||
|
{
|
||||||
|
gimp_undo_create_preview_private (undo);
|
||||||
|
}
|
||||||
|
|
||||||
|
undo->preview_idle_id = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_undo_create_preview_private (GimpUndo *undo)
|
||||||
|
{
|
||||||
|
GimpViewable *preview_viewable;
|
||||||
|
gint width;
|
||||||
|
gint height;
|
||||||
|
|
||||||
|
switch (undo->undo_type)
|
||||||
|
{
|
||||||
|
case GIMP_UNDO_GROUP_IMAGE_QMASK:
|
||||||
|
case GIMP_UNDO_IMAGE_QMASK:
|
||||||
|
case GIMP_UNDO_MASK:
|
||||||
|
preview_viewable = GIMP_VIEWABLE (gimp_image_get_mask (undo->gimage));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
preview_viewable = GIMP_VIEWABLE (undo->gimage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (undo->gimage->width <= 64 && undo->gimage->height <= 64)
|
||||||
|
{
|
||||||
|
width = undo->gimage->width;
|
||||||
|
height = undo->gimage->height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (undo->gimage->width > undo->gimage->height)
|
||||||
|
{
|
||||||
|
width = 64;
|
||||||
|
height = MAX (1, undo->gimage->height * 64 / undo->gimage->width);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
height = 64;
|
||||||
|
width = MAX (1, undo->gimage->width * 64 / undo->gimage->height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
undo->preview = gimp_viewable_get_new_preview (preview_viewable,
|
||||||
|
width, height);
|
||||||
|
|
||||||
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (undo));
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ struct _GimpUndo
|
|||||||
{
|
{
|
||||||
GimpViewable parent_instance;
|
GimpViewable parent_instance;
|
||||||
|
|
||||||
|
GimpImage *gimage; /* the image this undo is part of */
|
||||||
|
|
||||||
GimpUndoType undo_type; /* undo type */
|
GimpUndoType undo_type; /* undo type */
|
||||||
gpointer data; /* data to implement the undo */
|
gpointer data; /* data to implement the undo */
|
||||||
gsize size; /* size of undo item */
|
gsize size; /* size of undo item */
|
||||||
@ -58,6 +60,7 @@ struct _GimpUndo
|
|||||||
GimpUndoFreeFunc free_func; /* function pointer to free undo data */
|
GimpUndoFreeFunc free_func; /* function pointer to free undo data */
|
||||||
|
|
||||||
TempBuf *preview;
|
TempBuf *preview;
|
||||||
|
guint preview_idle_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GimpUndoClass
|
struct _GimpUndoClass
|
||||||
@ -65,32 +68,32 @@ struct _GimpUndoClass
|
|||||||
GimpViewableClass parent_class;
|
GimpViewableClass parent_class;
|
||||||
|
|
||||||
void (* pop) (GimpUndo *undo,
|
void (* pop) (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum);
|
GimpUndoAccumulator *accum);
|
||||||
void (* free) (GimpUndo *undo,
|
void (* free) (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
GimpUndoMode undo_mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
GType gimp_undo_get_type (void) G_GNUC_CONST;
|
GType gimp_undo_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
GimpUndo * gimp_undo_new (GimpUndoType undo_type,
|
GimpUndo * gimp_undo_new (GimpImage *gimage,
|
||||||
const gchar *name,
|
GimpUndoType undo_type,
|
||||||
gpointer data,
|
const gchar *name,
|
||||||
gsize size,
|
gpointer data,
|
||||||
gboolean dirties_image,
|
gsize size,
|
||||||
GimpUndoPopFunc pop_func,
|
gboolean dirties_image,
|
||||||
GimpUndoFreeFunc free_func);
|
GimpUndoPopFunc pop_func,
|
||||||
|
GimpUndoFreeFunc free_func);
|
||||||
|
|
||||||
void gimp_undo_pop (GimpUndo *undo,
|
void gimp_undo_pop (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoAccumulator *accum);
|
||||||
GimpUndoAccumulator *accum);
|
void gimp_undo_free (GimpUndo *undo,
|
||||||
void gimp_undo_free (GimpUndo *undo,
|
GimpUndoMode undo_mode);
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
void gimp_undo_create_preview (GimpUndo *undo,
|
||||||
|
gboolean create_now);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GIMP_UNDO_H__ */
|
#endif /* __GIMP_UNDO_H__ */
|
||||||
|
@ -28,27 +28,18 @@
|
|||||||
#include "gimpundostack.h"
|
#include "gimpundostack.h"
|
||||||
|
|
||||||
|
|
||||||
static void gimp_undo_stack_class_init (GimpUndoStackClass *klass);
|
static void gimp_undo_stack_class_init (GimpUndoStackClass *klass);
|
||||||
static void gimp_undo_stack_init (GimpUndoStack *stack);
|
static void gimp_undo_stack_init (GimpUndoStack *stack);
|
||||||
|
|
||||||
static void gimp_undo_stack_finalize (GObject *object);
|
static void gimp_undo_stack_finalize (GObject *object);
|
||||||
|
|
||||||
static gsize gimp_undo_stack_get_memsize (GimpObject *object);
|
static gsize gimp_undo_stack_get_memsize (GimpObject *object);
|
||||||
|
|
||||||
static void gimp_undo_stack_pop (GimpUndo *undo,
|
static void gimp_undo_stack_pop (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoAccumulator *accum);
|
||||||
GimpUndoAccumulator *accum);
|
static void gimp_undo_stack_free (GimpUndo *undo,
|
||||||
static void gimp_undo_stack_free (GimpUndo *undo,
|
GimpUndoMode undo_mode);
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
|
||||||
|
|
||||||
static void gimp_undo_stack_add_callback (GimpContainer *container,
|
|
||||||
GimpObject *object,
|
|
||||||
gpointer data);
|
|
||||||
static void gimp_undo_stack_remove_callback (GimpContainer *container,
|
|
||||||
GimpObject *object,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
|
|
||||||
static GimpUndoClass *parent_class = NULL;
|
static GimpUndoClass *parent_class = NULL;
|
||||||
@ -106,21 +97,8 @@ gimp_undo_stack_class_init (GimpUndoStackClass *klass)
|
|||||||
static void
|
static void
|
||||||
gimp_undo_stack_init (GimpUndoStack *stack)
|
gimp_undo_stack_init (GimpUndoStack *stack)
|
||||||
{
|
{
|
||||||
GimpContainer *undos;
|
stack->undos = gimp_list_new (GIMP_TYPE_UNDO,
|
||||||
|
GIMP_CONTAINER_POLICY_STRONG);
|
||||||
undos = gimp_list_new (GIMP_TYPE_UNDO,
|
|
||||||
GIMP_CONTAINER_POLICY_STRONG);
|
|
||||||
|
|
||||||
stack->undos = undos;
|
|
||||||
|
|
||||||
g_signal_connect (undos, "add",
|
|
||||||
G_CALLBACK (gimp_undo_stack_add_callback),
|
|
||||||
stack);
|
|
||||||
g_signal_connect (undos, "remove",
|
|
||||||
G_CALLBACK (gimp_undo_stack_remove_callback),
|
|
||||||
stack);
|
|
||||||
|
|
||||||
stack->gimage = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -155,7 +133,6 @@ gimp_undo_stack_get_memsize (GimpObject *object)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_undo_stack_pop (GimpUndo *undo,
|
gimp_undo_stack_pop (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum)
|
GimpUndoAccumulator *accum)
|
||||||
{
|
{
|
||||||
@ -172,13 +149,12 @@ gimp_undo_stack_pop (GimpUndo *undo,
|
|||||||
|
|
||||||
child = GIMP_UNDO (list->data);
|
child = GIMP_UNDO (list->data);
|
||||||
|
|
||||||
gimp_undo_pop (child, gimage, undo_mode, accum);
|
gimp_undo_pop (child, undo_mode, accum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_undo_stack_free (GimpUndo *undo,
|
gimp_undo_stack_free (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode)
|
GimpUndoMode undo_mode)
|
||||||
{
|
{
|
||||||
GimpUndoStack *stack;
|
GimpUndoStack *stack;
|
||||||
@ -194,7 +170,7 @@ gimp_undo_stack_free (GimpUndo *undo,
|
|||||||
|
|
||||||
child = GIMP_UNDO (list->data);
|
child = GIMP_UNDO (list->data);
|
||||||
|
|
||||||
gimp_undo_free (child, gimage, undo_mode);
|
gimp_undo_free (child, undo_mode);
|
||||||
g_object_unref (child);
|
g_object_unref (child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +188,7 @@ gimp_undo_stack_new (GimpImage *gimage)
|
|||||||
|
|
||||||
stack = GIMP_UNDO_STACK (g_object_new (GIMP_TYPE_UNDO_STACK, NULL));
|
stack = GIMP_UNDO_STACK (g_object_new (GIMP_TYPE_UNDO_STACK, NULL));
|
||||||
|
|
||||||
stack->gimage = gimage;
|
GIMP_UNDO (stack)->gimage = gimage;
|
||||||
|
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
@ -232,45 +208,49 @@ gimp_undo_stack_pop_undo (GimpUndoStack *stack,
|
|||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum)
|
GimpUndoAccumulator *accum)
|
||||||
{
|
{
|
||||||
GimpObject *object;
|
GimpUndo *undo;
|
||||||
|
|
||||||
g_return_val_if_fail (GIMP_IS_UNDO_STACK (stack), NULL);
|
g_return_val_if_fail (GIMP_IS_UNDO_STACK (stack), NULL);
|
||||||
g_return_val_if_fail (accum != NULL, NULL);
|
g_return_val_if_fail (accum != NULL, NULL);
|
||||||
|
|
||||||
object = gimp_container_get_child_by_index (GIMP_CONTAINER (stack->undos),0);
|
|
||||||
|
|
||||||
if (object)
|
undo = (GimpUndo *)
|
||||||
|
gimp_container_get_child_by_index (GIMP_CONTAINER (stack->undos), 0);
|
||||||
|
|
||||||
|
if (undo)
|
||||||
{
|
{
|
||||||
gimp_container_remove (GIMP_CONTAINER (stack->undos), object);
|
gimp_container_remove (GIMP_CONTAINER (stack->undos), GIMP_OBJECT (undo));
|
||||||
gimp_undo_pop (GIMP_UNDO (object), stack->gimage, undo_mode, accum);
|
gimp_undo_pop (undo, undo_mode, accum);
|
||||||
|
|
||||||
return GIMP_UNDO (object);
|
return undo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
GimpUndo *
|
||||||
gimp_undo_stack_free_bottom (GimpUndoStack *stack,
|
gimp_undo_stack_free_bottom (GimpUndoStack *stack,
|
||||||
GimpUndoMode undo_mode)
|
GimpUndoMode undo_mode)
|
||||||
{
|
{
|
||||||
GimpObject *object;
|
GimpUndo *undo;
|
||||||
gint n_children;
|
gint n_children;
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_UNDO_STACK (stack));
|
g_return_val_if_fail (GIMP_IS_UNDO_STACK (stack), NULL);
|
||||||
|
|
||||||
n_children = gimp_container_num_children (GIMP_CONTAINER (stack->undos));
|
n_children = gimp_container_num_children (GIMP_CONTAINER (stack->undos));
|
||||||
|
|
||||||
object = gimp_container_get_child_by_index (GIMP_CONTAINER (stack->undos),
|
undo = (GimpUndo *)
|
||||||
n_children - 1);
|
gimp_container_get_child_by_index (GIMP_CONTAINER (stack->undos),
|
||||||
|
n_children - 1);
|
||||||
|
|
||||||
if (object)
|
if (undo)
|
||||||
{
|
{
|
||||||
gimp_container_remove (GIMP_CONTAINER (stack->undos), object);
|
gimp_container_remove (GIMP_CONTAINER (stack->undos), GIMP_OBJECT (undo));
|
||||||
gimp_undo_free (GIMP_UNDO (object), stack->gimage, undo_mode);
|
gimp_undo_free (undo, undo_mode);
|
||||||
|
|
||||||
g_object_unref (object);
|
return undo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GimpUndo *
|
GimpUndo *
|
||||||
@ -284,27 +264,3 @@ gimp_undo_stack_peek (GimpUndoStack *stack)
|
|||||||
|
|
||||||
return (object ? GIMP_UNDO (object) : NULL);
|
return (object ? GIMP_UNDO (object) : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gimp_undo_stack_add_callback (GimpContainer *container,
|
|
||||||
GimpObject *object,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GimpUndo *undo;
|
|
||||||
GimpUndo *stack;
|
|
||||||
|
|
||||||
undo = GIMP_UNDO (object);
|
|
||||||
stack = GIMP_UNDO (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gimp_undo_stack_remove_callback (GimpContainer *container,
|
|
||||||
GimpObject *object,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
GimpUndo *undo;
|
|
||||||
GimpUndo *stack;
|
|
||||||
|
|
||||||
undo = GIMP_UNDO (object);
|
|
||||||
stack = GIMP_UNDO (data);
|
|
||||||
}
|
|
||||||
|
@ -37,7 +37,6 @@ struct _GimpUndoStack
|
|||||||
{
|
{
|
||||||
GimpUndo parent_instance;
|
GimpUndo parent_instance;
|
||||||
|
|
||||||
GimpImage *gimage;
|
|
||||||
GimpContainer *undos;
|
GimpContainer *undos;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ GimpUndo * gimp_undo_stack_pop_undo (GimpUndoStack *stack,
|
|||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum);
|
GimpUndoAccumulator *accum);
|
||||||
|
|
||||||
void gimp_undo_stack_free_bottom (GimpUndoStack *stack,
|
GimpUndo * gimp_undo_stack_free_bottom (GimpUndoStack *stack,
|
||||||
GimpUndoMode undo_mode);
|
GimpUndoMode undo_mode);
|
||||||
GimpUndo * gimp_undo_stack_peek (GimpUndoStack *stack);
|
GimpUndo * gimp_undo_stack_peek (GimpUndoStack *stack);
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "widgets/gimpselectioneditor.h"
|
#include "widgets/gimpselectioneditor.h"
|
||||||
#include "widgets/gimptoolbox.h"
|
#include "widgets/gimptoolbox.h"
|
||||||
#include "widgets/gimptoolbox-color-area.h"
|
#include "widgets/gimptoolbox-color-area.h"
|
||||||
|
#include "widgets/gimpundoeditor.h"
|
||||||
#include "widgets/gimpvectorslistview.h"
|
#include "widgets/gimpvectorslistview.h"
|
||||||
|
|
||||||
#include "display/gimpdisplay.h"
|
#include "display/gimpdisplay.h"
|
||||||
@ -82,8 +83,6 @@
|
|||||||
#include "tool-options-dialog.h"
|
#include "tool-options-dialog.h"
|
||||||
#include "vectors-commands.h"
|
#include "vectors-commands.h"
|
||||||
|
|
||||||
#include "undo_history.h"
|
|
||||||
|
|
||||||
#include "libgimp/gimpintl.h"
|
#include "libgimp/gimpintl.h"
|
||||||
|
|
||||||
|
|
||||||
@ -128,6 +127,8 @@ static void dialogs_set_indexed_palette_context_func (GimpDockable *dockable,
|
|||||||
GimpContext *context);
|
GimpContext *context);
|
||||||
static void dialogs_set_selection_editor_context_func (GimpDockable *dockable,
|
static void dialogs_set_selection_editor_context_func (GimpDockable *dockable,
|
||||||
GimpContext *context);
|
GimpContext *context);
|
||||||
|
static void dialogs_set_undo_history_context_func (GimpDockable *dockable,
|
||||||
|
GimpContext *context);
|
||||||
static void dialogs_set_navigation_context_func (GimpDockable *dockable,
|
static void dialogs_set_navigation_context_func (GimpDockable *dockable,
|
||||||
GimpContext *context);
|
GimpContext *context);
|
||||||
|
|
||||||
@ -150,6 +151,9 @@ static void dialogs_indexed_palette_image_changed (GimpContext *context
|
|||||||
static void dialogs_selection_editor_image_changed (GimpContext *context,
|
static void dialogs_selection_editor_image_changed (GimpContext *context,
|
||||||
GimpImage *gimage,
|
GimpImage *gimage,
|
||||||
GimpSelectionEditor *editor);
|
GimpSelectionEditor *editor);
|
||||||
|
static void dialogs_undo_history_image_changed (GimpContext *context,
|
||||||
|
GimpImage *gimage,
|
||||||
|
GimpUndoEditor *editor);
|
||||||
static void dialogs_navigation_display_changed (GimpContext *context,
|
static void dialogs_navigation_display_changed (GimpContext *context,
|
||||||
GimpDisplay *gdisp,
|
GimpDisplay *gdisp,
|
||||||
GimpNavigationView *view);
|
GimpNavigationView *view);
|
||||||
@ -183,31 +187,6 @@ dialogs_module_browser_get (GimpDialogFactory *factory,
|
|||||||
return module_browser_new (context->gimp);
|
return module_browser_new (context->gimp);
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
dialogs_undo_history_get (GimpDialogFactory *factory,
|
|
||||||
GimpContext *context,
|
|
||||||
gint preview_size)
|
|
||||||
{
|
|
||||||
GimpImage *gimage;
|
|
||||||
GtkWidget *undo_history;
|
|
||||||
|
|
||||||
gimage = gimp_context_get_image (context);
|
|
||||||
|
|
||||||
if (! gimage)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
undo_history = g_object_get_data (G_OBJECT (gimage), "gimp-undo-history");
|
|
||||||
|
|
||||||
if (! undo_history)
|
|
||||||
{
|
|
||||||
undo_history = undo_history_new (gimage);
|
|
||||||
|
|
||||||
g_object_set_data (G_OBJECT (gimage), "gimp-undo-history", undo_history);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undo_history;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
dialogs_display_filters_get (GimpDialogFactory *factory,
|
dialogs_display_filters_get (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
@ -795,6 +774,30 @@ dialogs_selection_editor_new (GimpDialogFactory *factory,
|
|||||||
return dockable;
|
return dockable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
dialogs_undo_history_new (GimpDialogFactory *factory,
|
||||||
|
GimpContext *context,
|
||||||
|
gint preview_size)
|
||||||
|
{
|
||||||
|
GimpImage *gimage;
|
||||||
|
GtkWidget *view;
|
||||||
|
GtkWidget *dockable;
|
||||||
|
|
||||||
|
gimage = gimp_context_get_image (context);
|
||||||
|
|
||||||
|
view = gimp_undo_editor_new (gimage);
|
||||||
|
|
||||||
|
dockable = dialogs_dockable_new (view,
|
||||||
|
_("Undo History"), _("Undo"),
|
||||||
|
GTK_STOCK_UNDO,
|
||||||
|
dialogs_stock_text_tab_func,
|
||||||
|
dialogs_set_undo_history_context_func);
|
||||||
|
|
||||||
|
gimp_dockable_set_context (GIMP_DOCKABLE (dockable), context);
|
||||||
|
|
||||||
|
return dockable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***** misc dockables *****/
|
/***** misc dockables *****/
|
||||||
|
|
||||||
@ -1380,6 +1383,41 @@ dialogs_set_selection_editor_context_func (GimpDockable *dockable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dialogs_set_undo_history_context_func (GimpDockable *dockable,
|
||||||
|
GimpContext *context)
|
||||||
|
{
|
||||||
|
GimpUndoEditor *view;
|
||||||
|
|
||||||
|
view = (GimpUndoEditor *) g_object_get_data (G_OBJECT (dockable),
|
||||||
|
"gimp-dialogs-view");
|
||||||
|
|
||||||
|
if (view)
|
||||||
|
{
|
||||||
|
if (dockable->context)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (dockable->context,
|
||||||
|
dialogs_undo_history_image_changed,
|
||||||
|
view);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
g_signal_connect (context, "image_changed",
|
||||||
|
G_CALLBACK (dialogs_undo_history_image_changed),
|
||||||
|
view);
|
||||||
|
|
||||||
|
dialogs_undo_history_image_changed (context,
|
||||||
|
gimp_context_get_image (context),
|
||||||
|
view);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialogs_undo_history_image_changed (NULL, NULL, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dialogs_set_navigation_context_func (GimpDockable *dockable,
|
dialogs_set_navigation_context_func (GimpDockable *dockable,
|
||||||
GimpContext *context)
|
GimpContext *context)
|
||||||
@ -1470,6 +1508,14 @@ dialogs_selection_editor_image_changed (GimpContext *context,
|
|||||||
gimp_selection_editor_set_image (editor, gimage);
|
gimp_selection_editor_set_image (editor, gimage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dialogs_undo_history_image_changed (GimpContext *context,
|
||||||
|
GimpImage *gimage,
|
||||||
|
GimpUndoEditor *editor)
|
||||||
|
{
|
||||||
|
gimp_undo_editor_set_image (editor, gimage);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dialogs_navigation_display_changed (GimpContext *context,
|
dialogs_navigation_display_changed (GimpContext *context,
|
||||||
GimpDisplay *gdisp,
|
GimpDisplay *gdisp,
|
||||||
|
@ -31,9 +31,6 @@ GtkWidget * dialogs_preferences_get (GimpDialogFactory *factory,
|
|||||||
GtkWidget * dialogs_module_browser_get (GimpDialogFactory *factory,
|
GtkWidget * dialogs_module_browser_get (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gint preview_size);
|
gint preview_size);
|
||||||
GtkWidget * dialogs_undo_history_get (GimpDialogFactory *factory,
|
|
||||||
GimpContext *context,
|
|
||||||
gint preview_size);
|
|
||||||
GtkWidget * dialogs_display_filters_get (GimpDialogFactory *factory,
|
GtkWidget * dialogs_display_filters_get (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gint preview_size);
|
gint preview_size);
|
||||||
@ -126,6 +123,9 @@ GtkWidget * dialogs_indexed_palette_new (GimpDialogFactory *factory,
|
|||||||
GtkWidget * dialogs_selection_editor_new (GimpDialogFactory *factory,
|
GtkWidget * dialogs_selection_editor_new (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gint preview_size);
|
gint preview_size);
|
||||||
|
GtkWidget * dialogs_undo_history_new (GimpDialogFactory *factory,
|
||||||
|
GimpContext *context,
|
||||||
|
gint preview_size);
|
||||||
|
|
||||||
GtkWidget * dialogs_color_editor_new (GimpDialogFactory *factory,
|
GtkWidget * dialogs_color_editor_new (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
|
@ -43,7 +43,6 @@ static const GimpDialogFactoryEntry toplevel_entries[] =
|
|||||||
{ "gimp-device-status-dialog", dialogs_device_status_get, 32, TRUE, TRUE, FALSE, TRUE },
|
{ "gimp-device-status-dialog", dialogs_device_status_get, 32, TRUE, TRUE, FALSE, TRUE },
|
||||||
{ "gimp-preferences-dialog", dialogs_preferences_get, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-preferences-dialog", dialogs_preferences_get, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-module-browser-dialog", dialogs_module_browser_get, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-module-browser-dialog", dialogs_module_browser_get, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-undo-history-dialog", dialogs_undo_history_get, 32, FALSE, FALSE, FALSE, TRUE },
|
|
||||||
{ "gimp-display-filters-dialog", dialogs_display_filters_get, 32, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-display-filters-dialog", dialogs_display_filters_get, 32, FALSE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-tips-dialog", dialogs_tips_get, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-tips-dialog", dialogs_tips_get, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-about-dialog", dialogs_about_get, 32, TRUE, FALSE, FALSE, TRUE }
|
{ "gimp-about-dialog", dialogs_about_get, 32, TRUE, FALSE, FALSE, TRUE }
|
||||||
@ -76,6 +75,7 @@ static const GimpDialogFactoryEntry dock_entries[] =
|
|||||||
{ "gimp-path-list", dialogs_path_list_view_new, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-path-list", dialogs_path_list_view_new, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-indexed-palette", dialogs_indexed_palette_new, 32, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-indexed-palette", dialogs_indexed_palette_new, 32, FALSE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-selection-editor", dialogs_selection_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-selection-editor", dialogs_selection_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
||||||
|
{ "gimp-undo-history", dialogs_undo_history_new, 0, FALSE, FALSE, FALSE, TRUE },
|
||||||
|
|
||||||
{ "gimp-color-editor", dialogs_color_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-color-editor", dialogs_color_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
||||||
|
|
||||||
|
@ -44,7 +44,8 @@
|
|||||||
static void gimp_display_shell_clean_dirty_handler (GimpImage *gimage,
|
static void gimp_display_shell_clean_dirty_handler (GimpImage *gimage,
|
||||||
GimpDisplayShell *shell);
|
GimpDisplayShell *shell);
|
||||||
static void gimp_display_shell_undo_event_handler (GimpImage *gimage,
|
static void gimp_display_shell_undo_event_handler (GimpImage *gimage,
|
||||||
gint event,
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo,
|
||||||
GimpDisplayShell *shell);
|
GimpDisplayShell *shell);
|
||||||
static void gimp_display_shell_name_changed_handler (GimpImage *gimage,
|
static void gimp_display_shell_name_changed_handler (GimpImage *gimage,
|
||||||
GimpDisplayShell *shell);
|
GimpDisplayShell *shell);
|
||||||
@ -267,7 +268,8 @@ gimp_display_shell_clean_dirty_handler (GimpImage *gimage,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_display_shell_undo_event_handler (GimpImage *gimage,
|
gimp_display_shell_undo_event_handler (GimpImage *gimage,
|
||||||
gint event,
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo,
|
||||||
GimpDisplayShell *shell)
|
GimpDisplayShell *shell)
|
||||||
{
|
{
|
||||||
shell->title_dirty = TRUE;
|
shell->title_dirty = TRUE;
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include "widgets/gimpselectioneditor.h"
|
#include "widgets/gimpselectioneditor.h"
|
||||||
#include "widgets/gimptoolbox.h"
|
#include "widgets/gimptoolbox.h"
|
||||||
#include "widgets/gimptoolbox-color-area.h"
|
#include "widgets/gimptoolbox-color-area.h"
|
||||||
|
#include "widgets/gimpundoeditor.h"
|
||||||
#include "widgets/gimpvectorslistview.h"
|
#include "widgets/gimpvectorslistview.h"
|
||||||
|
|
||||||
#include "display/gimpdisplay.h"
|
#include "display/gimpdisplay.h"
|
||||||
@ -82,8 +83,6 @@
|
|||||||
#include "tool-options-dialog.h"
|
#include "tool-options-dialog.h"
|
||||||
#include "vectors-commands.h"
|
#include "vectors-commands.h"
|
||||||
|
|
||||||
#include "undo_history.h"
|
|
||||||
|
|
||||||
#include "libgimp/gimpintl.h"
|
#include "libgimp/gimpintl.h"
|
||||||
|
|
||||||
|
|
||||||
@ -128,6 +127,8 @@ static void dialogs_set_indexed_palette_context_func (GimpDockable *dockable,
|
|||||||
GimpContext *context);
|
GimpContext *context);
|
||||||
static void dialogs_set_selection_editor_context_func (GimpDockable *dockable,
|
static void dialogs_set_selection_editor_context_func (GimpDockable *dockable,
|
||||||
GimpContext *context);
|
GimpContext *context);
|
||||||
|
static void dialogs_set_undo_history_context_func (GimpDockable *dockable,
|
||||||
|
GimpContext *context);
|
||||||
static void dialogs_set_navigation_context_func (GimpDockable *dockable,
|
static void dialogs_set_navigation_context_func (GimpDockable *dockable,
|
||||||
GimpContext *context);
|
GimpContext *context);
|
||||||
|
|
||||||
@ -150,6 +151,9 @@ static void dialogs_indexed_palette_image_changed (GimpContext *context
|
|||||||
static void dialogs_selection_editor_image_changed (GimpContext *context,
|
static void dialogs_selection_editor_image_changed (GimpContext *context,
|
||||||
GimpImage *gimage,
|
GimpImage *gimage,
|
||||||
GimpSelectionEditor *editor);
|
GimpSelectionEditor *editor);
|
||||||
|
static void dialogs_undo_history_image_changed (GimpContext *context,
|
||||||
|
GimpImage *gimage,
|
||||||
|
GimpUndoEditor *editor);
|
||||||
static void dialogs_navigation_display_changed (GimpContext *context,
|
static void dialogs_navigation_display_changed (GimpContext *context,
|
||||||
GimpDisplay *gdisp,
|
GimpDisplay *gdisp,
|
||||||
GimpNavigationView *view);
|
GimpNavigationView *view);
|
||||||
@ -183,31 +187,6 @@ dialogs_module_browser_get (GimpDialogFactory *factory,
|
|||||||
return module_browser_new (context->gimp);
|
return module_browser_new (context->gimp);
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
dialogs_undo_history_get (GimpDialogFactory *factory,
|
|
||||||
GimpContext *context,
|
|
||||||
gint preview_size)
|
|
||||||
{
|
|
||||||
GimpImage *gimage;
|
|
||||||
GtkWidget *undo_history;
|
|
||||||
|
|
||||||
gimage = gimp_context_get_image (context);
|
|
||||||
|
|
||||||
if (! gimage)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
undo_history = g_object_get_data (G_OBJECT (gimage), "gimp-undo-history");
|
|
||||||
|
|
||||||
if (! undo_history)
|
|
||||||
{
|
|
||||||
undo_history = undo_history_new (gimage);
|
|
||||||
|
|
||||||
g_object_set_data (G_OBJECT (gimage), "gimp-undo-history", undo_history);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undo_history;
|
|
||||||
}
|
|
||||||
|
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
dialogs_display_filters_get (GimpDialogFactory *factory,
|
dialogs_display_filters_get (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
@ -795,6 +774,30 @@ dialogs_selection_editor_new (GimpDialogFactory *factory,
|
|||||||
return dockable;
|
return dockable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
dialogs_undo_history_new (GimpDialogFactory *factory,
|
||||||
|
GimpContext *context,
|
||||||
|
gint preview_size)
|
||||||
|
{
|
||||||
|
GimpImage *gimage;
|
||||||
|
GtkWidget *view;
|
||||||
|
GtkWidget *dockable;
|
||||||
|
|
||||||
|
gimage = gimp_context_get_image (context);
|
||||||
|
|
||||||
|
view = gimp_undo_editor_new (gimage);
|
||||||
|
|
||||||
|
dockable = dialogs_dockable_new (view,
|
||||||
|
_("Undo History"), _("Undo"),
|
||||||
|
GTK_STOCK_UNDO,
|
||||||
|
dialogs_stock_text_tab_func,
|
||||||
|
dialogs_set_undo_history_context_func);
|
||||||
|
|
||||||
|
gimp_dockable_set_context (GIMP_DOCKABLE (dockable), context);
|
||||||
|
|
||||||
|
return dockable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***** misc dockables *****/
|
/***** misc dockables *****/
|
||||||
|
|
||||||
@ -1380,6 +1383,41 @@ dialogs_set_selection_editor_context_func (GimpDockable *dockable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dialogs_set_undo_history_context_func (GimpDockable *dockable,
|
||||||
|
GimpContext *context)
|
||||||
|
{
|
||||||
|
GimpUndoEditor *view;
|
||||||
|
|
||||||
|
view = (GimpUndoEditor *) g_object_get_data (G_OBJECT (dockable),
|
||||||
|
"gimp-dialogs-view");
|
||||||
|
|
||||||
|
if (view)
|
||||||
|
{
|
||||||
|
if (dockable->context)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (dockable->context,
|
||||||
|
dialogs_undo_history_image_changed,
|
||||||
|
view);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
g_signal_connect (context, "image_changed",
|
||||||
|
G_CALLBACK (dialogs_undo_history_image_changed),
|
||||||
|
view);
|
||||||
|
|
||||||
|
dialogs_undo_history_image_changed (context,
|
||||||
|
gimp_context_get_image (context),
|
||||||
|
view);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dialogs_undo_history_image_changed (NULL, NULL, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dialogs_set_navigation_context_func (GimpDockable *dockable,
|
dialogs_set_navigation_context_func (GimpDockable *dockable,
|
||||||
GimpContext *context)
|
GimpContext *context)
|
||||||
@ -1470,6 +1508,14 @@ dialogs_selection_editor_image_changed (GimpContext *context,
|
|||||||
gimp_selection_editor_set_image (editor, gimage);
|
gimp_selection_editor_set_image (editor, gimage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dialogs_undo_history_image_changed (GimpContext *context,
|
||||||
|
GimpImage *gimage,
|
||||||
|
GimpUndoEditor *editor)
|
||||||
|
{
|
||||||
|
gimp_undo_editor_set_image (editor, gimage);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dialogs_navigation_display_changed (GimpContext *context,
|
dialogs_navigation_display_changed (GimpContext *context,
|
||||||
GimpDisplay *gdisp,
|
GimpDisplay *gdisp,
|
||||||
|
@ -31,9 +31,6 @@ GtkWidget * dialogs_preferences_get (GimpDialogFactory *factory,
|
|||||||
GtkWidget * dialogs_module_browser_get (GimpDialogFactory *factory,
|
GtkWidget * dialogs_module_browser_get (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gint preview_size);
|
gint preview_size);
|
||||||
GtkWidget * dialogs_undo_history_get (GimpDialogFactory *factory,
|
|
||||||
GimpContext *context,
|
|
||||||
gint preview_size);
|
|
||||||
GtkWidget * dialogs_display_filters_get (GimpDialogFactory *factory,
|
GtkWidget * dialogs_display_filters_get (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gint preview_size);
|
gint preview_size);
|
||||||
@ -126,6 +123,9 @@ GtkWidget * dialogs_indexed_palette_new (GimpDialogFactory *factory,
|
|||||||
GtkWidget * dialogs_selection_editor_new (GimpDialogFactory *factory,
|
GtkWidget * dialogs_selection_editor_new (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gint preview_size);
|
gint preview_size);
|
||||||
|
GtkWidget * dialogs_undo_history_new (GimpDialogFactory *factory,
|
||||||
|
GimpContext *context,
|
||||||
|
gint preview_size);
|
||||||
|
|
||||||
GtkWidget * dialogs_color_editor_new (GimpDialogFactory *factory,
|
GtkWidget * dialogs_color_editor_new (GimpDialogFactory *factory,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
|
@ -67,6 +67,8 @@ GimpItemFactoryEntry dialogs_menu_entries[] =
|
|||||||
"<StockItem>", GIMP_STOCK_TOOL_RECT_SELECT),
|
"<StockItem>", GIMP_STOCK_TOOL_RECT_SELECT),
|
||||||
ADD_TAB (N_("/Add Tab/Navigation..."), "gimp-navigation-view",
|
ADD_TAB (N_("/Add Tab/Navigation..."), "gimp-navigation-view",
|
||||||
"<StockItem>", GIMP_STOCK_NAVIGATION),
|
"<StockItem>", GIMP_STOCK_NAVIGATION),
|
||||||
|
ADD_TAB (N_("/Add Tab/Undo History..."), "gimp-undo-history",
|
||||||
|
"<StockItem>", GTK_STOCK_UNDO),
|
||||||
|
|
||||||
MENU_SEPARATOR ("/Add Tab/---"),
|
MENU_SEPARATOR ("/Add Tab/---"),
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ static const GimpDialogFactoryEntry toplevel_entries[] =
|
|||||||
{ "gimp-device-status-dialog", dialogs_device_status_get, 32, TRUE, TRUE, FALSE, TRUE },
|
{ "gimp-device-status-dialog", dialogs_device_status_get, 32, TRUE, TRUE, FALSE, TRUE },
|
||||||
{ "gimp-preferences-dialog", dialogs_preferences_get, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-preferences-dialog", dialogs_preferences_get, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-module-browser-dialog", dialogs_module_browser_get, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-module-browser-dialog", dialogs_module_browser_get, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-undo-history-dialog", dialogs_undo_history_get, 32, FALSE, FALSE, FALSE, TRUE },
|
|
||||||
{ "gimp-display-filters-dialog", dialogs_display_filters_get, 32, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-display-filters-dialog", dialogs_display_filters_get, 32, FALSE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-tips-dialog", dialogs_tips_get, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-tips-dialog", dialogs_tips_get, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-about-dialog", dialogs_about_get, 32, TRUE, FALSE, FALSE, TRUE }
|
{ "gimp-about-dialog", dialogs_about_get, 32, TRUE, FALSE, FALSE, TRUE }
|
||||||
@ -76,6 +75,7 @@ static const GimpDialogFactoryEntry dock_entries[] =
|
|||||||
{ "gimp-path-list", dialogs_path_list_view_new, 32, TRUE, FALSE, FALSE, TRUE },
|
{ "gimp-path-list", dialogs_path_list_view_new, 32, TRUE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-indexed-palette", dialogs_indexed_palette_new, 32, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-indexed-palette", dialogs_indexed_palette_new, 32, FALSE, FALSE, FALSE, TRUE },
|
||||||
{ "gimp-selection-editor", dialogs_selection_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-selection-editor", dialogs_selection_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
||||||
|
{ "gimp-undo-history", dialogs_undo_history_new, 0, FALSE, FALSE, FALSE, TRUE },
|
||||||
|
|
||||||
{ "gimp-color-editor", dialogs_color_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
{ "gimp-color-editor", dialogs_color_editor_new, 0, FALSE, FALSE, FALSE, TRUE },
|
||||||
|
|
||||||
|
@ -466,13 +466,6 @@ GimpItemFactoryEntry image_menu_entries[] =
|
|||||||
NULL,
|
NULL,
|
||||||
"layers/flatten_image.html", NULL },
|
"layers/flatten_image.html", NULL },
|
||||||
|
|
||||||
MENU_SEPARATOR ("/Image/---"),
|
|
||||||
|
|
||||||
{ { N_("/Image/Undo History..."), NULL,
|
|
||||||
dialogs_create_toplevel_cmd_callback, 0 },
|
|
||||||
"gimp-undo-history-dialog",
|
|
||||||
"dialogs/undo_history.html", NULL },
|
|
||||||
|
|
||||||
/* <Image>/Layer */
|
/* <Image>/Layer */
|
||||||
|
|
||||||
/* <Image>/Layer/Stack */
|
/* <Image>/Layer/Stack */
|
||||||
@ -707,6 +700,11 @@ GimpItemFactoryEntry image_menu_entries[] =
|
|||||||
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
||||||
"gimp-navigation-view",
|
"gimp-navigation-view",
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
{ { N_("/Dialogs/Undo History..."), NULL,
|
||||||
|
dialogs_create_dockable_cmd_callback, 0,
|
||||||
|
"<StockItem>", GTK_STOCK_UNDO },
|
||||||
|
"gimp-undo-history",
|
||||||
|
NULL, NULL },
|
||||||
|
|
||||||
MENU_SEPARATOR ("/Dialogs/---"),
|
MENU_SEPARATOR ("/Dialogs/---"),
|
||||||
|
|
||||||
@ -1277,7 +1275,6 @@ image_menu_update (GtkItemFactory *item_factory,
|
|||||||
SET_SENSITIVE ("/Image/Duplicate", gdisp);
|
SET_SENSITIVE ("/Image/Duplicate", gdisp);
|
||||||
SET_SENSITIVE ("/Image/Merge Visible Layers...", gdisp && !fs && !aux && lp);
|
SET_SENSITIVE ("/Image/Merge Visible Layers...", gdisp && !fs && !aux && lp);
|
||||||
SET_SENSITIVE ("/Image/Flatten Image", gdisp && !fs && !aux && lp);
|
SET_SENSITIVE ("/Image/Flatten Image", gdisp && !fs && !aux && lp);
|
||||||
SET_SENSITIVE ("/Image/Undo History...", gdisp);
|
|
||||||
|
|
||||||
/* Layer */
|
/* Layer */
|
||||||
|
|
||||||
|
@ -125,6 +125,11 @@ GimpItemFactoryEntry toolbox_menu_entries[] =
|
|||||||
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
||||||
"gimp-navigation-view",
|
"gimp-navigation-view",
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
{ { N_("/File/Dialogs/Undo History..."), NULL,
|
||||||
|
dialogs_create_dockable_cmd_callback, 0,
|
||||||
|
"<StockItem>", GTK_STOCK_UNDO },
|
||||||
|
"gimp-undo-history",
|
||||||
|
NULL, NULL },
|
||||||
|
|
||||||
MENU_SEPARATOR ("/File/Dialogs/---"),
|
MENU_SEPARATOR ("/File/Dialogs/---"),
|
||||||
|
|
||||||
|
@ -466,13 +466,6 @@ GimpItemFactoryEntry image_menu_entries[] =
|
|||||||
NULL,
|
NULL,
|
||||||
"layers/flatten_image.html", NULL },
|
"layers/flatten_image.html", NULL },
|
||||||
|
|
||||||
MENU_SEPARATOR ("/Image/---"),
|
|
||||||
|
|
||||||
{ { N_("/Image/Undo History..."), NULL,
|
|
||||||
dialogs_create_toplevel_cmd_callback, 0 },
|
|
||||||
"gimp-undo-history-dialog",
|
|
||||||
"dialogs/undo_history.html", NULL },
|
|
||||||
|
|
||||||
/* <Image>/Layer */
|
/* <Image>/Layer */
|
||||||
|
|
||||||
/* <Image>/Layer/Stack */
|
/* <Image>/Layer/Stack */
|
||||||
@ -707,6 +700,11 @@ GimpItemFactoryEntry image_menu_entries[] =
|
|||||||
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
||||||
"gimp-navigation-view",
|
"gimp-navigation-view",
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
{ { N_("/Dialogs/Undo History..."), NULL,
|
||||||
|
dialogs_create_dockable_cmd_callback, 0,
|
||||||
|
"<StockItem>", GTK_STOCK_UNDO },
|
||||||
|
"gimp-undo-history",
|
||||||
|
NULL, NULL },
|
||||||
|
|
||||||
MENU_SEPARATOR ("/Dialogs/---"),
|
MENU_SEPARATOR ("/Dialogs/---"),
|
||||||
|
|
||||||
@ -1277,7 +1275,6 @@ image_menu_update (GtkItemFactory *item_factory,
|
|||||||
SET_SENSITIVE ("/Image/Duplicate", gdisp);
|
SET_SENSITIVE ("/Image/Duplicate", gdisp);
|
||||||
SET_SENSITIVE ("/Image/Merge Visible Layers...", gdisp && !fs && !aux && lp);
|
SET_SENSITIVE ("/Image/Merge Visible Layers...", gdisp && !fs && !aux && lp);
|
||||||
SET_SENSITIVE ("/Image/Flatten Image", gdisp && !fs && !aux && lp);
|
SET_SENSITIVE ("/Image/Flatten Image", gdisp && !fs && !aux && lp);
|
||||||
SET_SENSITIVE ("/Image/Undo History...", gdisp);
|
|
||||||
|
|
||||||
/* Layer */
|
/* Layer */
|
||||||
|
|
||||||
|
@ -125,6 +125,11 @@ GimpItemFactoryEntry toolbox_menu_entries[] =
|
|||||||
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
"<StockItem>", GIMP_STOCK_NAVIGATION },
|
||||||
"gimp-navigation-view",
|
"gimp-navigation-view",
|
||||||
NULL, NULL },
|
NULL, NULL },
|
||||||
|
{ { N_("/File/Dialogs/Undo History..."), NULL,
|
||||||
|
dialogs_create_dockable_cmd_callback, 0,
|
||||||
|
"<StockItem>", GTK_STOCK_UNDO },
|
||||||
|
"gimp-undo-history",
|
||||||
|
NULL, NULL },
|
||||||
|
|
||||||
MENU_SEPARATOR ("/File/Dialogs/---"),
|
MENU_SEPARATOR ("/File/Dialogs/---"),
|
||||||
|
|
||||||
|
@ -44,11 +44,9 @@ struct _PaintUndo
|
|||||||
};
|
};
|
||||||
|
|
||||||
static gboolean undo_pop_paint (GimpUndo *undo,
|
static gboolean undo_pop_paint (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum);
|
GimpUndoAccumulator *accum);
|
||||||
static void undo_free_paint (GimpUndo *undo,
|
static void undo_free_paint (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
GimpUndoMode undo_mode);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -86,7 +84,6 @@ gimp_paint_core_push_undo (GimpImage *gimage,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
undo_pop_paint (GimpUndo *undo,
|
undo_pop_paint (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum)
|
GimpUndoAccumulator *accum)
|
||||||
{
|
{
|
||||||
@ -109,7 +106,6 @@ undo_pop_paint (GimpUndo *undo,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
undo_free_paint (GimpUndo *undo,
|
undo_free_paint (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode)
|
GimpUndoMode undo_mode)
|
||||||
{
|
{
|
||||||
PaintUndo *pu;
|
PaintUndo *pu;
|
||||||
|
@ -54,11 +54,9 @@ struct _TransformUndo
|
|||||||
};
|
};
|
||||||
|
|
||||||
static gboolean undo_pop_transform (GimpUndo *undo,
|
static gboolean undo_pop_transform (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum);
|
GimpUndoAccumulator *accum);
|
||||||
static void undo_free_transform (GimpUndo *undo,
|
static void undo_free_transform (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode);
|
GimpUndoMode undo_mode);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -102,13 +100,12 @@ gimp_transform_tool_push_undo (GimpImage *gimage,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
undo_pop_transform (GimpUndo *undo,
|
undo_pop_transform (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode,
|
GimpUndoMode undo_mode,
|
||||||
GimpUndoAccumulator *accum)
|
GimpUndoAccumulator *accum)
|
||||||
{
|
{
|
||||||
GimpTool *active_tool;
|
GimpTool *active_tool;
|
||||||
|
|
||||||
active_tool = tool_manager_get_active (gimage->gimp);
|
active_tool = tool_manager_get_active (undo->gimage->gimp);
|
||||||
|
|
||||||
if (GIMP_IS_TRANSFORM_TOOL (active_tool))
|
if (GIMP_IS_TRANSFORM_TOOL (active_tool))
|
||||||
{
|
{
|
||||||
@ -118,7 +115,7 @@ undo_pop_transform (GimpUndo *undo,
|
|||||||
tt = GIMP_TRANSFORM_TOOL (active_tool);
|
tt = GIMP_TRANSFORM_TOOL (active_tool);
|
||||||
tu = (TransformUndo *) undo->data;
|
tu = (TransformUndo *) undo->data;
|
||||||
|
|
||||||
path_transform_do_undo (gimage, tu->path_undo);
|
path_transform_do_undo (undo->gimage, tu->path_undo);
|
||||||
|
|
||||||
/* only pop if the active tool is the tool that pushed this undo */
|
/* only pop if the active tool is the tool that pushed this undo */
|
||||||
if (tu->tool_ID == active_tool->ID)
|
if (tu->tool_ID == active_tool->ID)
|
||||||
@ -156,7 +153,6 @@ undo_pop_transform (GimpUndo *undo,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
undo_free_transform (GimpUndo *undo,
|
undo_free_transform (GimpUndo *undo,
|
||||||
GimpImage *gimage,
|
|
||||||
GimpUndoMode undo_mode)
|
GimpUndoMode undo_mode)
|
||||||
{
|
{
|
||||||
TransformUndo * tu;
|
TransformUndo * tu;
|
||||||
@ -165,6 +161,8 @@ undo_free_transform (GimpUndo *undo,
|
|||||||
|
|
||||||
if (tu->original)
|
if (tu->original)
|
||||||
tile_manager_destroy (tu->original);
|
tile_manager_destroy (tu->original);
|
||||||
|
|
||||||
path_transform_free_undo (tu->path_undo);
|
path_transform_free_undo (tu->path_undo);
|
||||||
|
|
||||||
g_free (tu);
|
g_free (tu);
|
||||||
}
|
}
|
||||||
|
@ -1,917 +0,0 @@
|
|||||||
/* 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:
|
|
||||||
*
|
|
||||||
* - reuse the L&C previews?
|
|
||||||
* Currently we use gimp_image_construct_composite_preview ()
|
|
||||||
* which makes use of the preview_cache on a per layer basis.
|
|
||||||
*
|
|
||||||
* - work out which (if any) is the clean image, and mark it as such.
|
|
||||||
* Currently, it's on the wrong line.
|
|
||||||
*
|
|
||||||
* - 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 pixmap in wrong place
|
|
||||||
*
|
|
||||||
* Initial rev 0.01, (c) 19 Sept 1999 Austin Donnelly <austin@gimp.org>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#warning GTK_DISABLE_DEPRECATED
|
|
||||||
#endif
|
|
||||||
#undef GTK_DISABLE_DEPRECATED
|
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#include "libgimpbase/gimpbase.h"
|
|
||||||
#include "libgimpwidgets/gimpwidgets.h"
|
|
||||||
|
|
||||||
#include "display/display-types.h"
|
|
||||||
|
|
||||||
#include "config/gimpcoreconfig.h"
|
|
||||||
|
|
||||||
#include "base/pixel-region.h"
|
|
||||||
#include "base/temp-buf.h"
|
|
||||||
|
|
||||||
#include "paint-funcs/paint-funcs.h"
|
|
||||||
|
|
||||||
#include "core/gimp.h"
|
|
||||||
#include "core/gimpcontainer.h"
|
|
||||||
#include "core/gimpdrawable.h"
|
|
||||||
#include "core/gimpimage.h"
|
|
||||||
#include "core/gimpimage-mask.h"
|
|
||||||
#include "core/gimpimage-undo.h"
|
|
||||||
#include "core/gimpundostack.h"
|
|
||||||
|
|
||||||
#include "file/file-utils.h"
|
|
||||||
|
|
||||||
#include "widgets/gimpviewabledialog.h"
|
|
||||||
|
|
||||||
#include "libgimp/gimpintl.h"
|
|
||||||
|
|
||||||
#include "pixmaps/yes.xpm"
|
|
||||||
#include "pixmaps/question.xpm"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GimpImage *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 */
|
|
||||||
int preview_size; /* size of the previews (from preferences) */
|
|
||||||
} undo_history_st;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GtkCList *clist;
|
|
||||||
gint row;
|
|
||||||
gint size;
|
|
||||||
GimpImage *gimage;
|
|
||||||
} idle_preview_args;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**************************************************************/
|
|
||||||
/* Static Data */
|
|
||||||
|
|
||||||
static GdkPixmap *clean_pixmap = NULL;
|
|
||||||
static GdkBitmap *clean_mask = NULL;
|
|
||||||
|
|
||||||
static GdkPixmap *clear_pixmap = NULL;
|
|
||||||
static GdkBitmap *clear_mask = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static void undo_history_undo_event (GtkWidget *widget,
|
|
||||||
gint ev,
|
|
||||||
gpointer data);
|
|
||||||
static void undo_history_clean_callback (GtkWidget *widget,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
static void undo_history_select_row_callback (GtkWidget *widget,
|
|
||||||
gint row,
|
|
||||||
gint column,
|
|
||||||
gpointer event,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************/
|
|
||||||
/* Local functions */
|
|
||||||
|
|
||||||
|
|
||||||
static MaskBuf *
|
|
||||||
mask_render_preview (GimpImage *gimage,
|
|
||||||
gint *pwidth,
|
|
||||||
gint *pheight)
|
|
||||||
{
|
|
||||||
GimpChannel *mask;
|
|
||||||
MaskBuf *scaled_buf = NULL;
|
|
||||||
PixelRegion srcPR, destPR;
|
|
||||||
gint subsample;
|
|
||||||
gint width, height;
|
|
||||||
gint scale;
|
|
||||||
|
|
||||||
mask = gimp_image_get_mask (gimage);
|
|
||||||
if ((gimp_drawable_width (GIMP_DRAWABLE(mask)) > *pwidth) ||
|
|
||||||
(gimp_drawable_height (GIMP_DRAWABLE(mask)) > *pheight))
|
|
||||||
{
|
|
||||||
if (((gfloat) gimp_drawable_width (GIMP_DRAWABLE (mask)) / (gfloat) *pwidth) >
|
|
||||||
((gfloat) gimp_drawable_height (GIMP_DRAWABLE (mask)) / (gfloat) *pheight))
|
|
||||||
{
|
|
||||||
width = *pwidth;
|
|
||||||
height = (gimp_drawable_height (GIMP_DRAWABLE (mask)) * (*pwidth)) / gimp_drawable_width (GIMP_DRAWABLE (mask));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = (gimp_drawable_width (GIMP_DRAWABLE (mask)) * (*pheight)) / gimp_drawable_height (GIMP_DRAWABLE (mask));
|
|
||||||
height = *pheight;
|
|
||||||
}
|
|
||||||
|
|
||||||
scale = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = gimp_drawable_width (GIMP_DRAWABLE (mask));
|
|
||||||
height = gimp_drawable_height (GIMP_DRAWABLE (mask));
|
|
||||||
|
|
||||||
scale = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if the mask is empty, no need to scale and update again */
|
|
||||||
if (gimp_image_mask_is_empty (gimage))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (scale)
|
|
||||||
{
|
|
||||||
/* calculate 'acceptable' subsample */
|
|
||||||
subsample = 1;
|
|
||||||
while ((width * (subsample + 1) * 2 < gimp_drawable_width (GIMP_DRAWABLE (mask))) &&
|
|
||||||
(height * (subsample + 1) * 2 < gimp_drawable_height (GIMP_DRAWABLE (mask))))
|
|
||||||
subsample = subsample + 1;
|
|
||||||
|
|
||||||
pixel_region_init (&srcPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
|
|
||||||
0, 0,
|
|
||||||
gimp_drawable_width (GIMP_DRAWABLE (mask)),
|
|
||||||
gimp_drawable_height (GIMP_DRAWABLE (mask)), FALSE);
|
|
||||||
|
|
||||||
scaled_buf = mask_buf_new (width, height);
|
|
||||||
destPR.bytes = 1;
|
|
||||||
destPR.x = 0;
|
|
||||||
destPR.y = 0;
|
|
||||||
destPR.w = width;
|
|
||||||
destPR.h = height;
|
|
||||||
destPR.rowstride = srcPR.bytes * width;
|
|
||||||
destPR.data = mask_buf_data (scaled_buf);
|
|
||||||
destPR.tiles = NULL;
|
|
||||||
|
|
||||||
subsample_region (&srcPR, &destPR, subsample);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixel_region_init (&srcPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
|
|
||||||
0, 0,
|
|
||||||
gimp_drawable_width (GIMP_DRAWABLE (mask)),
|
|
||||||
gimp_drawable_height (GIMP_DRAWABLE (mask)), FALSE);
|
|
||||||
|
|
||||||
scaled_buf = mask_buf_new (width, height);
|
|
||||||
destPR.bytes = 1;
|
|
||||||
destPR.x = 0;
|
|
||||||
destPR.y = 0;
|
|
||||||
destPR.w = width;
|
|
||||||
destPR.h = height;
|
|
||||||
destPR.rowstride = srcPR.bytes * width;
|
|
||||||
destPR.data = mask_buf_data (scaled_buf);
|
|
||||||
destPR.tiles = NULL;
|
|
||||||
|
|
||||||
copy_region (&srcPR, &destPR);
|
|
||||||
}
|
|
||||||
|
|
||||||
*pheight = height;
|
|
||||||
*pwidth = width;
|
|
||||||
return scaled_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static gint
|
|
||||||
undo_history_set_pixmap_idle (gpointer data)
|
|
||||||
{
|
|
||||||
idle_preview_args *idle = data;
|
|
||||||
static GdkGC *gc = NULL;
|
|
||||||
TempBuf *buf = NULL;
|
|
||||||
GdkPixmap *pixmap;
|
|
||||||
GimpUndoType utype;
|
|
||||||
MaskBuf *mbuf = NULL;
|
|
||||||
guchar *src;
|
|
||||||
gdouble r, g, b, a;
|
|
||||||
gdouble c0, c1;
|
|
||||||
guchar *p0, *p1, *even, *odd;
|
|
||||||
gint width, height, bpp;
|
|
||||||
gint x, y;
|
|
||||||
|
|
||||||
if (!gc)
|
|
||||||
gc = gdk_gc_new (GTK_WIDGET (idle->clist)->window);
|
|
||||||
|
|
||||||
width = idle->gimage->width;
|
|
||||||
height = idle->gimage->height;
|
|
||||||
|
|
||||||
/* Get right aspect ratio */
|
|
||||||
if (width > height)
|
|
||||||
{
|
|
||||||
height = (gint)(((gdouble)idle->size * (gdouble)height) / (gdouble)width + 0.5);
|
|
||||||
width = (gint)(((gdouble)width * (gdouble)height)/ (gdouble)idle->gimage->height + 0.5);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = (gint)(((gdouble)idle->size * (gdouble)width) / (gdouble)height + 0.5);
|
|
||||||
height = (gint)(((gdouble)height * (gdouble)width ) /(gdouble) idle->gimage->width + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
utype = gimp_undo_stack_peek (idle->gimage->undo_stack)->undo_type;
|
|
||||||
|
|
||||||
if ((utype != GIMP_UNDO_MASK && utype != GIMP_UNDO_IMAGE_QMASK) ||
|
|
||||||
(mbuf = mask_render_preview (idle->gimage, &width, &height)) == NULL)
|
|
||||||
{
|
|
||||||
buf = gimp_viewable_get_new_preview (GIMP_VIEWABLE (idle->gimage),
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
bpp = buf->bytes;
|
|
||||||
src = temp_buf_data (buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src = mask_buf_data (mbuf);
|
|
||||||
bpp = 1; /* Always the case for masks */
|
|
||||||
}
|
|
||||||
|
|
||||||
pixmap = gdk_pixmap_new (GTK_WIDGET (idle->clist)->window,
|
|
||||||
width + 2, height + 2,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
gdk_draw_rectangle (pixmap,
|
|
||||||
GTK_WIDGET (idle->clist)->style->black_gc,
|
|
||||||
TRUE,
|
|
||||||
0, 0,
|
|
||||||
width + 2, height + 2);
|
|
||||||
|
|
||||||
even = g_malloc (width * 3);
|
|
||||||
odd = g_malloc (width * 3);
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
p0 = even;
|
|
||||||
p1 = odd;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
if (bpp == 4)
|
|
||||||
{
|
|
||||||
r = ((gdouble) src[x*4+0]) / 255.0;
|
|
||||||
g = ((gdouble) src[x*4+1]) / 255.0;
|
|
||||||
b = ((gdouble) src[x*4+2]) / 255.0;
|
|
||||||
a = ((gdouble) src[x*4+3]) / 255.0;
|
|
||||||
}
|
|
||||||
else if (bpp == 3)
|
|
||||||
{
|
|
||||||
r = ((gdouble) src[x*3+0]) / 255.0;
|
|
||||||
g = ((gdouble) src[x*3+1]) / 255.0;
|
|
||||||
b = ((gdouble) src[x*3+2]) / 255.0;
|
|
||||||
a = 1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r = ((gdouble) src[x*bpp+0]) / 255.0;
|
|
||||||
g = b = r;
|
|
||||||
if (bpp == 2)
|
|
||||||
a = ((gdouble) src[x*bpp+1]) / 255.0;
|
|
||||||
else
|
|
||||||
a = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((x / GIMP_CHECK_SIZE_SM) & 1)
|
|
||||||
{
|
|
||||||
c0 = GIMP_CHECK_LIGHT;
|
|
||||||
c1 = GIMP_CHECK_DARK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c0 = GIMP_CHECK_DARK;
|
|
||||||
c1 = GIMP_CHECK_LIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*p0++ = (c0 + (r - c0) * a) * 255.0;
|
|
||||||
*p0++ = (c0 + (g - c0) * a) * 255.0;
|
|
||||||
*p0++ = (c0 + (b - c0) * a) * 255.0;
|
|
||||||
|
|
||||||
*p1++ = (c1 + (r - c1) * a) * 255.0;
|
|
||||||
*p1++ = (c1 + (g - c1) * a) * 255.0;
|
|
||||||
*p1++ = (c1 + (b - c1) * a) * 255.0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((y / GIMP_CHECK_SIZE_SM) & 1)
|
|
||||||
{
|
|
||||||
gdk_draw_rgb_image (pixmap, gc,
|
|
||||||
1, y + 1,
|
|
||||||
width, 1,
|
|
||||||
GDK_RGB_DITHER_NORMAL,
|
|
||||||
(guchar *) odd, 3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdk_draw_rgb_image (pixmap, gc,
|
|
||||||
1, y + 1,
|
|
||||||
width, 1,
|
|
||||||
GDK_RGB_DITHER_NORMAL,
|
|
||||||
(guchar *) even, 3);
|
|
||||||
}
|
|
||||||
src += width * bpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (even);
|
|
||||||
g_free (odd);
|
|
||||||
|
|
||||||
if (buf)
|
|
||||||
temp_buf_free (buf);
|
|
||||||
if (mbuf)
|
|
||||||
mask_buf_free (mbuf);
|
|
||||||
|
|
||||||
gtk_clist_set_row_data (idle->clist, idle->row, (gpointer)2);
|
|
||||||
gtk_clist_set_pixmap (idle->clist, idle->row, 0, pixmap, NULL);
|
|
||||||
g_object_unref (pixmap);
|
|
||||||
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if a preview is already made, otherwise g_idle_add the pixmap func */
|
|
||||||
static void
|
|
||||||
undo_history_set_pixmap (GtkCList *clist,
|
|
||||||
gint row,
|
|
||||||
gint size,
|
|
||||||
GimpImage *gimage)
|
|
||||||
{
|
|
||||||
static idle_preview_args idle;
|
|
||||||
|
|
||||||
if (!size || (GPOINTER_TO_INT (gtk_clist_get_row_data (clist, row))) == 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
idle.clist = clist;
|
|
||||||
idle.row = row;
|
|
||||||
idle.size = size;
|
|
||||||
idle.gimage = gimage;
|
|
||||||
|
|
||||||
g_idle_add (undo_history_set_pixmap_idle, &idle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* close button clicked */
|
|
||||||
static void
|
|
||||||
undo_history_close_callback (GtkWidget *widget,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
gtk_widget_hide (GTK_WIDGET (st->shell));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 renamed */
|
|
||||||
static void
|
|
||||||
undo_history_gimage_rename_callback (GimpImage *gimage,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
gchar *basename;
|
|
||||||
gchar *title;
|
|
||||||
|
|
||||||
basename = g_path_get_basename (gimp_image_get_uri (gimage));
|
|
||||||
|
|
||||||
title = g_strdup_printf (_("Undo History: %s"), basename);
|
|
||||||
|
|
||||||
g_free (basename);
|
|
||||||
|
|
||||||
gtk_window_set_title (GTK_WINDOW (st->shell), title);
|
|
||||||
|
|
||||||
g_free (title);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
undo_history_shell_destroy_callback (GtkWidget *widget,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
|
|
||||||
if (st->gimage)
|
|
||||||
{
|
|
||||||
g_signal_handlers_disconnect_by_func (st->gimage,
|
|
||||||
undo_history_undo_event,
|
|
||||||
st);
|
|
||||||
g_signal_handlers_disconnect_by_func (st->gimage,
|
|
||||||
undo_history_gimage_rename_callback,
|
|
||||||
st);
|
|
||||||
g_signal_handlers_disconnect_by_func (st->gimage,
|
|
||||||
undo_history_clean_callback,
|
|
||||||
st);
|
|
||||||
g_object_unref (st->gimage);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (st);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* undo button clicked */
|
|
||||||
static void
|
|
||||||
undo_history_undo_callback (GtkWidget *widget,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
|
|
||||||
if (gimp_image_undo (st->gimage))
|
|
||||||
gimp_image_flush (st->gimage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* redo button clicked */
|
|
||||||
static void
|
|
||||||
undo_history_redo_callback (GtkWidget *widget,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
|
|
||||||
if (gimp_image_redo (st->gimage))
|
|
||||||
gimp_image_flush (st->gimage);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Always start clist with dummy entry for image state before
|
|
||||||
* the first action on the undo stack */
|
|
||||||
static void
|
|
||||||
undo_history_prepend_special (GtkCList *clist)
|
|
||||||
{
|
|
||||||
gchar *name = _("[ base image ]");
|
|
||||||
gchar *namelist[3];
|
|
||||||
gint row;
|
|
||||||
|
|
||||||
namelist[0] = NULL;
|
|
||||||
namelist[1] = NULL;
|
|
||||||
namelist[2] = name;
|
|
||||||
|
|
||||||
row = gtk_clist_prepend (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,
|
|
||||||
gint 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,
|
|
||||||
gint ev,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
undo_event_t event = ev;
|
|
||||||
const gchar *name;
|
|
||||||
gchar *namelist[3];
|
|
||||||
GList *list;
|
|
||||||
gint cur_selection;
|
|
||||||
GtkCList *clist;
|
|
||||||
gint row;
|
|
||||||
GdkPixmap *pixmap;
|
|
||||||
GdkBitmap *mask;
|
|
||||||
|
|
||||||
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 */
|
|
||||||
g_signal_handlers_block_by_func (st->clist,
|
|
||||||
undo_history_select_row_callback,
|
|
||||||
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 = gimp_object_get_name (GIMP_OBJECT (gimp_undo_stack_peek (st->gimage->undo_stack)));
|
|
||||||
namelist[0] = NULL;
|
|
||||||
namelist[1] = NULL;
|
|
||||||
namelist[2] = (char *) name;
|
|
||||||
row = gtk_clist_append (clist, namelist);
|
|
||||||
g_assert (clist->rows == cur_selection + 2);
|
|
||||||
|
|
||||||
undo_history_set_pixmap (clist, row, st->preview_size, st->gimage);
|
|
||||||
|
|
||||||
/* always force selection to bottom, and scroll to it */
|
|
||||||
gtk_clist_select_row (clist, clist->rows - 1, -1);
|
|
||||||
gtk_clist_thaw (clist);
|
|
||||||
gtk_clist_moveto (clist, clist->rows - 1, 0, 1.0, 0.0);
|
|
||||||
cur_selection = clist->rows - 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNDO_EXPIRED:
|
|
||||||
/* remove earliest row, but not our special first one */
|
|
||||||
if (gtk_clist_get_pixmap (clist, 1, 0, &pixmap, &mask))
|
|
||||||
gtk_clist_set_pixmap (clist, 0, 0, pixmap, mask);
|
|
||||||
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--;
|
|
||||||
undo_history_set_pixmap (clist, cur_selection, st->preview_size, st->gimage);
|
|
||||||
if ( !(gtk_clist_row_is_visible (clist, cur_selection) & GTK_VISIBILITY_FULL))
|
|
||||||
gtk_clist_moveto (clist, cur_selection, 0, 0.0, 0.0);
|
|
||||||
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++;
|
|
||||||
undo_history_set_pixmap (clist, cur_selection, st->preview_size, st->gimage);
|
|
||||||
if ( !(gtk_clist_row_is_visible (clist, cur_selection) & GTK_VISIBILITY_FULL))
|
|
||||||
gtk_clist_moveto (clist, cur_selection, 0, 1.0, 0.0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNDO_FREE:
|
|
||||||
/* clear all info other that the special first line */
|
|
||||||
gtk_clist_freeze (clist);
|
|
||||||
gtk_clist_clear (clist);
|
|
||||||
undo_history_prepend_special (clist);
|
|
||||||
gtk_clist_thaw (clist);
|
|
||||||
cur_selection = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if the image is clean, set the clean pixmap */
|
|
||||||
if (st->gimage->dirty == 0)
|
|
||||||
gtk_clist_set_pixmap (clist, cur_selection, 1, clean_pixmap, clean_mask);
|
|
||||||
|
|
||||||
g_signal_handlers_unblock_by_func (st->clist,
|
|
||||||
undo_history_select_row_callback,
|
|
||||||
st);
|
|
||||||
|
|
||||||
st->old_selection = cur_selection;
|
|
||||||
undo_history_set_sensitive (st, clist->rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
undo_history_select_row_callback (GtkWidget *widget,
|
|
||||||
gint row,
|
|
||||||
gint column,
|
|
||||||
gpointer event,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
gint 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. */
|
|
||||||
g_signal_handlers_block_by_func (st->gimage,
|
|
||||||
undo_history_undo_event, st);
|
|
||||||
|
|
||||||
while (cur_selection < st->old_selection)
|
|
||||||
{
|
|
||||||
gimp_image_undo (st->gimage);
|
|
||||||
st->old_selection--;
|
|
||||||
}
|
|
||||||
while (cur_selection > st->old_selection)
|
|
||||||
{
|
|
||||||
gimp_image_redo (st->gimage);
|
|
||||||
st->old_selection++;
|
|
||||||
}
|
|
||||||
|
|
||||||
gimp_image_flush (st->gimage);
|
|
||||||
|
|
||||||
undo_history_set_pixmap (GTK_CLIST (widget),
|
|
||||||
cur_selection, st->preview_size, st->gimage);
|
|
||||||
|
|
||||||
/* if the image is clean, set the clean pixmap */
|
|
||||||
if (st->gimage->dirty == 0)
|
|
||||||
gtk_clist_set_pixmap (GTK_CLIST (widget),
|
|
||||||
cur_selection, 1, clean_pixmap, clean_mask);
|
|
||||||
|
|
||||||
g_signal_handlers_unblock_by_func (st->gimage,
|
|
||||||
undo_history_undo_event, st);
|
|
||||||
|
|
||||||
undo_history_set_sensitive (st, GTK_CLIST(st->clist)->rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
undo_history_clean_callback (GtkWidget *widget,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
gint i;
|
|
||||||
gint nrows;
|
|
||||||
GtkCList *clist;
|
|
||||||
|
|
||||||
if (st->gimage->dirty != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The image has become clean. Remove the clean_pixmap from
|
|
||||||
* all entries. It will be set in the undo_event or select_row
|
|
||||||
* callbacks.
|
|
||||||
* Ugly, but works better than before. The actual problem is
|
|
||||||
* that the "clean" signal is emitted before UNDO_POPPED event,
|
|
||||||
* so we can not simply set the clean pixmap here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
clist = GTK_CLIST (st->clist);
|
|
||||||
nrows = clist->rows;
|
|
||||||
|
|
||||||
gtk_clist_freeze (clist);
|
|
||||||
for (i=0; i < nrows; i++)
|
|
||||||
gtk_clist_set_text (clist, i, 1, NULL);
|
|
||||||
gtk_clist_thaw (clist);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Used to build up initial contents of clist */
|
|
||||||
static void
|
|
||||||
undo_history_init_undo (gpointer undo,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
gchar *namelist[3];
|
|
||||||
gint row;
|
|
||||||
|
|
||||||
namelist[0] = NULL;
|
|
||||||
namelist[1] = NULL;
|
|
||||||
namelist[2] = (gchar *) gimp_object_get_name (GIMP_OBJECT (undo));
|
|
||||||
row = gtk_clist_prepend (GTK_CLIST (st->clist), namelist);
|
|
||||||
gtk_clist_set_pixmap (GTK_CLIST (st->clist), row, 0,
|
|
||||||
clear_pixmap, clear_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
undo_history_init_redo (gpointer undo,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
undo_history_st *st = data;
|
|
||||||
gchar *namelist[3];
|
|
||||||
gint row;
|
|
||||||
|
|
||||||
namelist[0] = NULL; namelist[1] = NULL;
|
|
||||||
namelist[1] = NULL;
|
|
||||||
namelist[2] = (gchar *) gimp_object_get_name (GIMP_OBJECT (undo));
|
|
||||||
row = gtk_clist_append (GTK_CLIST (st->clist), namelist);
|
|
||||||
gtk_clist_set_pixmap (GTK_CLIST (st->clist), row, 0,
|
|
||||||
clear_pixmap, clear_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************/
|
|
||||||
/* Publicly exported function */
|
|
||||||
|
|
||||||
GtkWidget *
|
|
||||||
undo_history_new (GimpImage *gimage)
|
|
||||||
{
|
|
||||||
undo_history_st *st;
|
|
||||||
GtkWidget *vbox;
|
|
||||||
GtkWidget *hbox;
|
|
||||||
GtkWidget *button;
|
|
||||||
GtkWidget *scrolled_win;
|
|
||||||
|
|
||||||
st = g_new0 (undo_history_st, 1);
|
|
||||||
st->gimage = gimage;
|
|
||||||
g_object_ref (gimage);
|
|
||||||
st->preview_size = gimage->gimp->config->preview_size;
|
|
||||||
|
|
||||||
/* gimage signals */
|
|
||||||
g_signal_connect (gimage, "undo_event",
|
|
||||||
G_CALLBACK (undo_history_undo_event),
|
|
||||||
st);
|
|
||||||
g_signal_connect (gimage, "name_changed",
|
|
||||||
G_CALLBACK (undo_history_gimage_rename_callback),
|
|
||||||
st);
|
|
||||||
g_signal_connect (gimage, "clean",
|
|
||||||
G_CALLBACK (undo_history_clean_callback),
|
|
||||||
st);
|
|
||||||
|
|
||||||
/* The shell and main vbox */
|
|
||||||
st->shell =
|
|
||||||
gimp_viewable_dialog_new (GIMP_VIEWABLE (gimage),
|
|
||||||
_("Undo History"), "undo_history",
|
|
||||||
GTK_STOCK_UNDO,
|
|
||||||
_("Image Undo History"),
|
|
||||||
gimp_standard_help_func,
|
|
||||||
"dialogs/undo_history.html",
|
|
||||||
|
|
||||||
GTK_STOCK_CLOSE, undo_history_close_callback,
|
|
||||||
st, NULL, NULL, TRUE, TRUE,
|
|
||||||
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
vbox = gtk_vbox_new (FALSE, 2);
|
|
||||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
|
|
||||||
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (st->shell)->vbox), vbox);
|
|
||||||
gtk_widget_show (vbox);
|
|
||||||
|
|
||||||
g_signal_connect (st->shell, "destroy",
|
|
||||||
G_CALLBACK (undo_history_shell_destroy_callback),
|
|
||||||
st);
|
|
||||||
|
|
||||||
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
|
|
||||||
gtk_widget_set_usize (GTK_WIDGET (scrolled_win),
|
|
||||||
160 + st->preview_size,
|
|
||||||
4 * (MAX (st->preview_size, 16) + 6));
|
|
||||||
|
|
||||||
/* clist of undo actions */
|
|
||||||
st->clist = gtk_clist_new (3);
|
|
||||||
gtk_clist_set_selection_mode (GTK_CLIST (st->clist), GTK_SELECTION_BROWSE);
|
|
||||||
gtk_clist_set_reorderable (GTK_CLIST (st->clist), FALSE);
|
|
||||||
gtk_clist_set_row_height (GTK_CLIST (st->clist), MAX (st->preview_size, 16) + 4);
|
|
||||||
gtk_clist_set_column_width (GTK_CLIST (st->clist), 0, st->preview_size + 2);
|
|
||||||
gtk_clist_set_column_width (GTK_CLIST (st->clist), 1, 18);
|
|
||||||
gtk_clist_set_column_min_width (GTK_CLIST (st->clist), 2, 64);
|
|
||||||
|
|
||||||
/* allocate the pixmaps if not already done */
|
|
||||||
if (!clean_pixmap)
|
|
||||||
{
|
|
||||||
GtkStyle *style;
|
|
||||||
|
|
||||||
gtk_widget_realize (st->shell);
|
|
||||||
style = gtk_widget_get_style (st->shell);
|
|
||||||
|
|
||||||
clean_pixmap =
|
|
||||||
gdk_pixmap_create_from_xpm_d (st->shell->window,
|
|
||||||
&clean_mask,
|
|
||||||
&style->bg[GTK_STATE_NORMAL],
|
|
||||||
yes_xpm);
|
|
||||||
|
|
||||||
clear_pixmap =
|
|
||||||
gdk_pixmap_create_from_xpm_d (st->shell->window,
|
|
||||||
&clear_mask,
|
|
||||||
&style->bg[GTK_STATE_NORMAL],
|
|
||||||
question_xpm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* work out the initial contents */
|
|
||||||
gimp_container_foreach (GIMP_CONTAINER (st->gimage->undo_stack->undos),
|
|
||||||
undo_history_init_undo, st);
|
|
||||||
|
|
||||||
/* force selection to bottom */
|
|
||||||
gtk_clist_select_row (GTK_CLIST (st->clist),
|
|
||||||
GTK_CLIST (st->clist)->rows - 1, -1);
|
|
||||||
|
|
||||||
gimp_container_foreach (GIMP_CONTAINER (st->gimage->redo_stack->undos),
|
|
||||||
undo_history_init_redo, st);
|
|
||||||
|
|
||||||
undo_history_prepend_special (GTK_CLIST (st->clist));
|
|
||||||
st->old_selection = GPOINTER_TO_INT(GTK_CLIST(st->clist)->selection->data);
|
|
||||||
|
|
||||||
/* draw the preview of the current state */
|
|
||||||
undo_history_set_pixmap (GTK_CLIST (st->clist),
|
|
||||||
st->old_selection, st->preview_size, st->gimage);
|
|
||||||
|
|
||||||
g_signal_connect (st->clist, "select_row",
|
|
||||||
G_CALLBACK (undo_history_select_row_callback),
|
|
||||||
st);
|
|
||||||
|
|
||||||
/* if the image is clean, set the clean pixmap */
|
|
||||||
if (st->gimage->dirty == 0)
|
|
||||||
gtk_clist_set_pixmap (GTK_CLIST (st->clist), st->old_selection, 1, clean_pixmap, clean_mask);
|
|
||||||
|
|
||||||
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_NEVER,
|
|
||||||
GTK_POLICY_ALWAYS);
|
|
||||||
|
|
||||||
hbox = gtk_hbox_new (FALSE, 6);
|
|
||||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
|
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
||||||
gtk_widget_show (hbox);
|
|
||||||
|
|
||||||
st->undo_button = button = gtk_button_new_from_stock (GTK_STOCK_UNDO);
|
|
||||||
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
||||||
g_signal_connect (button, "clicked",
|
|
||||||
G_CALLBACK (undo_history_undo_callback),
|
|
||||||
st);
|
|
||||||
gtk_widget_show (GTK_WIDGET (button));
|
|
||||||
|
|
||||||
st->redo_button = button = gtk_button_new_from_stock (GTK_STOCK_REDO);
|
|
||||||
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
|
||||||
g_signal_connect (button, "clicked",
|
|
||||||
G_CALLBACK (undo_history_redo_callback),
|
|
||||||
st);
|
|
||||||
gtk_widget_show (GTK_WIDGET (button));
|
|
||||||
|
|
||||||
undo_history_set_sensitive (st, GTK_CLIST (st->clist)->rows);
|
|
||||||
|
|
||||||
gtk_widget_show (GTK_WIDGET (st->shell));
|
|
||||||
gtk_clist_moveto (GTK_CLIST (st->clist), st->old_selection, 0, 0.5, 0.0);
|
|
||||||
|
|
||||||
return st->shell;
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
/* 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_HISTORY_H__
|
|
||||||
#define __UNDO_HISTORY_H__
|
|
||||||
|
|
||||||
|
|
||||||
GtkWidget * undo_history_new (GimpImage *gimage);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __UNDO_HISTORY_H__ */
|
|
@ -151,6 +151,10 @@ libappwidgets_a_sources = \
|
|||||||
gimptoolbox-indicator-area.h \
|
gimptoolbox-indicator-area.h \
|
||||||
gimptoolinfopreview.c \
|
gimptoolinfopreview.c \
|
||||||
gimptoolinfopreview.h \
|
gimptoolinfopreview.h \
|
||||||
|
gimpundoeditor.c \
|
||||||
|
gimpundoeditor.h \
|
||||||
|
gimpundopreview.c \
|
||||||
|
gimpundopreview.h \
|
||||||
gimpvectorslistview.c \
|
gimpvectorslistview.c \
|
||||||
gimpvectorslistview.h \
|
gimpvectorslistview.h \
|
||||||
gimpviewabledialog.c \
|
gimpviewabledialog.c \
|
||||||
|
@ -1141,16 +1141,11 @@ gimp_dnd_data_type_get_by_g_type (GType type)
|
|||||||
{
|
{
|
||||||
dnd_type = GIMP_DND_TYPE_TOOL;
|
dnd_type = GIMP_DND_TYPE_TOOL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("%s(): unsupported GType \"%s\"",
|
|
||||||
G_GNUC_FUNCTION, g_type_name (type));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dnd_type;
|
return dnd_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
|
gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
|
||||||
GdkModifierType start_button_mask,
|
GdkModifierType start_button_mask,
|
||||||
GType type,
|
GType type,
|
||||||
@ -1158,20 +1153,22 @@ gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
GimpDndType dnd_type;
|
GimpDndType dnd_type;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||||
|
|
||||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||||
|
|
||||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
gtk_drag_source_set (widget, start_button_mask,
|
gtk_drag_source_set (widget, start_button_mask,
|
||||||
&dnd_data_defs[dnd_type].target_entry,
|
&dnd_data_defs[dnd_type].target_entry,
|
||||||
1,
|
1,
|
||||||
actions);
|
actions);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
||||||
GtkDestDefaults flags,
|
GtkDestDefaults flags,
|
||||||
GType type,
|
GType type,
|
||||||
@ -1179,20 +1176,22 @@ gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
GimpDndType dnd_type;
|
GimpDndType dnd_type;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||||
|
|
||||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||||
|
|
||||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
gtk_drag_dest_set (widget, flags,
|
gtk_drag_dest_set (widget, flags,
|
||||||
&dnd_data_defs[dnd_type].target_entry,
|
&dnd_data_defs[dnd_type].target_entry,
|
||||||
1,
|
1,
|
||||||
actions);
|
actions);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gimp_dnd_viewable_source_set (GtkWidget *widget,
|
gimp_dnd_viewable_source_set (GtkWidget *widget,
|
||||||
GType type,
|
GType type,
|
||||||
GimpDndDragViewableFunc get_viewable_func,
|
GimpDndDragViewableFunc get_viewable_func,
|
||||||
@ -1200,36 +1199,40 @@ gimp_dnd_viewable_source_set (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
GimpDndType dnd_type;
|
GimpDndType dnd_type;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||||
g_return_if_fail (get_viewable_func != NULL);
|
g_return_val_if_fail (get_viewable_func != NULL, FALSE);
|
||||||
|
|
||||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||||
|
|
||||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
gimp_dnd_data_source_set (dnd_type, widget,
|
gimp_dnd_data_source_set (dnd_type, widget,
|
||||||
G_CALLBACK (get_viewable_func),
|
G_CALLBACK (get_viewable_func),
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gimp_dnd_viewable_source_unset (GtkWidget *widget,
|
gimp_dnd_viewable_source_unset (GtkWidget *widget,
|
||||||
GType type)
|
GType type)
|
||||||
{
|
{
|
||||||
GimpDndType dnd_type;
|
GimpDndType dnd_type;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||||
|
|
||||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||||
|
|
||||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
gimp_dnd_data_source_unset (widget);
|
gimp_dnd_data_source_unset (widget);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
||||||
GType type,
|
GType type,
|
||||||
GimpDndDropViewableFunc set_viewable_func,
|
GimpDndDropViewableFunc set_viewable_func,
|
||||||
@ -1237,33 +1240,37 @@ gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
GimpDndType dnd_type;
|
GimpDndType dnd_type;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||||
g_return_if_fail (set_viewable_func != NULL);
|
g_return_val_if_fail (set_viewable_func != NULL, FALSE);
|
||||||
|
|
||||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||||
|
|
||||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
gimp_dnd_data_dest_add (dnd_type, widget,
|
gimp_dnd_data_dest_add (dnd_type, widget,
|
||||||
G_CALLBACK (set_viewable_func),
|
G_CALLBACK (set_viewable_func),
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
||||||
GType type)
|
GType type)
|
||||||
{
|
{
|
||||||
GimpDndType dnd_type;
|
GimpDndType dnd_type;
|
||||||
|
|
||||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||||
|
|
||||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||||
|
|
||||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
gimp_dnd_data_dest_remove (dnd_type, widget);
|
gimp_dnd_data_dest_remove (dnd_type, widget);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GimpViewable *
|
GimpViewable *
|
||||||
|
@ -145,30 +145,30 @@ typedef GimpViewable * (* GimpDndDragViewableFunc) (GtkWidget *widget,
|
|||||||
gpointer data);
|
gpointer data);
|
||||||
|
|
||||||
|
|
||||||
void gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
|
gboolean gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
|
||||||
GdkModifierType start_button_mask,
|
GdkModifierType start_button_mask,
|
||||||
GType type,
|
GType type,
|
||||||
GdkDragAction actions);
|
GdkDragAction actions);
|
||||||
void gimp_dnd_viewable_source_set (GtkWidget *widget,
|
gboolean gimp_dnd_viewable_source_set (GtkWidget *widget,
|
||||||
GType type,
|
GType type,
|
||||||
GimpDndDragViewableFunc get_viewable_func,
|
GimpDndDragViewableFunc get_viewable_func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
void gimp_dnd_viewable_source_unset (GtkWidget *widget,
|
gboolean gimp_dnd_viewable_source_unset (GtkWidget *widget,
|
||||||
GType type);
|
GType type);
|
||||||
|
|
||||||
void gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
gboolean gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
||||||
GtkDestDefaults flags,
|
GtkDestDefaults flags,
|
||||||
GType type,
|
GType type,
|
||||||
GdkDragAction actions);
|
GdkDragAction actions);
|
||||||
|
|
||||||
void gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
gboolean gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
||||||
GType type,
|
GType type,
|
||||||
GimpDndDropViewableFunc set_viewable_func,
|
GimpDndDropViewableFunc set_viewable_func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
void gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
gboolean gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
||||||
GType type);
|
GType type);
|
||||||
|
|
||||||
GimpViewable * gimp_dnd_get_drag_data (GtkWidget *widget);
|
GimpViewable * gimp_dnd_get_drag_data (GtkWidget *widget);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GIMP_DND_H__ */
|
#endif /* __GIMP_DND_H__ */
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "core/gimppalette.h"
|
#include "core/gimppalette.h"
|
||||||
#include "core/gimppattern.h"
|
#include "core/gimppattern.h"
|
||||||
#include "core/gimptoolinfo.h"
|
#include "core/gimptoolinfo.h"
|
||||||
|
#include "core/gimpundo.h"
|
||||||
|
|
||||||
#include "gimpbrushpreview.h"
|
#include "gimpbrushpreview.h"
|
||||||
#include "gimpbufferpreview.h"
|
#include "gimpbufferpreview.h"
|
||||||
@ -44,6 +45,7 @@
|
|||||||
#include "gimppalettepreview.h"
|
#include "gimppalettepreview.h"
|
||||||
#include "gimppatternpreview.h"
|
#include "gimppatternpreview.h"
|
||||||
#include "gimptoolinfopreview.h"
|
#include "gimptoolinfopreview.h"
|
||||||
|
#include "gimpundopreview.h"
|
||||||
|
|
||||||
|
|
||||||
GType
|
GType
|
||||||
@ -90,6 +92,10 @@ gimp_preview_type_from_viewable_type (GType viewable_type)
|
|||||||
{
|
{
|
||||||
type = GIMP_TYPE_IMAGEFILE_PREVIEW;
|
type = GIMP_TYPE_IMAGEFILE_PREVIEW;
|
||||||
}
|
}
|
||||||
|
else if (g_type_is_a (viewable_type, GIMP_TYPE_UNDO))
|
||||||
|
{
|
||||||
|
type = GIMP_TYPE_UNDO_PREVIEW;
|
||||||
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -630,17 +630,28 @@ gimp_preview_set_viewable (GimpPreview *preview,
|
|||||||
g_signal_handlers_disconnect_by_func (preview->viewable,
|
g_signal_handlers_disconnect_by_func (preview->viewable,
|
||||||
G_CALLBACK (gimp_preview_size_changed),
|
G_CALLBACK (gimp_preview_size_changed),
|
||||||
preview);
|
preview);
|
||||||
|
|
||||||
|
if (! viewable && ! preview->is_popup)
|
||||||
|
{
|
||||||
|
if (gimp_dnd_viewable_source_unset (GTK_WIDGET (preview),
|
||||||
|
G_TYPE_FROM_INSTANCE (preview->viewable)))
|
||||||
|
{
|
||||||
|
gtk_drag_source_unset (GTK_WIDGET (preview));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (viewable && ! preview->is_popup)
|
else if (viewable && ! preview->is_popup)
|
||||||
{
|
{
|
||||||
gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
if (gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
||||||
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
||||||
|
viewable_type,
|
||||||
|
GDK_ACTION_COPY))
|
||||||
|
{
|
||||||
|
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
||||||
viewable_type,
|
viewable_type,
|
||||||
GDK_ACTION_COPY);
|
gimp_preview_drag_viewable,
|
||||||
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
NULL);
|
||||||
viewable_type,
|
}
|
||||||
gimp_preview_drag_viewable,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
preview->viewable = viewable;
|
preview->viewable = viewable;
|
||||||
|
@ -630,17 +630,28 @@ gimp_preview_set_viewable (GimpPreview *preview,
|
|||||||
g_signal_handlers_disconnect_by_func (preview->viewable,
|
g_signal_handlers_disconnect_by_func (preview->viewable,
|
||||||
G_CALLBACK (gimp_preview_size_changed),
|
G_CALLBACK (gimp_preview_size_changed),
|
||||||
preview);
|
preview);
|
||||||
|
|
||||||
|
if (! viewable && ! preview->is_popup)
|
||||||
|
{
|
||||||
|
if (gimp_dnd_viewable_source_unset (GTK_WIDGET (preview),
|
||||||
|
G_TYPE_FROM_INSTANCE (preview->viewable)))
|
||||||
|
{
|
||||||
|
gtk_drag_source_unset (GTK_WIDGET (preview));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (viewable && ! preview->is_popup)
|
else if (viewable && ! preview->is_popup)
|
||||||
{
|
{
|
||||||
gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
if (gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
||||||
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
||||||
|
viewable_type,
|
||||||
|
GDK_ACTION_COPY))
|
||||||
|
{
|
||||||
|
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
||||||
viewable_type,
|
viewable_type,
|
||||||
GDK_ACTION_COPY);
|
gimp_preview_drag_viewable,
|
||||||
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
NULL);
|
||||||
viewable_type,
|
}
|
||||||
gimp_preview_drag_viewable,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
preview->viewable = viewable;
|
preview->viewable = viewable;
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
#include "gimpeditor.h"
|
#include "gimpeditor.h"
|
||||||
|
|
||||||
#include "gui/gui-types.h" /* temp hack */
|
|
||||||
|
|
||||||
|
|
||||||
#define GIMP_TYPE_SELECTION_EDITOR (gimp_selection_editor_get_type ())
|
#define GIMP_TYPE_SELECTION_EDITOR (gimp_selection_editor_get_type ())
|
||||||
#define GIMP_SELECTION_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SELECTION_EDITOR, GimpSelectionEditor))
|
#define GIMP_SELECTION_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SELECTION_EDITOR, GimpSelectionEditor))
|
||||||
|
422
app/widgets/gimpundoeditor.c
Normal file
422
app/widgets/gimpundoeditor.c
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
/* 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 "libgimpwidgets/gimpwidgets.h"
|
||||||
|
|
||||||
|
#include "widgets-types.h"
|
||||||
|
|
||||||
|
#include "core/gimp.h"
|
||||||
|
#include "core/gimplist.h"
|
||||||
|
#include "core/gimpimage.h"
|
||||||
|
#include "core/gimpimage-undo.h"
|
||||||
|
#include "core/gimpundostack.h"
|
||||||
|
|
||||||
|
#include "gimpcontainerlistview.h"
|
||||||
|
#include "gimpundoeditor.h"
|
||||||
|
|
||||||
|
#include "libgimp/gimpintl.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void gimp_undo_editor_class_init (GimpUndoEditorClass *klass);
|
||||||
|
static void gimp_undo_editor_init (GimpUndoEditor *undo_editor);
|
||||||
|
|
||||||
|
static void gimp_undo_editor_destroy (GtkObject *object);
|
||||||
|
|
||||||
|
static void gimp_undo_editor_undo_clicked (GtkWidget *widget,
|
||||||
|
GimpUndoEditor *editor);
|
||||||
|
static void gimp_undo_editor_redo_clicked (GtkWidget *widget,
|
||||||
|
GimpUndoEditor *editor);
|
||||||
|
|
||||||
|
static void gimp_undo_editor_undo_event (GimpImage *gimage,
|
||||||
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo,
|
||||||
|
GimpUndoEditor *editor);
|
||||||
|
|
||||||
|
static void gimp_undo_editor_select_item (GimpContainerView *view,
|
||||||
|
GimpUndo *undo,
|
||||||
|
gpointer insert_data,
|
||||||
|
GimpUndoEditor *editor);
|
||||||
|
|
||||||
|
|
||||||
|
static GimpEditorClass *parent_class = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
GType
|
||||||
|
gimp_undo_editor_get_type (void)
|
||||||
|
{
|
||||||
|
static GType editor_type = 0;
|
||||||
|
|
||||||
|
if (! editor_type)
|
||||||
|
{
|
||||||
|
static const GTypeInfo editor_info =
|
||||||
|
{
|
||||||
|
sizeof (GimpUndoEditorClass),
|
||||||
|
(GBaseInitFunc) NULL,
|
||||||
|
(GBaseFinalizeFunc) NULL,
|
||||||
|
(GClassInitFunc) gimp_undo_editor_class_init,
|
||||||
|
NULL, /* class_finalize */
|
||||||
|
NULL, /* class_data */
|
||||||
|
sizeof (GimpUndoEditor),
|
||||||
|
0, /* n_preallocs */
|
||||||
|
(GInstanceInitFunc) gimp_undo_editor_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
editor_type = g_type_register_static (GIMP_TYPE_EDITOR,
|
||||||
|
"GimpUndoEditor",
|
||||||
|
&editor_info, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return editor_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_class_init (GimpUndoEditorClass *klass)
|
||||||
|
{
|
||||||
|
GtkObjectClass *object_class;
|
||||||
|
|
||||||
|
object_class = GTK_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
|
object_class->destroy = gimp_undo_editor_destroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_init (GimpUndoEditor *undo_editor)
|
||||||
|
{
|
||||||
|
undo_editor->gimage = NULL;
|
||||||
|
undo_editor->container = NULL;
|
||||||
|
|
||||||
|
undo_editor->view = gimp_container_list_view_new (NULL,
|
||||||
|
NULL,
|
||||||
|
GIMP_PREVIEW_SIZE_MEDIUM,
|
||||||
|
FALSE, 3, 3);
|
||||||
|
gtk_box_pack_start (GTK_BOX (undo_editor), undo_editor->view, TRUE, TRUE, 0);
|
||||||
|
gtk_widget_show (undo_editor->view);
|
||||||
|
|
||||||
|
g_signal_connect (undo_editor->view, "select_item",
|
||||||
|
G_CALLBACK (gimp_undo_editor_select_item),
|
||||||
|
undo_editor);
|
||||||
|
|
||||||
|
undo_editor->undo_button =
|
||||||
|
gimp_editor_add_button (GIMP_EDITOR (undo_editor),
|
||||||
|
GTK_STOCK_UNDO,
|
||||||
|
_("Undo"), NULL,
|
||||||
|
G_CALLBACK (gimp_undo_editor_undo_clicked),
|
||||||
|
NULL,
|
||||||
|
undo_editor);
|
||||||
|
|
||||||
|
undo_editor->redo_button =
|
||||||
|
gimp_editor_add_button (GIMP_EDITOR (undo_editor),
|
||||||
|
GTK_STOCK_REDO,
|
||||||
|
_("Redo"), NULL,
|
||||||
|
G_CALLBACK (gimp_undo_editor_redo_clicked),
|
||||||
|
NULL,
|
||||||
|
undo_editor);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (undo_editor), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_destroy (GtkObject *object)
|
||||||
|
{
|
||||||
|
GimpUndoEditor *editor;
|
||||||
|
|
||||||
|
editor = GIMP_UNDO_EDITOR (object);
|
||||||
|
|
||||||
|
if (editor->gimage)
|
||||||
|
gimp_undo_editor_set_image (editor, NULL);
|
||||||
|
|
||||||
|
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* public functions */
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gimp_undo_editor_new (GimpImage *gimage)
|
||||||
|
{
|
||||||
|
GimpUndoEditor *editor;
|
||||||
|
|
||||||
|
g_return_val_if_fail (! gimage || GIMP_IS_IMAGE (gimage), NULL);
|
||||||
|
|
||||||
|
editor = g_object_new (GIMP_TYPE_UNDO_EDITOR, NULL);
|
||||||
|
|
||||||
|
gimp_undo_editor_set_image (editor, gimage);
|
||||||
|
|
||||||
|
return GTK_WIDGET (editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_undo_editor_set_image (GimpUndoEditor *editor,
|
||||||
|
GimpImage *gimage)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GIMP_IS_UNDO_EDITOR (editor));
|
||||||
|
g_return_if_fail (! gimage || GIMP_IS_IMAGE (gimage));
|
||||||
|
|
||||||
|
if (gimage == editor->gimage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (editor->gimage)
|
||||||
|
{
|
||||||
|
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
NULL);
|
||||||
|
g_object_unref (editor->container);
|
||||||
|
editor->container = NULL;
|
||||||
|
|
||||||
|
g_object_unref (editor->base_item);
|
||||||
|
editor->base_item = NULL;
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (editor->gimage,
|
||||||
|
gimp_undo_editor_undo_event,
|
||||||
|
editor);
|
||||||
|
}
|
||||||
|
else if (gimage)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor->gimage = gimage;
|
||||||
|
|
||||||
|
if (gimage)
|
||||||
|
{
|
||||||
|
GimpUndo *top_undo_item;
|
||||||
|
GimpUndo *top_redo_item;
|
||||||
|
GList *list;
|
||||||
|
|
||||||
|
/* create a container as model for the undo history list */
|
||||||
|
editor->container = gimp_list_new (GIMP_TYPE_UNDO,
|
||||||
|
GIMP_CONTAINER_POLICY_STRONG);
|
||||||
|
editor->base_item = gimp_undo_new (gimage,
|
||||||
|
GIMP_UNDO_GROUP_NONE,
|
||||||
|
_("[ Base Image ]"),
|
||||||
|
NULL, 0, FALSE, NULL, NULL);
|
||||||
|
|
||||||
|
/* the list prepends its items, so first add the redo items... */
|
||||||
|
for (list = GIMP_LIST (gimage->redo_stack->undos)->list;
|
||||||
|
list;
|
||||||
|
list = g_list_next (list))
|
||||||
|
{
|
||||||
|
gimp_container_add (editor->container, GIMP_OBJECT (list->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ...reverse the list so the redo items are in ascending order... */
|
||||||
|
gimp_list_reverse (GIMP_LIST (editor->container));
|
||||||
|
|
||||||
|
/* ...then add the undo items in descending order... */
|
||||||
|
for (list = GIMP_LIST (gimage->undo_stack->undos)->list;
|
||||||
|
list;
|
||||||
|
list = g_list_next (list))
|
||||||
|
{
|
||||||
|
gimp_container_add (editor->container, GIMP_OBJECT (list->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ...finally, the first item is the special "base_item" which stands
|
||||||
|
* for the image with no more undos available to pop
|
||||||
|
*/
|
||||||
|
gimp_container_add (editor->container, GIMP_OBJECT (editor->base_item));
|
||||||
|
|
||||||
|
/* display the container */
|
||||||
|
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
editor->container);
|
||||||
|
|
||||||
|
/* get the top item of both stacks */
|
||||||
|
top_undo_item = gimp_undo_stack_peek (gimage->undo_stack);
|
||||||
|
top_redo_item = gimp_undo_stack_peek (gimage->redo_stack);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (editor->undo_button, top_undo_item != NULL);
|
||||||
|
gtk_widget_set_sensitive (editor->redo_button, top_redo_item != NULL);
|
||||||
|
|
||||||
|
g_signal_handlers_block_by_func (editor->view,
|
||||||
|
gimp_undo_editor_select_item,
|
||||||
|
editor);
|
||||||
|
|
||||||
|
/* select the current state of the image */
|
||||||
|
if (top_undo_item)
|
||||||
|
{
|
||||||
|
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
GIMP_VIEWABLE (top_undo_item));
|
||||||
|
gimp_undo_create_preview (top_undo_item, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
GIMP_VIEWABLE (editor->base_item));
|
||||||
|
gimp_undo_create_preview (editor->base_item, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_handlers_unblock_by_func (editor->view,
|
||||||
|
gimp_undo_editor_select_item,
|
||||||
|
editor);
|
||||||
|
|
||||||
|
g_signal_connect (gimage, "undo_event",
|
||||||
|
G_CALLBACK (gimp_undo_editor_undo_event),
|
||||||
|
editor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_undo_clicked (GtkWidget *widget,
|
||||||
|
GimpUndoEditor *editor)
|
||||||
|
{
|
||||||
|
if (editor->gimage)
|
||||||
|
{
|
||||||
|
if (gimp_image_undo (editor->gimage))
|
||||||
|
gimp_image_flush (editor->gimage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_redo_clicked (GtkWidget *widget,
|
||||||
|
GimpUndoEditor *editor)
|
||||||
|
{
|
||||||
|
if (editor->gimage)
|
||||||
|
{
|
||||||
|
if (gimp_image_redo (editor->gimage))
|
||||||
|
gimp_image_flush (editor->gimage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_undo_event (GimpImage *gimage,
|
||||||
|
GimpUndoEvent event,
|
||||||
|
GimpUndo *undo,
|
||||||
|
GimpUndoEditor *editor)
|
||||||
|
{
|
||||||
|
GimpUndo *top_undo_item;
|
||||||
|
GimpUndo *top_redo_item;
|
||||||
|
|
||||||
|
top_undo_item = gimp_undo_stack_peek (gimage->undo_stack);
|
||||||
|
top_redo_item = gimp_undo_stack_peek (gimage->redo_stack);
|
||||||
|
|
||||||
|
g_signal_handlers_block_by_func (editor->view,
|
||||||
|
gimp_undo_editor_select_item,
|
||||||
|
editor);
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case GIMP_UNDO_EVENT_UNDO_PUSHED:
|
||||||
|
gimp_container_insert (editor->container, GIMP_OBJECT (undo), -1);
|
||||||
|
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
GIMP_VIEWABLE (undo));
|
||||||
|
gimp_undo_create_preview (undo, FALSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GIMP_UNDO_EVENT_UNDO_EXPIRED:
|
||||||
|
case GIMP_UNDO_EVENT_REDO_EXPIRED:
|
||||||
|
gimp_container_remove (editor->container, GIMP_OBJECT (undo));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GIMP_UNDO_EVENT_UNDO:
|
||||||
|
if (top_undo_item)
|
||||||
|
{
|
||||||
|
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
GIMP_VIEWABLE (top_undo_item));
|
||||||
|
gimp_undo_create_preview (top_undo_item, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
GIMP_VIEWABLE (editor->base_item));
|
||||||
|
gimp_undo_create_preview (editor->base_item, TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GIMP_UNDO_EVENT_REDO:
|
||||||
|
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
|
||||||
|
GIMP_VIEWABLE (top_undo_item));
|
||||||
|
gimp_undo_create_preview (top_undo_item, FALSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GIMP_UNDO_EVENT_UNDO_FREE:
|
||||||
|
gimp_undo_editor_set_image (editor, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_handlers_unblock_by_func (editor->view,
|
||||||
|
gimp_undo_editor_select_item,
|
||||||
|
editor);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (editor->undo_button, top_undo_item != NULL);
|
||||||
|
gtk_widget_set_sensitive (editor->redo_button, top_redo_item != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_editor_select_item (GimpContainerView *view,
|
||||||
|
GimpUndo *undo,
|
||||||
|
gpointer insert_data,
|
||||||
|
GimpUndoEditor *editor)
|
||||||
|
{
|
||||||
|
GimpUndo *top_undo_item;
|
||||||
|
GimpUndo *top_redo_item;
|
||||||
|
|
||||||
|
top_undo_item = gimp_undo_stack_peek (editor->gimage->undo_stack);
|
||||||
|
|
||||||
|
if (undo == editor->base_item)
|
||||||
|
{
|
||||||
|
/* the base_image was selected, pop all available undo items
|
||||||
|
*/
|
||||||
|
while (top_undo_item != NULL)
|
||||||
|
{
|
||||||
|
gimp_image_undo (editor->gimage);
|
||||||
|
|
||||||
|
top_undo_item = gimp_undo_stack_peek (editor->gimage->undo_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gimp_container_have (editor->gimage->undo_stack->undos,
|
||||||
|
GIMP_OBJECT (undo)))
|
||||||
|
{
|
||||||
|
/* the selected item is on the undo stack, pop undos until it
|
||||||
|
* is on the of the undo stack
|
||||||
|
*/
|
||||||
|
while (top_undo_item != undo)
|
||||||
|
{
|
||||||
|
gimp_image_undo (editor->gimage);
|
||||||
|
|
||||||
|
top_undo_item = gimp_undo_stack_peek (editor->gimage->undo_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gimp_container_have (editor->gimage->redo_stack->undos,
|
||||||
|
GIMP_OBJECT (undo)))
|
||||||
|
{
|
||||||
|
/* the selected item is on the redo stack, pop redos until it
|
||||||
|
* is on top of the undo stack
|
||||||
|
*/
|
||||||
|
while (top_undo_item != undo)
|
||||||
|
{
|
||||||
|
gimp_image_redo (editor->gimage);
|
||||||
|
|
||||||
|
top_undo_item = gimp_undo_stack_peek (editor->gimage->undo_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gimp_image_flush (editor->gimage);
|
||||||
|
|
||||||
|
top_redo_item = gimp_undo_stack_peek (editor->gimage->redo_stack);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (editor->undo_button, top_undo_item != NULL);
|
||||||
|
gtk_widget_set_sensitive (editor->redo_button, top_redo_item != NULL);
|
||||||
|
}
|
64
app/widgets/gimpundoeditor.h
Normal file
64
app/widgets/gimpundoeditor.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* 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 __GIMP_UNDO_EDITOR_H__
|
||||||
|
#define __GIMP_UNDO_EDITOR_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include "gimpeditor.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define GIMP_TYPE_UNDO_EDITOR (gimp_undo_editor_get_type ())
|
||||||
|
#define GIMP_UNDO_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_UNDO_EDITOR, GimpUndoEditor))
|
||||||
|
#define GIMP_UNDO_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_UNDO_EDITOR, GimpUndoEditorClass))
|
||||||
|
#define GIMP_IS_UNDO_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_UNDO_EDITOR))
|
||||||
|
#define GIMP_IS_UNDO_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_UNDO_EDITOR))
|
||||||
|
#define GIMP_UNDO_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_UNDO_EDITOR, GimpUndoEditorClass))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GimpUndoEditorClass GimpUndoEditorClass;
|
||||||
|
|
||||||
|
struct _GimpUndoEditor
|
||||||
|
{
|
||||||
|
GimpEditor parent_instance;
|
||||||
|
|
||||||
|
GimpImage *gimage;
|
||||||
|
|
||||||
|
GimpContainer *container;
|
||||||
|
GtkWidget *view;
|
||||||
|
|
||||||
|
GimpUndo *base_item;
|
||||||
|
|
||||||
|
GtkWidget *undo_button;
|
||||||
|
GtkWidget *redo_button;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GimpUndoEditorClass
|
||||||
|
{
|
||||||
|
GimpEditorClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GType gimp_undo_editor_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GtkWidget * gimp_undo_editor_new (GimpImage *gimage);
|
||||||
|
void gimp_undo_editor_set_image (GimpUndoEditor *editor,
|
||||||
|
GimpImage *gimage);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __GIMP_UNDO_EDITOR_H__ */
|
161
app/widgets/gimpundopreview.c
Normal file
161
app/widgets/gimpundopreview.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/* The GIMP -- an image manipulation program
|
||||||
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||||
|
*
|
||||||
|
* GimpUndoPreview Widget
|
||||||
|
* Copyright (C) 2001 Michael Natterer <mitch@gimp.org>
|
||||||
|
*
|
||||||
|
* 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 "widgets-types.h"
|
||||||
|
|
||||||
|
#include "base/temp-buf.h"
|
||||||
|
|
||||||
|
#include "core/gimpundo.h"
|
||||||
|
|
||||||
|
#include "gimpundopreview.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void gimp_undo_preview_class_init (GimpUndoPreviewClass *klass);
|
||||||
|
static void gimp_undo_preview_init (GimpUndoPreview *preview);
|
||||||
|
|
||||||
|
static void gimp_undo_preview_render (GimpPreview *preview);
|
||||||
|
|
||||||
|
|
||||||
|
static GimpPreviewClass *parent_class = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
GType
|
||||||
|
gimp_undo_preview_get_type (void)
|
||||||
|
{
|
||||||
|
static GType preview_type = 0;
|
||||||
|
|
||||||
|
if (! preview_type)
|
||||||
|
{
|
||||||
|
static const GTypeInfo preview_info =
|
||||||
|
{
|
||||||
|
sizeof (GimpUndoPreviewClass),
|
||||||
|
NULL, /* base_init */
|
||||||
|
NULL, /* base_finalize */
|
||||||
|
(GClassInitFunc) gimp_undo_preview_class_init,
|
||||||
|
NULL, /* class_finalize */
|
||||||
|
NULL, /* class_data */
|
||||||
|
sizeof (GimpUndoPreview),
|
||||||
|
0, /* n_preallocs */
|
||||||
|
(GInstanceInitFunc) gimp_undo_preview_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
preview_type = g_type_register_static (GIMP_TYPE_PREVIEW,
|
||||||
|
"GimpUndoPreview",
|
||||||
|
&preview_info, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return preview_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_preview_class_init (GimpUndoPreviewClass *klass)
|
||||||
|
{
|
||||||
|
GimpPreviewClass *preview_class;
|
||||||
|
|
||||||
|
preview_class = GIMP_PREVIEW_CLASS (klass);
|
||||||
|
|
||||||
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
|
preview_class->render = gimp_undo_preview_render;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_preview_init (GimpUndoPreview *preview)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_undo_preview_render (GimpPreview *preview)
|
||||||
|
{
|
||||||
|
GimpUndo *undo;
|
||||||
|
gint width;
|
||||||
|
gint height;
|
||||||
|
gint preview_width;
|
||||||
|
gint preview_height;
|
||||||
|
gboolean scaling_up;
|
||||||
|
TempBuf *render_buf;
|
||||||
|
gboolean free_buf = FALSE;
|
||||||
|
|
||||||
|
undo = GIMP_UNDO (preview->viewable);
|
||||||
|
|
||||||
|
width = preview->width;
|
||||||
|
height = preview->height;
|
||||||
|
|
||||||
|
render_buf = gimp_viewable_get_preview (preview->viewable, width, height);
|
||||||
|
|
||||||
|
if (! render_buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gimp_preview_calc_size (preview,
|
||||||
|
render_buf->width,
|
||||||
|
render_buf->height,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
1.0, 1.0,
|
||||||
|
&preview_width,
|
||||||
|
&preview_height,
|
||||||
|
&scaling_up);
|
||||||
|
|
||||||
|
if (preview_width != render_buf->width ||
|
||||||
|
preview_height != render_buf->height)
|
||||||
|
{
|
||||||
|
render_buf = temp_buf_scale (render_buf, preview_width, preview_height);
|
||||||
|
|
||||||
|
free_buf = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preview_width < width) render_buf->x = (width - preview_width) / 2;
|
||||||
|
if (preview_height < height) render_buf->y = (height - preview_height) / 2;
|
||||||
|
|
||||||
|
if (render_buf->x || render_buf->y)
|
||||||
|
{
|
||||||
|
TempBuf *temp_buf;
|
||||||
|
guchar white[4] = { 255, 255, 255, 255 };
|
||||||
|
|
||||||
|
temp_buf = temp_buf_new (width, height,
|
||||||
|
render_buf->bytes,
|
||||||
|
0, 0,
|
||||||
|
white);
|
||||||
|
|
||||||
|
temp_buf_copy_area (render_buf, temp_buf,
|
||||||
|
0, 0,
|
||||||
|
render_buf->width,
|
||||||
|
render_buf->height,
|
||||||
|
render_buf->x,
|
||||||
|
render_buf->y);
|
||||||
|
|
||||||
|
if (free_buf)
|
||||||
|
temp_buf_free (render_buf);
|
||||||
|
|
||||||
|
render_buf = temp_buf;
|
||||||
|
|
||||||
|
free_buf = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gimp_preview_render_and_flush (preview, render_buf, -1);
|
||||||
|
|
||||||
|
if (free_buf)
|
||||||
|
temp_buf_free (render_buf);
|
||||||
|
}
|
51
app/widgets/gimpundopreview.h
Normal file
51
app/widgets/gimpundopreview.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* The GIMP -- an image manipulation program
|
||||||
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||||
|
*
|
||||||
|
* GimpUndoPreview Widget
|
||||||
|
* Copyright (C) 2001 Michael Natterer <mitch@gimp.org>
|
||||||
|
*
|
||||||
|
* 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 __GIMP_UNDO_PREVIEW_H__
|
||||||
|
#define __GIMP_UNDO_PREVIEW_H__
|
||||||
|
|
||||||
|
#include "gimppreview.h"
|
||||||
|
|
||||||
|
#define GIMP_TYPE_UNDO_PREVIEW (gimp_undo_preview_get_type ())
|
||||||
|
#define GIMP_UNDO_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_UNDO_PREVIEW, GimpUndoPreview))
|
||||||
|
#define GIMP_UNDO_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_UNDO_PREVIEW, GimpUndoPreviewClass))
|
||||||
|
#define GIMP_IS_UNDO_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GIMP_TYPE_UNDO_PREVIEW))
|
||||||
|
#define GIMP_IS_UNDO_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_UNDO_PREVIEW))
|
||||||
|
#define GIMP_UNDO_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_UNDO_PREVIEW, GimpUndoPreviewClass))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _GimpUndoPreviewClass GimpUndoPreviewClass;
|
||||||
|
|
||||||
|
struct _GimpUndoPreview
|
||||||
|
{
|
||||||
|
GimpPreview parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GimpUndoPreviewClass
|
||||||
|
{
|
||||||
|
GimpPreviewClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GType gimp_undo_preview_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __GIMP_UNDO_PREVIEW_H__ */
|
@ -630,17 +630,28 @@ gimp_preview_set_viewable (GimpPreview *preview,
|
|||||||
g_signal_handlers_disconnect_by_func (preview->viewable,
|
g_signal_handlers_disconnect_by_func (preview->viewable,
|
||||||
G_CALLBACK (gimp_preview_size_changed),
|
G_CALLBACK (gimp_preview_size_changed),
|
||||||
preview);
|
preview);
|
||||||
|
|
||||||
|
if (! viewable && ! preview->is_popup)
|
||||||
|
{
|
||||||
|
if (gimp_dnd_viewable_source_unset (GTK_WIDGET (preview),
|
||||||
|
G_TYPE_FROM_INSTANCE (preview->viewable)))
|
||||||
|
{
|
||||||
|
gtk_drag_source_unset (GTK_WIDGET (preview));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (viewable && ! preview->is_popup)
|
else if (viewable && ! preview->is_popup)
|
||||||
{
|
{
|
||||||
gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
if (gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
||||||
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
||||||
|
viewable_type,
|
||||||
|
GDK_ACTION_COPY))
|
||||||
|
{
|
||||||
|
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
||||||
viewable_type,
|
viewable_type,
|
||||||
GDK_ACTION_COPY);
|
gimp_preview_drag_viewable,
|
||||||
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
NULL);
|
||||||
viewable_type,
|
}
|
||||||
gimp_preview_drag_viewable,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
preview->viewable = viewable;
|
preview->viewable = viewable;
|
||||||
|
@ -630,17 +630,28 @@ gimp_preview_set_viewable (GimpPreview *preview,
|
|||||||
g_signal_handlers_disconnect_by_func (preview->viewable,
|
g_signal_handlers_disconnect_by_func (preview->viewable,
|
||||||
G_CALLBACK (gimp_preview_size_changed),
|
G_CALLBACK (gimp_preview_size_changed),
|
||||||
preview);
|
preview);
|
||||||
|
|
||||||
|
if (! viewable && ! preview->is_popup)
|
||||||
|
{
|
||||||
|
if (gimp_dnd_viewable_source_unset (GTK_WIDGET (preview),
|
||||||
|
G_TYPE_FROM_INSTANCE (preview->viewable)))
|
||||||
|
{
|
||||||
|
gtk_drag_source_unset (GTK_WIDGET (preview));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (viewable && ! preview->is_popup)
|
else if (viewable && ! preview->is_popup)
|
||||||
{
|
{
|
||||||
gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
if (gimp_dnd_drag_source_set_by_type (GTK_WIDGET (preview),
|
||||||
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
||||||
|
viewable_type,
|
||||||
|
GDK_ACTION_COPY))
|
||||||
|
{
|
||||||
|
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
||||||
viewable_type,
|
viewable_type,
|
||||||
GDK_ACTION_COPY);
|
gimp_preview_drag_viewable,
|
||||||
gimp_dnd_viewable_source_set (GTK_WIDGET (preview),
|
NULL);
|
||||||
viewable_type,
|
}
|
||||||
gimp_preview_drag_viewable,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
preview->viewable = viewable;
|
preview->viewable = viewable;
|
||||||
|
@ -38,16 +38,17 @@ typedef struct _GimpMenuFactory GimpMenuFactory;
|
|||||||
/* widgets */
|
/* widgets */
|
||||||
|
|
||||||
typedef struct _GimpPreview GimpPreview;
|
typedef struct _GimpPreview GimpPreview;
|
||||||
typedef struct _GimpImagePreview GimpImagePreview;
|
|
||||||
typedef struct _GimpDrawablePreview GimpDrawablePreview;
|
|
||||||
typedef struct _GimpImagefilePreview GimpImagefilePreview;
|
|
||||||
typedef struct _GimpBrushPreview GimpBrushPreview;
|
typedef struct _GimpBrushPreview GimpBrushPreview;
|
||||||
typedef struct _GimpNavigationPreview GimpNavigationPreview;
|
|
||||||
typedef struct _GimpPatternPreview GimpPatternPreview;
|
|
||||||
typedef struct _GimpPalettePreview GimpPalettePreview;
|
|
||||||
typedef struct _GimpGradientPreview GimpGradientPreview;
|
|
||||||
typedef struct _GimpToolInfoPreview GimpToolInfoPreview;
|
|
||||||
typedef struct _GimpBufferPreview GimpBufferPreview;
|
typedef struct _GimpBufferPreview GimpBufferPreview;
|
||||||
|
typedef struct _GimpDrawablePreview GimpDrawablePreview;
|
||||||
|
typedef struct _GimpGradientPreview GimpGradientPreview;
|
||||||
|
typedef struct _GimpImagePreview GimpImagePreview;
|
||||||
|
typedef struct _GimpImagefilePreview GimpImagefilePreview;
|
||||||
|
typedef struct _GimpNavigationPreview GimpNavigationPreview;
|
||||||
|
typedef struct _GimpPalettePreview GimpPalettePreview;
|
||||||
|
typedef struct _GimpPatternPreview GimpPatternPreview;
|
||||||
|
typedef struct _GimpToolInfoPreview GimpToolInfoPreview;
|
||||||
|
typedef struct _GimpUndoPreview GimpUndoPreview;
|
||||||
|
|
||||||
typedef struct _GimpContainerMenu GimpContainerMenu;
|
typedef struct _GimpContainerMenu GimpContainerMenu;
|
||||||
typedef struct _GimpContainerMenuImpl GimpContainerMenuImpl;
|
typedef struct _GimpContainerMenuImpl GimpContainerMenuImpl;
|
||||||
@ -63,6 +64,7 @@ typedef struct _GimpBrushEditor GimpBrushEditor;
|
|||||||
typedef struct _GimpGradientEditor GimpGradientEditor;
|
typedef struct _GimpGradientEditor GimpGradientEditor;
|
||||||
typedef struct _GimpPaletteEditor GimpPaletteEditor;
|
typedef struct _GimpPaletteEditor GimpPaletteEditor;
|
||||||
typedef struct _GimpSelectionEditor GimpSelectionEditor;
|
typedef struct _GimpSelectionEditor GimpSelectionEditor;
|
||||||
|
typedef struct _GimpUndoEditor GimpUndoEditor;
|
||||||
|
|
||||||
typedef struct _GimpContainerView GimpContainerView;
|
typedef struct _GimpContainerView GimpContainerView;
|
||||||
typedef struct _GimpContainerListView GimpContainerListView;
|
typedef struct _GimpContainerListView GimpContainerListView;
|
||||||
|
Reference in New Issue
Block a user