Updated my CVS. app/undo.c app/undo_history.c app/core/gimpimage.[ch]

2003-01-01 Garry R. Osgood <grosgood@rcn.com>
* MAINTAINERS: Updated my CVS.
* app/undo.c
* app/undo_history.c
* app/core/gimpimage.[ch]
* app/tools/gimpimagemaptool.c
* app/core/gimpimage-merge.c: implementation of LAYER_MERGE
signal emitters and listeners. (see bug #98843); listeners thaw
undo stack (image map tools, usually).
* app/widgets/gimpviewabledialog.c: gimp_viewable_dialog_close ()
Check if the widget has a non-null reference to a window before
using it to synthesize a cancel event. These seven deltas closes bug #98843.
* app/core/gimpimage-merge.c: (gimp_image_merge_layers())
Regardless of merge type, temporarily set composition mode
of bottom layer to NORMAL, then merge. Closes bug #101036.
This commit is contained in:
Garry R. Osgood 2003-01-01 23:40:53 +00:00 committed by Garry R. Osgood
parent 6cd51e1962
commit d8fd3b04c1
10 changed files with 117 additions and 32 deletions

View file

@ -1,3 +1,34 @@
2003-01-01 Garry R. Osgood <grosgood@rcn.com>
* MAINTAINERS: Updated my CVS.
* app/undo.c: Check if LayerUndo object provides a previous
layer before setting such active; in some cases the result of a
redo is an empty image, and prev_layer is not populated. Part of
bug # 98843.
* app/undo_history.c: undo_history_new () Increments reference
count on GimpImage in undo_history_st;
undo_history_shell_destroy_callback () dereferences. Before,
with undo history dialog active on application exit, the GimpImage
ref count would already be zero, with memory reclaimed, when
gimp_dialog_factory_dispose () invoked
undo_history_shell_destroy_callback (). See stack dumps in
bug # 98843; in part closes same.
* app/core/gimpimage-merge.c : gimp_image_merge_layers ()
Regardless of merge type, temporarily set composition mode
of bottom layer to NORMAL, then merge. Closes bug #101036.
Issues LAYER_MERGE signal (see bug #98843); listeners thaw
undo stack (image map tools, usually) in part closes this bug.
* app/core/gimpimage.[ch] Define and implement a LAYER_MERGE
signal.
* app/tools/gimpimagemaptool.c: gimp_image_map_tool_initialize ()
connects its associated GimpImage with dialog's cancel callback
via the GimpImage's LAYER_MERGE signal. gimp_image_map_tool_finalize ()
disconnects. Dismisses dialog in layer merges. In part closes
bug # 98843.
* app/widgets/gimpviewabledialog.c: gimp_viewable_dialog_close ()
Check if the widget has a non-null reference to a window before
using it to synthesize a cancel event.
2003-01-01 Sven Neumann <sven@gimp.org> 2003-01-01 Sven Neumann <sven@gimp.org>
* app/gui/menus.c (image_entries): changed some menu entries as * app/gui/menus.c (image_entries): changed some menu entries as

View file

@ -170,14 +170,15 @@ current work:
commit access: yes commit access: yes
Name: Garry R. Osgood Name: Garry R. Osgood
Email: gosgood@idt.net Email: grosgood@rcn.com
url: http://idt.net/~gosgood/ url: http://users.rcn.com/gosgood/
ircnick: ircnick:
expertise: Bug fixing. expertise: Bug fixing.
current work: I fell into this rabbit hole by writing highly verbose patch documentation, current work: I fell into this rabbit hole by writing highly verbose patch documentation,
which just goes to show that succinctness is its own reward. My patch documentation which just goes to show that succinctness is its own reward. My patch documentation
archive is http://idt.net/~gosgood/gimp-patch/ archive is http://users.rcn.com/gosgood/gimp-patch/
commit access: yes commit access: yes
should be committed: Only when they catch me ;)
Name: David Monniaux Name: David Monniaux
Email: monniaux@genievre.ens.fr Email: monniaux@genievre.ens.fr

View file

@ -296,7 +296,12 @@ gimp_image_merge_layers (GimpImage *gimage,
if ((x2 - x1) == 0 || (y2 - y1) == 0) if ((x2 - x1) == 0 || (y2 - y1) == 0)
return NULL; return NULL;
/* Start a merge undo group */ /* Tell any listeners about impending layer merges */
gimp_image_layer_merge (gimage);
/* Start a merge undo group. */
undo_push_group_start (gimage, IMAGE_LAYERS_MERGE_UNDO_GROUP); undo_push_group_start (gimage, IMAGE_LAYERS_MERGE_UNDO_GROUP);
name = g_strdup (gimp_object_get_name (GIMP_OBJECT (layer))); name = g_strdup (gimp_object_get_name (GIMP_OBJECT (layer)));
@ -376,22 +381,21 @@ gimp_image_merge_layers (GimpImage *gimage,
position = position =
gimp_container_num_children (gimage->layers) - gimp_container_num_children (gimage->layers) -
gimp_container_get_child_index (gimage->layers, GIMP_OBJECT (layer)); gimp_container_get_child_index (gimage->layers, GIMP_OBJECT (layer));
/* set the mode of the bottom layer to normal so that the contents
* aren't lost when merging with the all-alpha merge_layer
* Keep a pointer to it so that we can set the mode right after it's
* been merged so that undo works correctly.
*/
bottom_layer = layer;
bottom_mode = bottom_layer->mode;
/* DISSOLVE_MODE is special since it is the only mode that does not
* work on the projection with the lower layer, but only locally on
* the layers alpha channel.
*/
if (bottom_layer->mode != GIMP_DISSOLVE_MODE)
gimp_layer_set_mode (bottom_layer, GIMP_NORMAL_MODE);
} }
/* set the mode of the bottom layer to normal so that the contents
* aren't lost when merging with the all-alpha merge_layer
* Keep a pointer to it so that we can set the mode right after it's
* been merged so that undo works correctly.
*/
bottom_layer = layer;
bottom_mode = bottom_layer->mode;
/* DISSOLVE_MODE is special since it is the only mode that does not
* work on the projection with the lower layer, but only locally on
* the layers alpha channel.
*/
if (bottom_layer->mode != GIMP_DISSOLVE_MODE)
gimp_layer_set_mode (bottom_layer, GIMP_NORMAL_MODE);
/* Copy the tattoo and parasites of the bottom layer to the new layer */ /* Copy the tattoo and parasites of the bottom layer to the new layer */
gimp_item_set_tattoo (GIMP_ITEM (merge_layer), gimp_item_set_tattoo (GIMP_ITEM (merge_layer),

View file

@ -1684,8 +1684,11 @@ undo_pop_layer (GimpImage *gimage,
/* record the current position */ /* record the current position */
lu->prev_position = gimp_image_get_layer_index (gimage, lu->layer); lu->prev_position = gimp_image_get_layer_index (gimage, lu->layer);
/* set the previous layer */ /* if exists, set the previous layer */
gimp_image_set_active_layer (gimage, lu->prev_layer); /* (counterexample: result layer added after a merge op has no previous layer.) */
if(GIMP_IS_LAYER (lu->prev_layer))
gimp_image_set_active_layer (gimage, lu->prev_layer);
/* remove the layer */ /* remove the layer */
gimp_container_remove (gimage->layers, GIMP_OBJECT (lu->layer)); gimp_container_remove (gimage->layers, GIMP_OBJECT (lu->layer));

View file

@ -84,7 +84,6 @@ enum
UNIT_CHANGED, UNIT_CHANGED,
QMASK_CHANGED, QMASK_CHANGED,
SELECTION_CONTROL, SELECTION_CONTROL,
CLEAN, CLEAN,
DIRTY, DIRTY,
UPDATE, UPDATE,
@ -92,6 +91,7 @@ enum
COLORMAP_CHANGED, COLORMAP_CHANGED,
UNDO_EVENT, UNDO_EVENT,
FLUSH, FLUSH,
LAYER_MERGE,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -375,6 +375,15 @@ gimp_image_class_init (GimpImageClass *klass)
gimp_marshal_VOID__VOID, gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
gimp_image_signals[LAYER_MERGE] =
g_signal_new ("layer_merge",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpImageClass, layer_merge),
NULL, NULL,
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
object_class->dispose = gimp_image_dispose; object_class->dispose = gimp_image_dispose;
object_class->finalize = gimp_image_finalize; object_class->finalize = gimp_image_finalize;
@ -404,6 +413,8 @@ gimp_image_class_init (GimpImageClass *klass)
klass->undo_event = NULL; klass->undo_event = NULL;
klass->undo = gimp_image_undo; klass->undo = gimp_image_undo;
klass->redo = gimp_image_redo; klass->redo = gimp_image_redo;
klass->flush = NULL;
klass->layer_merge = NULL;
gimp_image_color_hash_init (); gimp_image_color_hash_init ();
} }
@ -1646,6 +1657,16 @@ gimp_image_flush (GimpImage *gimage)
g_signal_emit (G_OBJECT (gimage), gimp_image_signals[FLUSH], 0); g_signal_emit (G_OBJECT (gimage), gimp_image_signals[FLUSH], 0);
} }
/* Post notification of a layer merge */
void
gimp_image_layer_merge (GimpImage *gimage)
{
g_return_if_fail (GIMP_IS_IMAGE (gimage));
g_signal_emit (G_OBJECT (gimage), gimp_image_signals[LAYER_MERGE], 0);
}
/* color transforms / utilities */ /* color transforms / utilities */

