summaryrefslogtreecommitdiffstats
path: root/app/tools/gimpcroptool.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 03:13:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 03:13:10 +0000
commit3c57dd931145d43f2b0aef96c4d178135956bf91 (patch)
tree3de698981e9f0cc2c4f9569b19a5f3595e741f6b /app/tools/gimpcroptool.c
parentInitial commit. (diff)
downloadgimp-3c57dd931145d43f2b0aef96c4d178135956bf91.tar.xz
gimp-3c57dd931145d43f2b0aef96c4d178135956bf91.zip
Adding upstream version 2.10.36.upstream/2.10.36
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'app/tools/gimpcroptool.c')
-rw-r--r--app/tools/gimpcroptool.c723
1 files changed, 723 insertions, 0 deletions
diff --git a/app/tools/gimpcroptool.c b/app/tools/gimpcroptool.c
new file mode 100644
index 0000000..1803d00
--- /dev/null
+++ b/app/tools/gimpcroptool.c
@@ -0,0 +1,723 @@
+/* GIMP - The GNU 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 3 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "tools-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-crop.h"
+#include "core/gimpitem.h"
+#include "core/gimptoolinfo.h"
+
+#include "widgets/gimphelp-ids.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplayshell.h"
+#include "display/gimptoolrectangle.h"
+
+#include "gimpcropoptions.h"
+#include "gimpcroptool.h"
+#include "gimprectangleoptions.h"
+#include "gimptoolcontrol.h"
+#include "gimptools-utils.h"
+
+#include "gimp-intl.h"
+
+
+static void gimp_crop_tool_constructed (GObject *object);
+static void gimp_crop_tool_dispose (GObject *object);
+
+static void gimp_crop_tool_control (GimpTool *tool,
+ GimpToolAction action,
+ GimpDisplay *display);
+static void gimp_crop_tool_button_press (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type,
+ GimpDisplay *display);
+static void gimp_crop_tool_button_release (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type,
+ GimpDisplay *display);
+static void gimp_crop_tool_motion (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpDisplay *display);
+static void gimp_crop_tool_options_notify (GimpTool *tool,
+ GimpToolOptions *options,
+ const GParamSpec *pspec);
+
+static void gimp_crop_tool_rectangle_changed (GimpToolWidget *rectangle,
+ GimpCropTool *crop_tool);
+static void gimp_crop_tool_rectangle_response (GimpToolWidget *rectangle,
+ gint response_id,
+ GimpCropTool *crop_tool);
+static void gimp_crop_tool_rectangle_change_complete (GimpToolRectangle *rectangle,
+ GimpCropTool *crop_tool);
+
+static void gimp_crop_tool_start (GimpCropTool *crop_tool,
+ GimpDisplay *display);
+static void gimp_crop_tool_commit (GimpCropTool *crop_tool);
+static void gimp_crop_tool_halt (GimpCropTool *crop_tool);
+
+static void gimp_crop_tool_update_option_defaults (GimpCropTool *crop_tool,
+ gboolean ignore_pending);
+static GimpRectangleConstraint
+ gimp_crop_tool_get_constraint (GimpCropTool *crop_tool);
+
+static void gimp_crop_tool_image_changed (GimpCropTool *crop_tool,
+ GimpImage *image,
+ GimpContext *context);
+static void gimp_crop_tool_image_size_changed (GimpCropTool *crop_tool);
+static void gimp_crop_tool_image_active_layer_changed (GimpCropTool *crop_tool);
+static void gimp_crop_tool_layer_size_changed (GimpCropTool *crop_tool);
+
+static void gimp_crop_tool_auto_shrink (GimpCropTool *crop_tool);
+
+
+G_DEFINE_TYPE (GimpCropTool, gimp_crop_tool, GIMP_TYPE_DRAW_TOOL)
+
+#define parent_class gimp_crop_tool_parent_class
+
+
+/* public functions */
+
+void
+gimp_crop_tool_register (GimpToolRegisterCallback callback,
+ gpointer data)
+{
+ (* callback) (GIMP_TYPE_CROP_TOOL,
+ GIMP_TYPE_CROP_OPTIONS,
+ gimp_crop_options_gui,
+ GIMP_CONTEXT_PROP_MASK_FOREGROUND |
+ GIMP_CONTEXT_PROP_MASK_BACKGROUND |
+ GIMP_CONTEXT_PROP_MASK_PATTERN,
+ "gimp-crop-tool",
+ _("Crop"),
+ _("Crop Tool: Remove edge areas from image or layer"),
+ N_("_Crop"), "<shift>C",
+ NULL, GIMP_HELP_TOOL_CROP,
+ GIMP_ICON_TOOL_CROP,
+ data);
+}
+
+static void
+gimp_crop_tool_class_init (GimpCropToolClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
+
+ object_class->constructed = gimp_crop_tool_constructed;
+ object_class->dispose = gimp_crop_tool_dispose;
+
+ tool_class->control = gimp_crop_tool_control;
+ tool_class->button_press = gimp_crop_tool_button_press;
+ tool_class->button_release = gimp_crop_tool_button_release;
+ tool_class->motion = gimp_crop_tool_motion;
+ tool_class->options_notify = gimp_crop_tool_options_notify;
+}
+
+static void
+gimp_crop_tool_init (GimpCropTool *crop_tool)
+{
+ GimpTool *tool = GIMP_TOOL (crop_tool);
+
+ gimp_tool_control_set_wants_click (tool->control, TRUE);
+ gimp_tool_control_set_active_modifiers (tool->control,
+ GIMP_TOOL_ACTIVE_MODIFIERS_SEPARATE);
+ gimp_tool_control_set_precision (tool->control,
+ GIMP_CURSOR_PRECISION_PIXEL_BORDER);
+ gimp_tool_control_set_cursor (tool->control,
+ GIMP_CURSOR_CROSSHAIR_SMALL);
+ gimp_tool_control_set_tool_cursor (tool->control,
+ GIMP_TOOL_CURSOR_CROP);
+
+ gimp_draw_tool_set_default_status (GIMP_DRAW_TOOL (tool),
+ _("Click-Drag to draw a crop rectangle"));
+}
+
+static void
+gimp_crop_tool_constructed (GObject *object)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (object);
+ GimpContext *context;
+ GimpToolInfo *tool_info;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ tool_info = GIMP_TOOL (crop_tool)->tool_info;
+
+ context = gimp_get_user_context (tool_info->gimp);
+
+ g_signal_connect_object (context, "image-changed",
+ G_CALLBACK (gimp_crop_tool_image_changed),
+ crop_tool,
+ G_CONNECT_SWAPPED);
+
+ /* Make sure we are connected to "size-changed" for the initial
+ * image.
+ */
+ gimp_crop_tool_image_changed (crop_tool,
+ gimp_context_get_image (context),
+ context);
+}
+
+static void
+gimp_crop_tool_dispose (GObject *object)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (object);
+
+ /* Clean up current_image and current_layer. */
+ gimp_crop_tool_image_changed (crop_tool, NULL, NULL);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_crop_tool_control (GimpTool *tool,
+ GimpToolAction action,
+ GimpDisplay *display)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (tool);
+
+ switch (action)
+ {
+ case GIMP_TOOL_ACTION_PAUSE:
+ case GIMP_TOOL_ACTION_RESUME:
+ break;
+
+ case GIMP_TOOL_ACTION_HALT:
+ gimp_crop_tool_halt (crop_tool);
+ break;
+
+ case GIMP_TOOL_ACTION_COMMIT:
+ gimp_crop_tool_commit (crop_tool);
+ break;
+ }
+
+ GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
+}
+
+static void
+gimp_crop_tool_button_press (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type,
+ GimpDisplay *display)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (tool);
+
+ if (tool->display && display != tool->display)
+ gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
+
+ if (! tool->display)
+ {
+ gimp_crop_tool_start (crop_tool, display);
+
+ gimp_tool_widget_hover (crop_tool->widget, coords, state, TRUE);
+
+ /* HACK: force CREATING on a newly created rectangle; otherwise,
+ * property bindings would cause the rectangle to start with the
+ * size from tool options.
+ */
+ gimp_tool_rectangle_set_function (GIMP_TOOL_RECTANGLE (crop_tool->widget),
+ GIMP_TOOL_RECTANGLE_CREATING);
+ }
+
+ if (gimp_tool_widget_button_press (crop_tool->widget, coords, time, state,
+ press_type))
+ {
+ crop_tool->grab_widget = crop_tool->widget;
+ }
+
+ gimp_tool_control_activate (tool->control);
+}
+
+static void
+gimp_crop_tool_button_release (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type,
+ GimpDisplay *display)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (tool);
+
+ gimp_tool_control_halt (tool->control);
+
+ if (crop_tool->grab_widget)
+ {
+ gimp_tool_widget_button_release (crop_tool->grab_widget,
+ coords, time, state, release_type);
+ crop_tool->grab_widget = NULL;
+ }
+
+ gimp_tool_push_status (tool, display, _("Click or press Enter to crop"));
+}
+
+static void
+gimp_crop_tool_motion (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpDisplay *display)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (tool);
+
+ if (crop_tool->grab_widget)
+ {
+ gimp_tool_widget_motion (crop_tool->grab_widget, coords, time, state);
+ }
+}
+
+static void
+gimp_crop_tool_options_notify (GimpTool *tool,
+ GimpToolOptions *options,
+ const GParamSpec *pspec)
+{
+ GimpCropTool *crop_tool = GIMP_CROP_TOOL (tool);
+
+ if (! strcmp (pspec->name, "layer-only") ||
+ ! strcmp (pspec->name, "allow-growing"))
+ {
+ if (crop_tool->widget)
+ {
+ gimp_tool_rectangle_set_constraint (GIMP_TOOL_RECTANGLE (crop_tool->widget),
+ gimp_crop_tool_get_constraint (crop_tool));
+ }
+ else
+ {
+ gimp_crop_tool_update_option_defaults (crop_tool, FALSE);
+ }
+ }
+}
+
+static void
+gimp_crop_tool_rectangle_changed (GimpToolWidget *rectangle,
+ GimpCropTool *crop_tool)
+{
+}
+
+static void
+gimp_crop_tool_rectangle_response (GimpToolWidget *rectangle,
+ gint response_id,
+ GimpCropTool *crop_tool)
+{
+ GimpTool *tool = GIMP_TOOL (crop_tool);
+
+ switch (response_id)
+ {
+ case GIMP_TOOL_WIDGET_RESPONSE_CONFIRM:
+ gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, tool->display);
+ break;
+
+ case GIMP_TOOL_WIDGET_RESPONSE_CANCEL:
+ gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
+ break;
+ }
+}
+
+static void
+gimp_crop_tool_rectangle_change_complete (GimpToolRectangle *rectangle,
+ GimpCropTool *crop_tool)
+{
+ gimp_crop_tool_update_option_defaults (crop_tool, FALSE);
+}
+
+static void
+gimp_crop_tool_start (GimpCropTool *crop_tool,
+ GimpDisplay *display)
+{
+ static const gchar *properties[] =
+ {
+ "highlight",
+ "highlight-opacity",
+ "guide",
+ "x",
+ "y",
+ "width",
+ "height",
+ "fixed-rule-active",
+ "fixed-rule",
+ "desired-fixed-width",
+ "desired-fixed-height",
+ "desired-fixed-size-width",
+ "desired-fixed-size-height",
+ "aspect-numerator",
+ "aspect-denominator",
+ "fixed-center"
+ };
+
+ GimpTool *tool = GIMP_TOOL (crop_tool);
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GimpCropOptions *options = GIMP_CROP_TOOL_GET_OPTIONS (crop_tool);
+ GimpToolWidget *widget;
+ gint i;
+
+ tool->display = display;
+
+ crop_tool->widget = widget = gimp_tool_rectangle_new (shell);
+
+ g_object_set (widget,
+ "status-title", _("Crop to: "),
+ NULL);
+
+ gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), widget);
+
+ for (i = 0; i < G_N_ELEMENTS (properties); i++)
+ {
+ GBinding *binding =
+ g_object_bind_property (G_OBJECT (options), properties[i],
+ G_OBJECT (widget), properties[i],
+ G_BINDING_SYNC_CREATE |
+ G_BINDING_BIDIRECTIONAL);
+
+ crop_tool->bindings = g_list_prepend (crop_tool->bindings, binding);
+ }
+
+ gimp_rectangle_options_connect (GIMP_RECTANGLE_OPTIONS (options),
+ gimp_display_get_image (shell->display),
+ G_CALLBACK (gimp_crop_tool_auto_shrink),
+ crop_tool);
+
+ gimp_tool_rectangle_set_constraint (GIMP_TOOL_RECTANGLE (widget),
+ gimp_crop_tool_get_constraint (crop_tool));
+
+ g_signal_connect (widget, "changed",
+ G_CALLBACK (gimp_crop_tool_rectangle_changed),
+ crop_tool);
+ g_signal_connect (widget, "response",
+ G_CALLBACK (gimp_crop_tool_rectangle_response),
+ crop_tool);
+ g_signal_connect (widget, "change-complete",
+ G_CALLBACK (gimp_crop_tool_rectangle_change_complete),
+ crop_tool);
+
+ gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
+}
+
+static void
+gimp_crop_tool_commit (GimpCropTool *crop_tool)
+{
+ GimpTool *tool = GIMP_TOOL (crop_tool);
+
+ if (tool->display)
+ {
+ GimpCropOptions *options = GIMP_CROP_TOOL_GET_OPTIONS (tool);
+ GimpImage *image = gimp_display_get_image (tool->display);
+ gdouble x, y;
+ gdouble x2, y2;
+ gint w, h;
+
+ gimp_tool_rectangle_get_public_rect (GIMP_TOOL_RECTANGLE (crop_tool->widget),
+ &x, &y, &x2, &y2);
+ w = x2 - x;
+ h = y2 - y;
+
+ gimp_tool_pop_status (tool, tool->display);
+
+ /* if rectangle exists, crop it */
+ if (w > 0 && h > 0)
+ {
+ if (options->layer_only)
+ {
+ GimpLayer *layer = gimp_image_get_active_layer (image);
+ gint off_x, off_y;
+
+ if (! layer)
+ {
+ gimp_tool_message_literal (tool, tool->display,
+ _("There is no active layer to crop."));
+ return;
+ }
+
+ if (gimp_item_is_content_locked (GIMP_ITEM (layer)))
+ {
+ gimp_tool_message_literal (tool, tool->display,
+ _("The active layer's pixels are locked."));
+ gimp_tools_blink_lock_box (tool->display->gimp,
+ GIMP_ITEM (layer));
+ return;
+ }
+
+ gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y);
+
+ off_x -= x;
+ off_y -= y;
+
+ gimp_item_resize (GIMP_ITEM (layer),
+ GIMP_CONTEXT (options), options->fill_type,
+ w, h, off_x, off_y);
+ }
+ else
+ {
+ gimp_image_crop (image,
+ GIMP_CONTEXT (options), GIMP_FILL_TRANSPARENT,
+ x, y, w, h, options->delete_pixels);
+ }
+
+ gimp_image_flush (image);
+ }
+ }
+}
+
+static void
+gimp_crop_tool_halt (GimpCropTool *crop_tool)
+{
+ GimpTool *tool = GIMP_TOOL (crop_tool);
+ GimpCropOptions *options = GIMP_CROP_TOOL_GET_OPTIONS (crop_tool);
+
+ if (tool->display)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
+
+ gimp_display_shell_set_highlight (shell, NULL, 0.0);
+
+ gimp_rectangle_options_disconnect (GIMP_RECTANGLE_OPTIONS (options),
+ G_CALLBACK (gimp_crop_tool_auto_shrink),
+ crop_tool);
+ }
+
+ if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool)))
+ gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));
+
+ /* disconnect bindings manually so they are really gone *now*, we
+ * might be in the middle of a signal emission that keeps the
+ * widget and its bindings alive.
+ */
+ g_list_free_full (crop_tool->bindings, (GDestroyNotify) g_object_unref);
+ crop_tool->bindings = NULL;
+
+ gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
+ g_clear_object (&crop_tool->widget);
+
+ tool->display = NULL;
+ tool->drawable = NULL;
+
+ gimp_crop_tool_update_option_defaults (crop_tool, TRUE);
+}
+
+/**
+ * gimp_crop_tool_update_option_defaults:
+ * @crop_tool:
+ * @ignore_pending: %TRUE to ignore any pending crop rectangle.
+ *
+ * Sets the default Fixed: Aspect ratio and Fixed: Size option
+ * properties.
+ */
+static void
+gimp_crop_tool_update_option_defaults (GimpCropTool *crop_tool,
+ gboolean ignore_pending)
+{
+ GimpTool *tool = GIMP_TOOL (crop_tool);
+ GimpToolRectangle *rectangle = GIMP_TOOL_RECTANGLE (crop_tool->widget);
+ GimpRectangleOptions *options;
+
+ options = GIMP_RECTANGLE_OPTIONS (GIMP_TOOL_GET_OPTIONS (tool));
+
+ if (rectangle && ! ignore_pending)
+ {
+ /* There is a pending rectangle and we should not ignore it, so
+ * set default Fixed: Aspect ratio to the same as the current
+ * pending rectangle width/height.
+ */
+
+ gimp_tool_rectangle_pending_size_set (rectangle,
+ G_OBJECT (options),
+ "default-aspect-numerator",
+ "default-aspect-denominator");
+
+ g_object_set (G_OBJECT (options),
+ "use-string-current", TRUE,
+ NULL);
+ }
+ else
+ {
+ /* There is no pending rectangle, set default Fixed: Aspect
+ * ratio to that of the current image/layer.
+ */
+
+ if (! rectangle)
+ {
+ /* ugly hack: if we don't have a widget, construct a temporary one
+ * so that we can use it to call
+ * gimp_tool_rectangle_constraint_size_set().
+ */
+
+ GimpContext *context = gimp_get_user_context (tool->tool_info->gimp);
+ GimpDisplay *display = gimp_context_get_display (context);
+
+ if (display)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+
+ rectangle = GIMP_TOOL_RECTANGLE (gimp_tool_rectangle_new (shell));
+
+ gimp_tool_rectangle_set_constraint (
+ rectangle, gimp_crop_tool_get_constraint (crop_tool));
+ }
+ }
+
+ if (rectangle)
+ {
+ gimp_tool_rectangle_constraint_size_set (rectangle,
+ G_OBJECT (options),
+ "default-aspect-numerator",
+ "default-aspect-denominator");
+
+ if (! crop_tool->widget)
+ g_object_unref (rectangle);
+ }
+
+ g_object_set (G_OBJECT (options),
+ "use-string-current", FALSE,
+ NULL);
+ }
+}
+
+static GimpRectangleConstraint
+gimp_crop_tool_get_constraint (GimpCropTool *crop_tool)
+{
+ GimpCropOptions *crop_options = GIMP_CROP_TOOL_GET_OPTIONS (crop_tool);
+
+ if (crop_options->allow_growing)
+ {
+ return GIMP_RECTANGLE_CONSTRAIN_NONE;
+ }
+ else
+ {
+ return crop_options->layer_only ? GIMP_RECTANGLE_CONSTRAIN_DRAWABLE :
+ GIMP_RECTANGLE_CONSTRAIN_IMAGE;
+ }
+}
+
+static void
+gimp_crop_tool_image_changed (GimpCropTool *crop_tool,
+ GimpImage *image,
+ GimpContext *context)
+{
+ if (crop_tool->current_image)
+ {
+ g_signal_handlers_disconnect_by_func (crop_tool->current_image,
+ gimp_crop_tool_image_size_changed,
+ NULL);
+ g_signal_handlers_disconnect_by_func (crop_tool->current_image,
+ gimp_crop_tool_image_active_layer_changed,
+ NULL);
+
+ g_object_remove_weak_pointer (G_OBJECT (crop_tool->current_image),
+ (gpointer) &crop_tool->current_image);
+ }
+
+ crop_tool->current_image = image;
+
+ if (crop_tool->current_image)
+ {
+ g_object_add_weak_pointer (G_OBJECT (crop_tool->current_image),
+ (gpointer) &crop_tool->current_image);
+
+ g_signal_connect_object (crop_tool->current_image, "size-changed",
+ G_CALLBACK (gimp_crop_tool_image_size_changed),
+ crop_tool,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (crop_tool->current_image, "active-layer-changed",
+ G_CALLBACK (gimp_crop_tool_image_active_layer_changed),
+ crop_tool,
+ G_CONNECT_SWAPPED);
+ }
+
+ /* Make sure we are connected to "size-changed" for the initial
+ * layer.
+ */
+ gimp_crop_tool_image_active_layer_changed (crop_tool);
+
+ gimp_crop_tool_update_option_defaults (GIMP_CROP_TOOL (crop_tool), FALSE);
+}
+
+static void
+gimp_crop_tool_image_size_changed (GimpCropTool *crop_tool)
+{
+ gimp_crop_tool_update_option_defaults (crop_tool, FALSE);
+}
+
+static void
+gimp_crop_tool_image_active_layer_changed (GimpCropTool *crop_tool)
+{
+ if (crop_tool->current_layer)
+ {
+ g_signal_handlers_disconnect_by_func (crop_tool->current_layer,
+ gimp_crop_tool_layer_size_changed,
+ NULL);
+
+ g_object_remove_weak_pointer (G_OBJECT (crop_tool->current_layer),
+ (gpointer) &crop_tool->current_layer);
+ }
+
+ if (crop_tool->current_image)
+ {
+ crop_tool->current_layer =
+ gimp_image_get_active_layer (crop_tool->current_image);
+ }
+ else
+ {
+ crop_tool->current_layer = NULL;
+ }
+
+ if (crop_tool->current_layer)
+ {
+ g_object_add_weak_pointer (G_OBJECT (crop_tool->current_layer),
+ (gpointer) &crop_tool->current_layer);
+
+ g_signal_connect_object (crop_tool->current_layer, "size-changed",
+ G_CALLBACK (gimp_crop_tool_layer_size_changed),
+ crop_tool,
+ G_CONNECT_SWAPPED);
+ }
+
+ gimp_crop_tool_update_option_defaults (crop_tool, FALSE);
+}
+
+static void
+gimp_crop_tool_layer_size_changed (GimpCropTool *crop_tool)
+{
+ gimp_crop_tool_update_option_defaults (crop_tool, FALSE);
+}
+
+static void
+gimp_crop_tool_auto_shrink (GimpCropTool *crop_tool)
+{
+ gboolean shrink_merged ;
+
+ g_object_get (gimp_tool_get_options (GIMP_TOOL (crop_tool)),
+ "shrink-merged", &shrink_merged,
+ NULL);
+
+ gimp_tool_rectangle_auto_shrink (GIMP_TOOL_RECTANGLE (crop_tool->widget),
+ shrink_merged);
+}