diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
commit | 5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch) | |
tree | cbffb45144febf451e54061db2b21395faf94bfe /app/tools/gimpaligntool.c | |
parent | Initial commit. (diff) | |
download | gimp-63d1391ab989f6cb1b9abeaca4ec268574f16491.tar.xz gimp-63d1391ab989f6cb1b9abeaca4ec268574f16491.zip |
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'app/tools/gimpaligntool.c')
-rw-r--r-- | app/tools/gimpaligntool.c | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/app/tools/gimpaligntool.c b/app/tools/gimpaligntool.c new file mode 100644 index 0000000..4698993 --- /dev/null +++ b/app/tools/gimpaligntool.c @@ -0,0 +1,824 @@ +/* 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 <gdk/gdkkeysyms.h> + +#include "libgimpmath/gimpmath.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "tools-types.h" + +#include "config/gimpdisplayconfig.h" + +#include "core/gimp.h" +#include "core/gimpguide.h" +#include "core/gimpimage.h" +#include "core/gimpimage-arrange.h" +#include "core/gimpimage-pick-item.h" +#include "core/gimpimage-undo.h" +#include "core/gimplayer.h" + +#include "vectors/gimpvectors.h" + +#include "widgets/gimphelp-ids.h" +#include "widgets/gimpwidgets-utils.h" + +#include "display/gimpdisplay.h" +#include "display/gimpdisplayshell.h" +#include "display/gimpdisplayshell-appearance.h" + +#include "gimpalignoptions.h" +#include "gimpaligntool.h" +#include "gimptoolcontrol.h" + +#include "gimp-intl.h" + + +#define EPSILON 3 /* move distance after which we do a box-select */ + + +/* local function prototypes */ + +static void gimp_align_tool_constructed (GObject *object); + +static void gimp_align_tool_control (GimpTool *tool, + GimpToolAction action, + GimpDisplay *display); +static void gimp_align_tool_button_press (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonPressType press_type, + GimpDisplay *display); +static void gimp_align_tool_button_release (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonReleaseType release_type, + GimpDisplay *display); +static void gimp_align_tool_motion (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *display); +static gboolean gimp_align_tool_key_press (GimpTool *tool, + GdkEventKey *kevent, + GimpDisplay *display); +static void gimp_align_tool_oper_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + gboolean proximity, + GimpDisplay *display); +static void gimp_align_tool_status_update (GimpTool *tool, + GimpDisplay *display, + GdkModifierType state, + gboolean proximity); +static void gimp_align_tool_cursor_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + GimpDisplay *display); + +static void gimp_align_tool_draw (GimpDrawTool *draw_tool); + +static void gimp_align_tool_align (GimpAlignTool *align_tool, + GimpAlignmentType align_type); + +static void gimp_align_tool_object_removed (GObject *object, + GimpAlignTool *align_tool); +static void gimp_align_tool_clear_selected (GimpAlignTool *align_tool); + + +G_DEFINE_TYPE (GimpAlignTool, gimp_align_tool, GIMP_TYPE_DRAW_TOOL) + +#define parent_class gimp_align_tool_parent_class + + +void +gimp_align_tool_register (GimpToolRegisterCallback callback, + gpointer data) +{ + (* callback) (GIMP_TYPE_ALIGN_TOOL, + GIMP_TYPE_ALIGN_OPTIONS, + gimp_align_options_gui, + 0, + "gimp-align-tool", + _("Alignment"), + _("Alignment Tool: Align or arrange layers and other objects"), + N_("_Align"), "Q", + NULL, GIMP_HELP_TOOL_ALIGN, + GIMP_ICON_TOOL_ALIGN, + data); +} + +static void +gimp_align_tool_class_init (GimpAlignToolClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass); + GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass); + + object_class->constructed = gimp_align_tool_constructed; + + tool_class->control = gimp_align_tool_control; + tool_class->button_press = gimp_align_tool_button_press; + tool_class->button_release = gimp_align_tool_button_release; + tool_class->motion = gimp_align_tool_motion; + tool_class->key_press = gimp_align_tool_key_press; + tool_class->oper_update = gimp_align_tool_oper_update; + tool_class->cursor_update = gimp_align_tool_cursor_update; + + draw_tool_class->draw = gimp_align_tool_draw; +} + +static void +gimp_align_tool_init (GimpAlignTool *align_tool) +{ + GimpTool *tool = GIMP_TOOL (align_tool); + + gimp_tool_control_set_snap_to (tool->control, FALSE); + gimp_tool_control_set_precision (tool->control, + GIMP_CURSOR_PRECISION_PIXEL_BORDER); + gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_MOVE); + + align_tool->function = ALIGN_TOOL_IDLE; +} + +static void +gimp_align_tool_constructed (GObject *object) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (object); + GimpAlignOptions *options; + + G_OBJECT_CLASS (parent_class)->constructed (object); + + options = GIMP_ALIGN_TOOL_GET_OPTIONS (align_tool); + + g_signal_connect_object (options, "align-button-clicked", + G_CALLBACK (gimp_align_tool_align), + align_tool, G_CONNECT_SWAPPED); +} + +static void +gimp_align_tool_control (GimpTool *tool, + GimpToolAction action, + GimpDisplay *display) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + + switch (action) + { + case GIMP_TOOL_ACTION_PAUSE: + case GIMP_TOOL_ACTION_RESUME: + break; + + case GIMP_TOOL_ACTION_HALT: + gimp_align_tool_clear_selected (align_tool); + break; + + case GIMP_TOOL_ACTION_COMMIT: + break; + } + + GIMP_TOOL_CLASS (parent_class)->control (tool, action, display); +} + +static void +gimp_align_tool_button_press (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonPressType press_type, + GimpDisplay *display) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + + gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); + + /* If the tool was being used in another image... reset it */ + if (display != tool->display) + gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); + + tool->display = display; + + gimp_tool_control_activate (tool->control); + + align_tool->x2 = align_tool->x1 = coords->x; + align_tool->y2 = align_tool->y1 = coords->y; + + if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tool))) + gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display); + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); +} + +/* some rather complex logic here. If the user clicks without modifiers, + * then we start a new list, and use the first object in it as reference. + * If the user clicks using Shift, or draws a rubber-band box, then + * we add objects to the list, but do not specify which one should + * be used as reference. + */ +static void +gimp_align_tool_button_release (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonReleaseType release_type, + GimpDisplay *display) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (tool); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GObject *object = NULL; + GimpImage *image = gimp_display_get_image (display); + GdkModifierType extend_mask; + gint i; + + extend_mask = gimp_get_extend_selection_mask (); + + gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); + + gimp_tool_control_halt (tool->control); + + if (release_type == GIMP_BUTTON_RELEASE_CANCEL) + { + align_tool->x2 = align_tool->x1; + align_tool->y2 = align_tool->y1; + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); + return; + } + + if (! (state & extend_mask)) /* start a new list */ + { + gimp_align_tool_clear_selected (align_tool); + align_tool->set_reference = FALSE; + } + + /* if mouse has moved less than EPSILON pixels since button press, + * select the nearest thing, otherwise make a rubber-band rectangle + */ + if (hypot (coords->x - align_tool->x1, + coords->y - align_tool->y1) < EPSILON) + { + GimpVectors *vectors; + GimpGuide *guide; + GimpLayer *layer; + gint snap_distance = display->config->snap_distance; + + if ((vectors = gimp_image_pick_vectors (image, + coords->x, coords->y, + FUNSCALEX (shell, snap_distance), + FUNSCALEY (shell, snap_distance)))) + { + object = G_OBJECT (vectors); + } + else if (gimp_display_shell_get_show_guides (shell) && + (guide = gimp_image_pick_guide (image, + coords->x, coords->y, + FUNSCALEX (shell, snap_distance), + FUNSCALEY (shell, snap_distance)))) + { + object = G_OBJECT (guide); + } + else if ((layer = gimp_image_pick_layer_by_bounds (image, + coords->x, coords->y))) + { + object = G_OBJECT (layer); + } + + if (object) + { + if (! g_list_find (align_tool->selected_objects, object)) + { + align_tool->selected_objects = + g_list_append (align_tool->selected_objects, object); + + g_signal_connect (object, "removed", + G_CALLBACK (gimp_align_tool_object_removed), + align_tool); + + /* if an object has been selected using unmodified click, + * it should be used as the reference + */ + if (! (state & extend_mask)) + align_tool->set_reference = TRUE; + } + } + } + else /* FIXME: look for vectors too */ + { + gint X0 = MIN (coords->x, align_tool->x1); + gint X1 = MAX (coords->x, align_tool->x1); + gint Y0 = MIN (coords->y, align_tool->y1); + gint Y1 = MAX (coords->y, align_tool->y1); + GList *all_layers; + GList *list; + + all_layers = gimp_image_get_layer_list (image); + + for (list = all_layers; list; list = g_list_next (list)) + { + GimpLayer *layer = list->data; + gint x0, y0, x1, y1; + + if (! gimp_item_get_visible (GIMP_ITEM (layer))) + continue; + + gimp_item_get_offset (GIMP_ITEM (layer), &x0, &y0); + x1 = x0 + gimp_item_get_width (GIMP_ITEM (layer)); + y1 = y0 + gimp_item_get_height (GIMP_ITEM (layer)); + + if (x0 < X0 || y0 < Y0 || x1 > X1 || y1 > Y1) + continue; + + if (g_list_find (align_tool->selected_objects, layer)) + continue; + + align_tool->selected_objects = + g_list_append (align_tool->selected_objects, layer); + + g_signal_connect (layer, "removed", + G_CALLBACK (gimp_align_tool_object_removed), + align_tool); + } + + g_list_free (all_layers); + } + + for (i = 0; i < ALIGN_OPTIONS_N_BUTTONS; i++) + { + if (options->button[i]) + gtk_widget_set_sensitive (options->button[i], + align_tool->selected_objects != NULL); + } + + align_tool->x2 = align_tool->x1; + align_tool->y2 = align_tool->y1; + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); +} + +static void +gimp_align_tool_motion (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *display) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + + gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); + + align_tool->x2 = coords->x; + align_tool->y2 = coords->y; + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); +} + +static gboolean +gimp_align_tool_key_press (GimpTool *tool, + GdkEventKey *kevent, + GimpDisplay *display) +{ + if (display == tool->display) + { + switch (kevent->keyval) + { + case GDK_KEY_Escape: + gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); + return TRUE; + + default: + break; + } + } + + return FALSE; +} + +static void +gimp_align_tool_oper_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + gboolean proximity, + GimpDisplay *display) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpImage *image = gimp_display_get_image (display); + gint snap_distance = display->config->snap_distance; + gboolean add; + + add = ((state & gimp_get_extend_selection_mask ()) && + align_tool->selected_objects); + + if (gimp_image_pick_vectors (image, + coords->x, coords->y, + FUNSCALEX (shell, snap_distance), + FUNSCALEY (shell, snap_distance))) + { + if (add) + align_tool->function = ALIGN_TOOL_ADD_PATH; + else + align_tool->function = ALIGN_TOOL_PICK_PATH; + } + else if (gimp_display_shell_get_show_guides (shell) && + gimp_image_pick_guide (image, + coords->x, coords->y, + FUNSCALEX (shell, snap_distance), + FUNSCALEY (shell, snap_distance))) + { + if (add) + align_tool->function = ALIGN_TOOL_ADD_GUIDE; + else + align_tool->function = ALIGN_TOOL_PICK_GUIDE; + } + else if (gimp_image_pick_layer_by_bounds (image, coords->x, coords->y)) + { + if (add) + align_tool->function = ALIGN_TOOL_ADD_LAYER; + else + align_tool->function = ALIGN_TOOL_PICK_LAYER; + } + else + { + align_tool->function = ALIGN_TOOL_IDLE; + } + + gimp_align_tool_status_update (tool, display, state, proximity); +} + +static void +gimp_align_tool_cursor_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + GimpDisplay *display) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + GimpToolCursorType tool_cursor = GIMP_TOOL_CURSOR_NONE; + GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_NONE; + + /* always add '+' when Shift is pressed, even if nothing is selected */ + if (state & gimp_get_extend_selection_mask ()) + modifier = GIMP_CURSOR_MODIFIER_PLUS; + + switch (align_tool->function) + { + case ALIGN_TOOL_IDLE: + tool_cursor = GIMP_TOOL_CURSOR_RECT_SELECT; + break; + + case ALIGN_TOOL_PICK_LAYER: + case ALIGN_TOOL_ADD_LAYER: + tool_cursor = GIMP_TOOL_CURSOR_HAND; + break; + + case ALIGN_TOOL_PICK_GUIDE: + case ALIGN_TOOL_ADD_GUIDE: + tool_cursor = GIMP_TOOL_CURSOR_MOVE; + break; + + case ALIGN_TOOL_PICK_PATH: + case ALIGN_TOOL_ADD_PATH: + tool_cursor = GIMP_TOOL_CURSOR_PATHS; + break; + + case ALIGN_TOOL_DRAG_BOX: + break; + } + + gimp_tool_control_set_cursor (tool->control, GIMP_CURSOR_MOUSE); + gimp_tool_control_set_tool_cursor (tool->control, tool_cursor); + gimp_tool_control_set_cursor_modifier (tool->control, modifier); + + GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display); +} + +static void +gimp_align_tool_status_update (GimpTool *tool, + GimpDisplay *display, + GdkModifierType state, + gboolean proximity) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (tool); + GdkModifierType extend_mask; + + extend_mask = gimp_get_extend_selection_mask (); + + gimp_tool_pop_status (tool, display); + + if (proximity) + { + gchar *status = NULL; + + if (! align_tool->selected_objects) + { + /* no need to suggest Shift if nothing is selected */ + state |= extend_mask; + } + + switch (align_tool->function) + { + case ALIGN_TOOL_IDLE: + status = gimp_suggest_modifiers (_("Click on a layer, path or guide, " + "or Click-Drag to pick several " + "layers"), + extend_mask & ~state, + NULL, NULL, NULL); + break; + + case ALIGN_TOOL_PICK_LAYER: + status = gimp_suggest_modifiers (_("Click to pick this layer as " + "first item"), + extend_mask & ~state, + NULL, NULL, NULL); + break; + + case ALIGN_TOOL_ADD_LAYER: + status = g_strdup (_("Click to add this layer to the list")); + break; + + case ALIGN_TOOL_PICK_GUIDE: + status = gimp_suggest_modifiers (_("Click to pick this guide as " + "first item"), + extend_mask & ~state, + NULL, NULL, NULL); + break; + + case ALIGN_TOOL_ADD_GUIDE: + status = g_strdup (_("Click to add this guide to the list")); + break; + + case ALIGN_TOOL_PICK_PATH: + status = gimp_suggest_modifiers (_("Click to pick this path as " + "first item"), + extend_mask & ~state, + NULL, NULL, NULL); + break; + + case ALIGN_TOOL_ADD_PATH: + status = g_strdup (_("Click to add this path to the list")); + break; + + case ALIGN_TOOL_DRAG_BOX: + break; + } + + if (status) + { + gimp_tool_push_status (tool, display, "%s", status); + g_free (status); + } + } +} + +static void +gimp_align_tool_draw (GimpDrawTool *draw_tool) +{ + GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (draw_tool); + GList *list; + gint x, y, w, h; + + /* draw rubber-band rectangle */ + x = MIN (align_tool->x2, align_tool->x1); + y = MIN (align_tool->y2, align_tool->y1); + w = MAX (align_tool->x2, align_tool->x1) - x; + h = MAX (align_tool->y2, align_tool->y1) - y; + + gimp_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h); + + for (list = align_tool->selected_objects; + list; + list = g_list_next (list)) + { + if (GIMP_IS_ITEM (list->data)) + { + GimpItem *item = list->data; + gint off_x, off_y; + + gimp_item_bounds (item, &x, &y, &w, &h); + + gimp_item_get_offset (item, &off_x, &off_y); + x += off_x; + y += off_y; + + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + x, y, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_NORTH_WEST); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + x + w, y, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_NORTH_EAST); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + x, y + h, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_SOUTH_WEST); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + x + w, y + h, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_SOUTH_EAST); + } + else if (GIMP_IS_GUIDE (list->data)) + { + GimpGuide *guide = list->data; + GimpImage *image = gimp_display_get_image (GIMP_TOOL (draw_tool)->display); + gint x, y; + gint w, h; + + switch (gimp_guide_get_orientation (guide)) + { + case GIMP_ORIENTATION_VERTICAL: + x = gimp_guide_get_position (guide); + h = gimp_image_get_height (image); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + x, h, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_SOUTH); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + x, 0, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_NORTH); + break; + + case GIMP_ORIENTATION_HORIZONTAL: + y = gimp_guide_get_position (guide); + w = gimp_image_get_width (image); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + w, y, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_EAST); + gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, + 0, y, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_TOOL_HANDLE_SIZE_SMALL, + GIMP_HANDLE_ANCHOR_WEST); + break; + + default: + break; + } + } + } +} + +static void +gimp_align_tool_align (GimpAlignTool *align_tool, + GimpAlignmentType align_type) +{ + GimpAlignOptions *options = GIMP_ALIGN_TOOL_GET_OPTIONS (align_tool); + GimpImage *image; + GObject *reference_object = NULL; + GList *list; + gint offset = 0; + + /* if nothing is selected, just return */ + if (! align_tool->selected_objects) + return; + + image = gimp_display_get_image (GIMP_TOOL (align_tool)->display); + + switch (align_type) + { + case GIMP_ALIGN_LEFT: + case GIMP_ALIGN_HCENTER: + case GIMP_ALIGN_RIGHT: + case GIMP_ALIGN_TOP: + case GIMP_ALIGN_VCENTER: + case GIMP_ALIGN_BOTTOM: + offset = 0; + break; + + case GIMP_ARRANGE_LEFT: + case GIMP_ARRANGE_HCENTER: + case GIMP_ARRANGE_RIGHT: + case GIMP_ARRANGE_HFILL: + offset = options->offset_x; + break; + + case GIMP_ARRANGE_TOP: + case GIMP_ARRANGE_VCENTER: + case GIMP_ARRANGE_BOTTOM: + case GIMP_ARRANGE_VFILL: + offset = options->offset_y; + break; + } + + /* if only one object is selected, use the image as reference + * if multiple objects are selected, use the first one as reference if + * "set_reference" is TRUE, otherwise use NULL. + */ + + list = align_tool->selected_objects; + + switch (options->align_reference) + { + case GIMP_ALIGN_REFERENCE_IMAGE: + reference_object = G_OBJECT (image); + break; + + case GIMP_ALIGN_REFERENCE_FIRST: + if (g_list_length (list) == 1) + { + reference_object = G_OBJECT (image); + } + else + { + if (align_tool->set_reference) + { + reference_object = G_OBJECT (list->data); + list = g_list_next (list); + } + else + { + reference_object = NULL; + } + } + break; + + case GIMP_ALIGN_REFERENCE_SELECTION: + reference_object = G_OBJECT (gimp_image_get_mask (image)); + break; + + case GIMP_ALIGN_REFERENCE_ACTIVE_LAYER: + reference_object = G_OBJECT (gimp_image_get_active_layer (image)); + break; + + case GIMP_ALIGN_REFERENCE_ACTIVE_CHANNEL: + reference_object = G_OBJECT (gimp_image_get_active_channel (image)); + break; + + case GIMP_ALIGN_REFERENCE_ACTIVE_PATH: + reference_object = G_OBJECT (gimp_image_get_active_vectors (image)); + break; + } + + if (! reference_object) + return; + + gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool)); + + gimp_image_arrange_objects (image, list, + align_type, + reference_object, + align_type, + offset); + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool)); + + gimp_image_flush (image); +} + +static void +gimp_align_tool_object_removed (GObject *object, + GimpAlignTool *align_tool) +{ + gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool)); + + if (align_tool->selected_objects) + g_signal_handlers_disconnect_by_func (object, + gimp_align_tool_object_removed, + align_tool); + + align_tool->selected_objects = g_list_remove (align_tool->selected_objects, + object); + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool)); +} + +static void +gimp_align_tool_clear_selected (GimpAlignTool *align_tool) +{ + gimp_draw_tool_pause (GIMP_DRAW_TOOL (align_tool)); + + while (align_tool->selected_objects) + gimp_align_tool_object_removed (align_tool->selected_objects->data, + align_tool); + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (align_tool)); +} |