View file

@ -207,6 +207,7 @@ struct _GimpImageClass
void (* redo) (GimpImage *gimage); void (* redo) (GimpImage *gimage);
void (* flush) (GimpImage *gimage); void (* flush) (GimpImage *gimage);
void (* layer_merge) (GimpImage *gimage);
}; };
@ -314,6 +315,10 @@ void gimp_image_clean_all (GimpImage *gimage);
void gimp_image_flush (GimpImage *gimage); void gimp_image_flush (GimpImage *gimage);
/* Post notification of layer mergers */
void gimp_image_layer_merge (GimpImage *gimage);
/* color transforms / utilities */ /* color transforms / utilities */

View file

@ -172,6 +172,11 @@ gimp_image_map_tool_finalize (GObject *object)
gtk_widget_destroy (image_map_tool->shell); gtk_widget_destroy (image_map_tool->shell);
image_map_tool->shell = NULL; image_map_tool->shell = NULL;
image_map_tool->main_vbox = NULL; image_map_tool->main_vbox = NULL;
g_signal_handlers_disconnect_by_func (
gimp_item_get_image (GIMP_ITEM (image_map_tool->drawable)),
gimp_image_map_tool_cancel_clicked,
image_map_tool
);
} }
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
@ -256,6 +261,10 @@ gimp_image_map_tool_initialize (GimpTool *tool,
G_CALLBACK (gimp_image_map_tool_flush), G_CALLBACK (gimp_image_map_tool_flush),
image_map_tool); image_map_tool);
g_signal_connect (G_OBJECT (gdisp->gimage), "layer_merge",
G_CALLBACK (gimp_image_map_tool_cancel_clicked),
image_map_tool);
gimp_display_shell_set_menu_sensitivity (GIMP_DISPLAY_SHELL (gdisp->shell), gimp_display_shell_set_menu_sensitivity (GIMP_DISPLAY_SHELL (gdisp->shell),
gdisp->gimage->gimp, FALSE); gdisp->gimage->gimp, FALSE);
} }

View file

@ -1684,8 +1684,11 @@ undo_pop_layer (GimpImage *gimage,
/* record the current position */ /* record the current position */
lu->prev_position = gimp_image_get_layer_index (gimage, lu->layer); lu->prev_position = gimp_image_get_layer_index (gimage, lu->layer);
/* set the previous layer */ /* if exists, set the previous layer */
gimp_image_set_active_layer (gimage, lu->prev_layer); /* (counterexample: result layer added after a merge op has no previous layer.) */
if(GIMP_IS_LAYER (lu->prev_layer))
gimp_image_set_active_layer (gimage, lu->prev_layer);
/* remove the layer */ /* remove the layer */
gimp_container_remove (gimage->layers, GIMP_OBJECT (lu->layer)); gimp_container_remove (gimage->layers, GIMP_OBJECT (lu->layer));

View file

@ -493,6 +493,8 @@ undo_history_shell_destroy_callback (GtkWidget *widget,
g_signal_handlers_disconnect_by_func (G_OBJECT (st->gimage), g_signal_handlers_disconnect_by_func (G_OBJECT (st->gimage),
undo_history_clean_callback, undo_history_clean_callback,
st); st);
g_object_unref(G_OBJECT(st->gimage));
} }
g_free (st); g_free (st);
@ -784,6 +786,7 @@ undo_history_new (GimpImage *gimage)
st = g_new0 (undo_history_st, 1); st = g_new0 (undo_history_st, 1);
st->gimage = gimage; st->gimage = gimage;
g_object_ref(G_OBJECT(gimage));
st->preview_size = gimage->gimp->config->preview_size; st->preview_size = gimage->gimp->config->preview_size;
/* gimage signals */ /* gimage signals */

View file

@ -339,16 +339,21 @@ gimp_viewable_dialog_close (GimpViewableDialog *dialog)
GdkEventAny event; GdkEventAny event;
widget = GTK_WIDGET (dialog); widget = GTK_WIDGET (dialog);
/* Paranoia: Widget realized in a window? */
if(G_IS_OBJECT (widget->window) == TRUE)
{
/* Synthesize delete_event to close dialog. */
/* Synthesize delete_event to close dialog. */ event.type = GDK_DELETE;
event.window = widget->window;
event.send_event = TRUE;
event.type = GDK_DELETE; g_object_ref (G_OBJECT (event.window));
event.window = widget->window;
event.send_event = TRUE;
g_object_ref (G_OBJECT (event.window)); gtk_main_do_event ((GdkEvent *) &event);
gtk_main_do_event ((GdkEvent *) &event); g_object_unref (G_OBJECT (event.window));
}
g_object_unref (G_OBJECT (event.window));
} }