2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1997-11-25 06:05:25 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-25 06:05:25 +08:00
|
|
|
* (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
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-10-23 17:05:45 +08:00
|
|
|
|
2000-02-16 21:52:33 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <stdlib.h>
|
1998-07-20 22:05:33 +08:00
|
|
|
#include <stdarg.h>
|
2000-02-29 03:25:42 +08:00
|
|
|
|
2023-03-19 02:29:11 +08:00
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gprintf.h>
|
|
|
|
|
2008-10-10 04:24:04 +08:00
|
|
|
#include <gegl.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-02-29 03:25:42 +08:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
2015-06-30 21:55:05 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2007-03-09 21:00:01 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
2008-10-23 17:42:55 +08:00
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
2007-03-09 21:00:01 +08:00
|
|
|
|
2002-05-03 20:45:22 +08:00
|
|
|
#include "tools-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2004-04-15 07:37:34 +08:00
|
|
|
#include "core/gimp.h"
|
2009-04-23 03:08:42 +08:00
|
|
|
#include "core/gimp-utils.h"
|
2012-03-19 21:22:41 +08:00
|
|
|
#include "core/gimpboundary.h"
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
#include "core/gimpgrouplayer.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpimage.h"
|
include the new "paint-funcs/paint-funcs-types.h".
2001-11-28 Michael Natterer <mitch@gimp.org>
* app/base/base-types.h: include the new
"paint-funcs/paint-funcs-types.h".
* app/paint-funcs/Makefile.am
* app/paint-funcs/paint-funcs-types.h: new file. Includes
"base/base-types.h".
* app/paint-funcs/paint-funcs.[ch]: removed the enums here,
include "paint-funcs-types.h".
* app/widgets/widgets-types.h: include "display/display-types.h"
* app/display/display-types.h: include "widgets/widgets-types.h".
* app/tools/tools-types.h: include "display/display-types.h"
* app/gui/gui-types.h: include "tools/tools-types.h".
The order of namespaces/dependencies should be (but is not):
(base, paint-funcs) -> (core, file, xcf, pdb) ->
(widgets, display) -> tools -> gui
* app/path.c: include "tools/tools-types.h".
* app/core/Makefile.am
* app/core/gimpimage-guides.[ch]
* app/core/gimpimage-merge.[ch]
* app/core/gimpimage-resize.[ch]
* app/core/gimpimage-scale.[ch]: new files.
* app/core/gimpimage.[ch]: removed the stuff which is in the new
files. Reordered all functions in both the .h and .c files,
commented the groups of functions.
* app/core/gimpcontainer.c: create the handler_id using a counter,
not the address of a pointer, because the address *may* be the
same twice, added debugging output.
* app/core/gimpviewable.[ch]: added primitive support for getting
a preview GdkPixbuf.
* app/nav_window.c
* app/undo.c
* app/undo_history.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage-mask.[ch]
* app/display/gimpdisplay.c
* app/display/gimpdisplayshell-callbacks.c
* app/display/gimpdisplayshell-dnd.c
* app/display/gimpdisplayshell-render.c
* app/display/gimpdisplayshell-scale.c
* app/display/gimpdisplayshell-scroll.c
* app/gui/image-commands.c
* app/gui/info-window.c
* app/gui/layers-commands.c
* app/gui/palette-import-dialog.c
* app/tools/gimpbycolorselecttool.c
* app/tools/gimpeditselectiontool.c
* app/tools/gimpmeasuretool.c
* app/tools/gimpmovetool.c
* app/widgets/gimpcontainerview-utils.c
* app/xcf/xcf-load.c: changed accordingly, some cleanup.
* tools/pdbgen/pdb/guides.pdb
* tools/pdbgen/pdb/image.pdb: changed accordingly, reordered functions.
* app/plug_in.c: set the labels of the "Repeat" and "Re-Show" menu
items to the name of the last plug-in (Fixes #50986).
* app/display/gimpdisplayshell.[ch]: set the labels of "Undo" and
"Redo" to the resp. undo names. Much simplified the WM icon stuff
by removing most code and using gimp_viewable_get_new_preview_pixbuf().
* app/widgets/gimpbrushfactoryview.c: forgot to assign the GQuark
returned by gimp_container_add_handler().
* app/pdb/guides_cmds.c
* app/pdb/image_cmds.c
* libgimp/gimpimage_pdb.[ch]: regenerated.
2001-11-29 01:51:06 +08:00
|
|
|
#include "core/gimpimage-guides.h"
|
2006-05-21 19:32:41 +08:00
|
|
|
#include "core/gimpimage-item-list.h"
|
2003-02-13 01:11:34 +08:00
|
|
|
#include "core/gimpimage-undo.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimplayer.h"
|
2004-01-12 22:13:24 +08:00
|
|
|
#include "core/gimplayermask.h"
|
2004-07-14 00:36:29 +08:00
|
|
|
#include "core/gimpprojection.h"
|
2003-10-06 20:17:11 +08:00
|
|
|
#include "core/gimpselection.h"
|
2003-03-19 00:42:45 +08:00
|
|
|
#include "core/gimpundostack.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
|
2011-10-07 03:59:07 +08:00
|
|
|
#include "widgets/gimpwidgets-utils.h"
|
|
|
|
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "display/gimpdisplay.h"
|
2001-11-01 05:20:09 +08:00
|
|
|
#include "display/gimpdisplayshell.h"
|
2003-03-20 19:31:33 +08:00
|
|
|
#include "display/gimpdisplayshell-appearance.h"
|
2001-11-11 07:03:22 +08:00
|
|
|
#include "display/gimpdisplayshell-selection.h"
|
2003-01-04 02:01:30 +08:00
|
|
|
#include "display/gimpdisplayshell-transform.h"
|
2001-11-01 05:20:09 +08:00
|
|
|
|
|
|
|
#include "gimpdrawtool.h"
|
2003-04-16 00:05:52 +08:00
|
|
|
#include "gimpeditselectiontool.h"
|
|
|
|
#include "gimptoolcontrol.h"
|
2018-12-10 21:22:50 +08:00
|
|
|
#include "gimptools-utils.h"
|
2001-11-01 05:20:09 +08:00
|
|
|
#include "tool_manager.h"
|
2001-09-26 07:23:09 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
#include "gimp-intl.h"
|
2000-12-29 23:22:01 +08:00
|
|
|
|
2000-10-23 17:05:45 +08:00
|
|
|
|
2011-12-11 06:15:03 +08:00
|
|
|
#define ARROW_VELOCITY 25
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2008-01-16 04:01:39 +08:00
|
|
|
|
2011-04-04 14:19:12 +08:00
|
|
|
typedef struct _GimpEditSelectionTool GimpEditSelectionTool;
|
|
|
|
typedef struct _GimpEditSelectionToolClass GimpEditSelectionToolClass;
|
|
|
|
|
|
|
|
struct _GimpEditSelectionTool
|
2008-07-05 16:51:03 +08:00
|
|
|
{
|
|
|
|
GimpDrawTool parent_instance;
|
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
gdouble start_x; /* Coords where button was pressed */
|
|
|
|
gdouble start_y;
|
|
|
|
|
|
|
|
gint last_x; /* Last x and y coords */
|
|
|
|
gint last_y;
|
|
|
|
|
|
|
|
gint current_x; /* Current x and y coords */
|
|
|
|
gint current_y;
|
|
|
|
|
|
|
|
gint cuml_x; /* Cumulative changes to x and y */
|
|
|
|
gint cuml_y;
|
|
|
|
|
|
|
|
gint sel_x; /* Bounding box of selection mask */
|
|
|
|
gint sel_y; /* Bounding box of selection mask */
|
|
|
|
gint sel_width;
|
|
|
|
gint sel_height;
|
|
|
|
|
2008-07-05 16:51:03 +08:00
|
|
|
gint num_segs_in; /* Num seg in selection boundary */
|
|
|
|
gint num_segs_out; /* Num seg in selection boundary */
|
2012-03-19 22:04:20 +08:00
|
|
|
GimpBoundSeg *segs_in; /* Pointer to the channel sel. segs */
|
|
|
|
GimpBoundSeg *segs_out; /* Pointer to the channel sel. segs */
|
2008-07-05 16:51:03 +08:00
|
|
|
|
2008-07-05 17:47:39 +08:00
|
|
|
gdouble center_x; /* Where to draw the mark of center */
|
|
|
|
gdouble center_y;
|
|
|
|
|
2008-07-05 16:51:03 +08:00
|
|
|
GimpTranslateMode edit_mode; /* Translate the mask or layer? */
|
|
|
|
|
2015-06-27 18:34:19 +08:00
|
|
|
GList *live_items; /* Items that are transformed live */
|
|
|
|
GList *delayed_items; /* Items that are transformed later */
|
|
|
|
|
2008-07-05 16:51:03 +08:00
|
|
|
gboolean first_move; /* Don't push undos after the first */
|
|
|
|
|
|
|
|
gboolean propagate_release;
|
|
|
|
|
|
|
|
gboolean constrain; /* Constrain the movement */
|
2016-10-23 23:49:47 +08:00
|
|
|
|
|
|
|
gdouble last_motion_x; /* Previous coords sent to _motion */
|
|
|
|
gdouble last_motion_y;
|
2011-04-04 14:19:12 +08:00
|
|
|
};
|
2008-07-05 16:51:03 +08:00
|
|
|
|
2011-04-04 14:19:12 +08:00
|
|
|
struct _GimpEditSelectionToolClass
|
2008-07-05 16:51:03 +08:00
|
|
|
{
|
|
|
|
GimpDrawToolClass parent_class;
|
2011-04-04 14:19:12 +08:00
|
|
|
};
|
2008-07-05 16:51:03 +08:00
|
|
|
|
|
|
|
|
2015-07-03 18:26:32 +08:00
|
|
|
static void gimp_edit_selection_tool_finalize (GObject *object);
|
|
|
|
|
2015-06-27 18:34:19 +08:00
|
|
|
static void gimp_edit_selection_tool_button_release (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonReleaseType release_type,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_edit_selection_tool_motion (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_edit_selection_tool_active_modifier_key (GimpTool *tool,
|
|
|
|
GdkModifierType key,
|
|
|
|
gboolean press,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_edit_selection_tool_draw (GimpDrawTool *tool);
|
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
static GList * gimp_edit_selection_tool_get_selected_items (GimpEditSelectionTool *edit_select,
|
2015-06-27 18:34:19 +08:00
|
|
|
GimpImage *image);
|
2015-07-04 01:37:30 +08:00
|
|
|
static void gimp_edit_selection_tool_calc_coords (GimpEditSelectionTool *edit_select,
|
2016-10-23 23:49:47 +08:00
|
|
|
GimpImage *image,
|
2015-07-04 01:37:30 +08:00
|
|
|
gdouble x,
|
|
|
|
gdouble y);
|
|
|
|
static void gimp_edit_selection_tool_start_undo_group (GimpEditSelectionTool *edit_select,
|
|
|
|
GimpImage *image);
|
2001-02-28 10:29:25 +08:00
|
|
|
|
|
|
|
|
2005-12-13 17:13:50 +08:00
|
|
|
G_DEFINE_TYPE (GimpEditSelectionTool, gimp_edit_selection_tool,
|
2006-05-15 17:46:31 +08:00
|
|
|
GIMP_TYPE_DRAW_TOOL)
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2005-12-13 17:13:50 +08:00
|
|
|
#define parent_class gimp_edit_selection_tool_parent_class
|
2001-02-28 10:29:25 +08:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_edit_selection_tool_class_init (GimpEditSelectionToolClass *klass)
|
|
|
|
{
|
2015-07-03 18:26:32 +08:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2008-01-16 04:01:39 +08:00
|
|
|
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
|
|
|
|
GimpDrawToolClass *draw_class = GIMP_DRAW_TOOL_CLASS (klass);
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2015-07-03 18:26:32 +08:00
|
|
|
object_class->finalize = gimp_edit_selection_tool_finalize;
|
|
|
|
|
2008-01-16 04:01:39 +08:00
|
|
|
tool_class->button_release = gimp_edit_selection_tool_button_release;
|
|
|
|
tool_class->motion = gimp_edit_selection_tool_motion;
|
|
|
|
tool_class->active_modifier_key = gimp_edit_selection_tool_active_modifier_key;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2008-01-16 04:01:39 +08:00
|
|
|
draw_class->draw = gimp_edit_selection_tool_draw;
|
2001-02-28 10:29:25 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
static void
|
2015-06-27 18:34:19 +08:00
|
|
|
gimp_edit_selection_tool_init (GimpEditSelectionTool *edit_select)
|
2001-02-28 10:29:25 +08:00
|
|
|
{
|
2017-10-29 23:38:24 +08:00
|
|
|
GimpTool *tool = GIMP_TOOL (edit_select);
|
|
|
|
|
2015-06-27 18:34:19 +08:00
|
|
|
edit_select->first_move = TRUE;
|
2017-10-29 23:38:24 +08:00
|
|
|
|
|
|
|
gimp_tool_control_set_active_modifiers (tool->control,
|
|
|
|
GIMP_TOOL_ACTIVE_MODIFIERS_SEPARATE);
|
2001-02-28 10:29:25 +08:00
|
|
|
}
|
|
|
|
|
2015-07-03 18:26:32 +08:00
|
|
|
static void
|
|
|
|
gimp_edit_selection_tool_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
GimpEditSelectionTool *edit_select = GIMP_EDIT_SELECTION_TOOL (object);
|
|
|
|
|
2019-05-27 23:47:55 +08:00
|
|
|
g_clear_pointer (&edit_select->segs_in, g_free);
|
|
|
|
edit_select->num_segs_in = 0;
|
|
|
|
|
|
|
|
g_clear_pointer (&edit_select->segs_out, g_free);
|
|
|
|
edit_select->num_segs_out = 0;
|
|
|
|
|
|
|
|
g_clear_pointer (&edit_select->live_items, g_list_free);
|
|
|
|
g_clear_pointer (&edit_select->delayed_items, g_list_free);
|
2015-07-03 18:26:32 +08:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2004-07-26 22:50:51 +08:00
|
|
|
gimp_edit_selection_tool_start (GimpTool *parent_tool,
|
2006-03-29 01:55:52 +08:00
|
|
|
GimpDisplay *display,
|
2008-11-01 23:17:36 +08:00
|
|
|
const GimpCoords *coords,
|
2004-10-07 05:04:13 +08:00
|
|
|
GimpTranslateMode edit_mode,
|
|
|
|
gboolean propagate_release)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-02-28 10:29:25 +08:00
|
|
|
GimpEditSelectionTool *edit_select;
|
2008-08-21 00:22:09 +08:00
|
|
|
GimpTool *tool;
|
2001-11-01 05:20:09 +08:00
|
|
|
GimpDisplayShell *shell;
|
2009-10-07 01:20:44 +08:00
|
|
|
GimpImage *image;
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *selected_items;
|
|
|
|
GList *iter;
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
GList *list;
|
2020-05-05 19:29:25 +08:00
|
|
|
gint off_x = G_MAXINT;
|
|
|
|
gint off_y = G_MAXINT;
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2008-04-14 14:28:43 +08:00
|
|
|
edit_select = g_object_new (GIMP_TYPE_EDIT_SELECTION_TOOL,
|
|
|
|
"tool-info", parent_tool->tool_info,
|
|
|
|
NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-10-07 05:04:13 +08:00
|
|
|
edit_select->propagate_release = propagate_release;
|
|
|
|
|
2008-08-21 00:22:09 +08:00
|
|
|
tool = GIMP_TOOL (edit_select);
|
|
|
|
|
2009-10-05 01:56:39 +08:00
|
|
|
shell = gimp_display_get_shell (display);
|
2009-10-07 01:20:44 +08:00
|
|
|
image = gimp_display_get_image (display);
|
2001-11-01 05:20:09 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Make a check to see if it should be a floating selection translation */
|
2006-08-16 05:15:49 +08:00
|
|
|
if ((edit_mode == GIMP_TRANSLATE_MODE_MASK_TO_LAYER ||
|
|
|
|
edit_mode == GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER) &&
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_image_get_floating_selection (image))
|
2001-02-28 10:29:25 +08:00
|
|
|
{
|
2004-07-26 22:50:51 +08:00
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_FLOATING_SEL;
|
2001-02-28 10:29:25 +08:00
|
|
|
}
|
1999-05-05 17:10:35 +08:00
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
if (edit_mode == GIMP_TRANSLATE_MODE_LAYER)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *layers = gimp_image_get_selected_layers (image);
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
if (layers && gimp_layer_is_floating_sel (layers->data))
|
2004-07-26 22:50:51 +08:00
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_FLOATING_SEL;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
edit_select->edit_mode = edit_mode;
|
2003-09-17 00:23:38 +08:00
|
|
|
|
2015-07-04 01:37:30 +08:00
|
|
|
gimp_edit_selection_tool_start_undo_group (edit_select, image);
|
2003-03-20 00:58:17 +08:00
|
|
|
|
2008-01-16 04:01:39 +08:00
|
|
|
/* Remember starting point for use in constrained movement */
|
|
|
|
edit_select->start_x = coords->x;
|
|
|
|
edit_select->start_y = coords->y;
|
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = gimp_edit_selection_tool_get_selected_items (edit_select, image);
|
|
|
|
g_return_if_fail (selected_items != NULL);
|
2003-03-20 00:58:17 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
for (iter = selected_items; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
gint item_off_x, item_off_y;
|
|
|
|
|
|
|
|
gimp_item_get_offset (iter->data, &item_off_x, &item_off_y);
|
|
|
|
off_x = MIN (off_x, item_off_x);
|
|
|
|
off_y = MIN (off_y, item_off_y);
|
|
|
|
}
|
2005-07-18 23:54:49 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
/* Manually set the last coords to the starting point */
|
|
|
|
edit_select->last_x = coords->x - off_x;
|
|
|
|
edit_select->last_y = coords->y - off_y;
|
2005-07-18 23:54:49 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->constrain = FALSE;
|
2003-04-13 19:43:47 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
/* Find the active item's selection bounds */
|
|
|
|
{
|
|
|
|
GimpChannel *channel;
|
|
|
|
const GimpBoundSeg *segs_in;
|
|
|
|
const GimpBoundSeg *segs_out;
|
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
if (GIMP_IS_CHANNEL (selected_items->data))
|
|
|
|
channel = GIMP_CHANNEL (selected_items->data);
|
2016-10-23 23:49:47 +08:00
|
|
|
else
|
|
|
|
channel = gimp_image_get_mask (image);
|
|
|
|
|
|
|
|
gimp_channel_boundary (channel,
|
|
|
|
&segs_in, &segs_out,
|
|
|
|
&edit_select->num_segs_in,
|
|
|
|
&edit_select->num_segs_out,
|
|
|
|
0, 0, 0, 0);
|
|
|
|
|
2021-08-26 23:18:32 +08:00
|
|
|
edit_select->segs_in = g_memdup2 (segs_in,
|
|
|
|
edit_select->num_segs_in *
|
2016-10-23 23:49:47 +08:00
|
|
|
sizeof (GimpBoundSeg));
|
|
|
|
|
2021-08-26 23:18:32 +08:00
|
|
|
edit_select->segs_out = g_memdup2 (segs_out,
|
|
|
|
edit_select->num_segs_out *
|
|
|
|
sizeof (GimpBoundSeg));
|
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_VECTORS)
|
|
|
|
{
|
|
|
|
edit_select->sel_x = 0;
|
|
|
|
edit_select->sel_y = 0;
|
|
|
|
edit_select->sel_width = gimp_image_get_width (image);
|
|
|
|
edit_select->sel_height = gimp_image_get_height (image);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* find the bounding box of the selection mask - this is used
|
|
|
|
* for the case of a GIMP_TRANSLATE_MODE_MASK_TO_LAYER, where
|
|
|
|
* the translation will result in floating the selection mask
|
|
|
|
* and translating the resulting layer
|
|
|
|
*/
|
2020-05-05 19:29:25 +08:00
|
|
|
gimp_item_mask_intersect (selected_items->data,
|
2016-10-23 23:49:47 +08:00
|
|
|
&edit_select->sel_x,
|
|
|
|
&edit_select->sel_y,
|
|
|
|
&edit_select->sel_width,
|
|
|
|
&edit_select->sel_height);
|
|
|
|
}
|
|
|
|
}
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
gimp_edit_selection_tool_calc_coords (edit_select, image,
|
|
|
|
coords->x, coords->y);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-04-17 10:57:33 +08:00
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
gint x = 0;
|
|
|
|
gint y = 0;
|
|
|
|
gint w = 0;
|
|
|
|
gint h = 0;
|
2003-04-17 10:57:33 +08:00
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
switch (edit_select->edit_mode)
|
2003-04-17 10:57:33 +08:00
|
|
|
{
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_CHANNEL:
|
2015-06-27 18:34:19 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_MASK:
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_LAYER_MASK:
|
2021-12-16 06:14:28 +08:00
|
|
|
edit_select->delayed_items = gimp_image_item_list_filter (g_list_copy (selected_items));
|
2020-05-26 19:08:14 +08:00
|
|
|
gimp_image_item_list_bounds (image, edit_select->delayed_items, &x, &y, &w, &h);
|
2015-07-02 09:04:39 +08:00
|
|
|
x += off_x;
|
|
|
|
y += off_y;
|
2020-05-26 19:08:14 +08:00
|
|
|
|
2004-01-12 22:13:24 +08:00
|
|
|
break;
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
|
2020-05-26 19:08:14 +08:00
|
|
|
/* MASK_TO_LAYER and MASK_COPY_TO_LAYER create a live_item later */
|
2016-10-23 23:49:47 +08:00
|
|
|
x = edit_select->sel_x + off_x;
|
|
|
|
y = edit_select->sel_y + off_y;
|
|
|
|
w = edit_select->sel_width;
|
|
|
|
h = edit_select->sel_height;
|
2003-04-17 10:57:33 +08:00
|
|
|
break;
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_FLOATING_SEL:
|
2015-07-03 00:59:11 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_VECTORS:
|
2021-12-16 06:14:28 +08:00
|
|
|
edit_select->live_items = gimp_image_item_list_filter (g_list_copy (selected_items));
|
2020-05-26 19:08:14 +08:00
|
|
|
gimp_image_item_list_bounds (image, edit_select->live_items, &x, &y, &w, &h);
|
|
|
|
break;
|
2003-04-17 10:57:33 +08:00
|
|
|
}
|
|
|
|
|
2008-08-21 00:22:09 +08:00
|
|
|
gimp_tool_control_set_snap_offsets (tool->control,
|
2015-07-02 09:04:39 +08:00
|
|
|
x - coords->x,
|
|
|
|
y - coords->y,
|
|
|
|
w, h);
|
2008-07-05 17:47:39 +08:00
|
|
|
|
|
|
|
/* Save where to draw the mark of the center */
|
2015-07-02 09:04:39 +08:00
|
|
|
edit_select->center_x = x + w / 2.0;
|
|
|
|
edit_select->center_y = y + h / 2.0;
|
2003-04-17 10:57:33 +08:00
|
|
|
}
|
|
|
|
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
for (list = edit_select->live_items; list; list = g_list_next (list))
|
2019-09-04 23:49:54 +08:00
|
|
|
{
|
|
|
|
GimpItem *item = list->data;
|
|
|
|
|
|
|
|
gimp_viewable_preview_freeze (GIMP_VIEWABLE (item));
|
|
|
|
|
|
|
|
gimp_item_start_transform (item, TRUE);
|
|
|
|
}
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
g_list_free (selected_items);
|
|
|
|
|
2011-04-07 02:33:23 +08:00
|
|
|
tool_manager_push_tool (display->gimp, tool);
|
|
|
|
|
2008-08-21 00:22:09 +08:00
|
|
|
gimp_tool_control_activate (tool->control);
|
|
|
|
tool->display = display;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* pause the current selection */
|
2010-10-09 20:26:33 +08:00
|
|
|
gimp_display_shell_selection_pause (shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-07-24 02:33:01 +08:00
|
|
|
/* initialize the statusbar display */
|
2008-08-21 00:22:09 +08:00
|
|
|
gimp_tool_push_status_coords (tool, display,
|
|
|
|
gimp_tool_control_get_precision (tool->control),
|
2007-01-21 09:24:51 +08:00
|
|
|
_("Move: "), 0, ", ", 0, NULL);
|
2002-02-03 20:10:23 +08:00
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
gimp_draw_tool_start (GIMP_DRAW_TOOL (edit_select), display);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-02-28 10:29:25 +08:00
|
|
|
static void
|
2007-02-28 02:55:12 +08:00
|
|
|
gimp_edit_selection_tool_button_release (GimpTool *tool,
|
2008-11-01 23:17:36 +08:00
|
|
|
const GimpCoords *coords,
|
2007-02-28 02:55:12 +08:00
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonReleaseType release_type,
|
|
|
|
GimpDisplay *display)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-07-26 21:15:22 +08:00
|
|
|
GimpEditSelectionTool *edit_select = GIMP_EDIT_SELECTION_TOOL (tool);
|
2009-10-05 01:56:39 +08:00
|
|
|
GimpDisplayShell *shell = gimp_display_get_shell (display);
|
2009-10-07 01:20:44 +08:00
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
GList *list;
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2002-02-05 19:35:03 +08:00
|
|
|
/* resume the current selection */
|
2010-10-09 20:26:33 +08:00
|
|
|
gimp_display_shell_selection_resume (shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
gimp_tool_pop_status (tool, display);
|
1998-07-24 02:33:01 +08:00
|
|
|
|
2011-03-30 18:08:38 +08:00
|
|
|
gimp_tool_control_halt (tool->control);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Stop and free the selection core */
|
2001-02-28 10:29:25 +08:00
|
|
|
gimp_draw_tool_stop (GIMP_DRAW_TOOL (edit_select));
|
|
|
|
|
2009-10-05 02:05:28 +08:00
|
|
|
tool_manager_pop_tool (display->gimp);
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2015-06-27 18:34:19 +08:00
|
|
|
/* move the items -- whether there has been movement or not!
|
|
|
|
* (to ensure that there's something on the undo stack)
|
1999-12-18 04:59:37 +08:00
|
|
|
*/
|
2015-06-27 18:34:19 +08:00
|
|
|
gimp_image_item_list_translate (image,
|
|
|
|
edit_select->delayed_items,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_x,
|
|
|
|
edit_select->cuml_y,
|
2015-06-27 18:34:19 +08:00
|
|
|
TRUE);
|
2001-02-28 10:29:25 +08:00
|
|
|
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
for (list = edit_select->live_items; list; list = g_list_next (list))
|
2019-09-04 23:49:54 +08:00
|
|
|
{
|
|
|
|
GimpItem *item = list->data;
|
|
|
|
|
|
|
|
gimp_item_end_transform (item, TRUE);
|
|
|
|
|
|
|
|
gimp_viewable_preview_thaw (GIMP_VIEWABLE (item));
|
|
|
|
}
|
app: add gimp_item_{start,end}_move()
Add gimp_item_{start,end}_move(), and corresponding
GimpItem::{start,end}_move() virtual functions, which should be
called before/after "moving" the item (i.e., translating, scaling,
resizing, flipping, rotating, or transforming the item). Moves
performed between the outermost pair of start/end calls are treated
atomically.
What exactly does "treated atomically" entail depends on the
subclasses -- GimpItem doesn't provide a default implementation for
these functions, so the current commit doesn't change any behavior.
The next commit, which adds layer-mask support for group layers,
uses the functions to avoid cropping the mask too early while a
child is moving.
GimpItem calls {start,end}_move() in the various "move" functions
(gimp_item_{translate,scale,...}(), before performing the actual
operation. Additionally we call the functions in the
gimp_image_item_list_foo() functions, for each participating item,
so that the items are moved as a unit. We call the functions in
the various gimp_image_remove_foo() functions, since removing an
item may affect the size of its ancestors, and is therefore akin to
moving. We also call the functions in GimpEditSelectionTool, so
that the move tool moves items atomically while dragging.
2018-02-05 23:59:28 +08:00
|
|
|
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_image_undo_group_end (image);
|
1999-03-21 23:38:11 +08:00
|
|
|
|
2007-02-28 02:55:12 +08:00
|
|
|
if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
|
1999-03-21 23:38:11 +08:00
|
|
|
{
|
|
|
|
/* Operation cancelled - undo the undo-group! */
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_image_undo (image);
|
1999-03-21 23:38:11 +08:00
|
|
|
}
|
|
|
|
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_image_flush (image);
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2004-10-07 05:04:13 +08:00
|
|
|
if (edit_select->propagate_release &&
|
2009-10-05 02:05:28 +08:00
|
|
|
tool_manager_get_active (display->gimp))
|
2004-10-07 05:04:13 +08:00
|
|
|
{
|
2009-10-05 02:05:28 +08:00
|
|
|
tool_manager_button_release_active (display->gimp,
|
2004-10-07 05:04:13 +08:00
|
|
|
coords, time, state,
|
2006-03-29 01:55:52 +08:00
|
|
|
display);
|
2004-10-07 05:04:13 +08:00
|
|
|
}
|
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_object_unref (edit_select);
|
2023-03-17 04:41:19 +08:00
|
|
|
|
|
|
|
shell->equidistance_side_horizontal = GIMP_ARRANGE_HFILL;
|
|
|
|
shell->equidistance_side_vertical = GIMP_ARRANGE_HFILL;
|
|
|
|
shell->snapped_side_horizontal = GIMP_ARRANGE_HFILL;
|
|
|
|
shell->snapped_side_vertical = GIMP_ARRANGE_HFILL;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-02-28 10:29:25 +08:00
|
|
|
static void
|
2008-01-22 02:55:37 +08:00
|
|
|
gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
|
|
|
|
gdouble new_x,
|
|
|
|
gdouble new_y,
|
|
|
|
GimpDisplay *display)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2018-05-08 06:54:02 +08:00
|
|
|
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (edit_select);
|
|
|
|
GimpTool *tool = GIMP_TOOL (edit_select);
|
|
|
|
GimpDisplayShell *shell = gimp_display_get_shell (display);
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
gint dx;
|
|
|
|
gint dy;
|
|
|
|
|
|
|
|
gdk_display_flush (gtk_widget_get_display (GTK_WIDGET (shell)));
|
1999-02-07 23:16:45 +08:00
|
|
|
|
2008-01-22 02:55:37 +08:00
|
|
|
gimp_draw_tool_pause (draw_tool);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2008-01-16 04:01:39 +08:00
|
|
|
if (edit_select->constrain)
|
|
|
|
{
|
2009-04-23 03:08:42 +08:00
|
|
|
gimp_constrain_line (edit_select->start_x, edit_select->start_y,
|
|
|
|
&new_x, &new_y,
|
2018-07-16 05:58:55 +08:00
|
|
|
GIMP_CONSTRAIN_LINE_45_DEGREES, 0.0, 1.0, 1.0);
|
2008-01-16 04:01:39 +08:00
|
|
|
}
|
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
gimp_edit_selection_tool_calc_coords (edit_select, image,
|
|
|
|
new_x, new_y);
|
2000-02-29 03:25:42 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
dx = edit_select->current_x - edit_select->last_x;
|
|
|
|
dy = edit_select->current_y - edit_select->last_y;
|
2003-09-03 18:19:47 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
/* if there has been movement, move */
|
|
|
|
if (dx != 0 || dy != 0)
|
2008-01-19 23:08:39 +08:00
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *selected_items;
|
|
|
|
GList *list;
|
|
|
|
GError *error = NULL;
|
1999-03-21 23:38:11 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = gimp_edit_selection_tool_get_selected_items (edit_select, image);
|
2003-07-10 06:40:27 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_x += dx;
|
|
|
|
edit_select->cuml_y += dy;
|
1999-03-21 23:38:11 +08:00
|
|
|
|
2008-01-19 23:08:39 +08:00
|
|
|
switch (edit_select->edit_mode)
|
|
|
|
{
|
|
|
|
case GIMP_TRANSLATE_MODE_LAYER_MASK:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK:
|
|
|
|
case GIMP_TRANSLATE_MODE_VECTORS:
|
|
|
|
case GIMP_TRANSLATE_MODE_CHANNEL:
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->last_x = edit_select->current_x;
|
|
|
|
edit_select->last_y = edit_select->current_y;
|
2008-01-19 23:08:39 +08:00
|
|
|
|
|
|
|
/* fallthru */
|
|
|
|
|
|
|
|
case GIMP_TRANSLATE_MODE_LAYER:
|
2015-06-27 18:34:19 +08:00
|
|
|
gimp_image_item_list_translate (image,
|
|
|
|
edit_select->live_items,
|
2016-10-23 23:49:47 +08:00
|
|
|
dx, dy,
|
2015-06-27 18:34:19 +08:00
|
|
|
edit_select->first_move);
|
2008-01-19 23:08:39 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
|
2009-10-07 01:20:44 +08:00
|
|
|
if (! gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
|
2020-05-18 05:00:07 +08:00
|
|
|
selected_items,
|
2009-10-05 02:05:28 +08:00
|
|
|
gimp_get_user_context (display->gimp),
|
2008-01-19 23:08:39 +08:00
|
|
|
edit_select->edit_mode ==
|
|
|
|
GIMP_TRANSLATE_MODE_MASK_TO_LAYER,
|
|
|
|
0, 0, &error))
|
|
|
|
{
|
|
|
|
/* no region to float, abort safely */
|
2009-10-05 02:05:28 +08:00
|
|
|
gimp_message_literal (display->gimp, G_OBJECT (display),
|
2013-09-15 00:59:20 +08:00
|
|
|
GIMP_MESSAGE_WARNING,
|
|
|
|
error->message);
|
2008-01-19 23:08:39 +08:00
|
|
|
g_clear_error (&error);
|
2008-01-22 02:55:37 +08:00
|
|
|
gimp_draw_tool_resume (draw_tool);
|
2008-01-19 23:08:39 +08:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
1999-04-25 04:58:55 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->last_x -= edit_select->sel_x;
|
|
|
|
edit_select->last_y -= edit_select->sel_y;
|
|
|
|
edit_select->sel_x = 0;
|
|
|
|
edit_select->sel_y = 0;
|
2000-02-10 22:23:11 +08:00
|
|
|
|
2008-01-19 23:08:39 +08:00
|
|
|
edit_select->edit_mode = GIMP_TRANSLATE_MODE_FLOATING_SEL;
|
2003-04-07 17:31:28 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
/* Selected items should have changed. */
|
|
|
|
edit_select->live_items = gimp_edit_selection_tool_get_selected_items (edit_select, image);
|
2003-09-17 00:23:38 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
for (list = edit_select->live_items; list; list = g_list_next (list))
|
|
|
|
{
|
|
|
|
GimpItem *item = list->data;
|
2015-06-27 18:34:19 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
gimp_viewable_preview_freeze (GIMP_VIEWABLE (item));
|
2019-10-02 23:33:27 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
gimp_item_start_transform (item, TRUE);
|
|
|
|
}
|
2018-02-12 18:03:53 +08:00
|
|
|
|
2015-06-27 18:34:19 +08:00
|
|
|
/* fallthru */
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2008-01-19 23:08:39 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_FLOATING_SEL:
|
2015-06-27 18:34:19 +08:00
|
|
|
gimp_image_item_list_translate (image,
|
|
|
|
edit_select->live_items,
|
2016-10-23 23:49:47 +08:00
|
|
|
dx, dy,
|
2015-06-27 18:34:19 +08:00
|
|
|
edit_select->first_move);
|
2008-01-19 23:08:39 +08:00
|
|
|
break;
|
|
|
|
}
|
2004-10-07 05:04:13 +08:00
|
|
|
|
2008-01-19 23:08:39 +08:00
|
|
|
edit_select->first_move = FALSE;
|
2020-05-05 19:29:25 +08:00
|
|
|
|
|
|
|
g_list_free (selected_items);
|
2008-01-19 23:08:39 +08:00
|
|
|
}
|
1999-03-21 23:38:11 +08:00
|
|
|
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_projection_flush (gimp_image_get_projection (image));
|
1999-02-07 23:16:45 +08:00
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
gimp_tool_pop_status (tool, display);
|
|
|
|
gimp_tool_push_status_coords (tool, display,
|
2008-08-21 00:22:09 +08:00
|
|
|
gimp_tool_control_get_precision (tool->control),
|
2002-02-03 20:10:23 +08:00
|
|
|
_("Move: "),
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_x,
|
2002-02-03 20:10:23 +08:00
|
|
|
", ",
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_y,
|
2007-01-21 09:24:51 +08:00
|
|
|
NULL);
|
1998-07-24 02:33:01 +08:00
|
|
|
|
2008-01-22 02:55:37 +08:00
|
|
|
gimp_draw_tool_resume (draw_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2008-11-01 23:17:36 +08:00
|
|
|
gimp_edit_selection_tool_motion (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display)
|
2008-01-22 02:55:37 +08:00
|
|
|
{
|
|
|
|
GimpEditSelectionTool *edit_select = GIMP_EDIT_SELECTION_TOOL (tool);
|
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->last_motion_x = coords->x;
|
|
|
|
edit_select->last_motion_y = coords->y;
|
2008-01-22 02:55:37 +08:00
|
|
|
|
|
|
|
gimp_edit_selection_tool_update_motion (edit_select,
|
|
|
|
coords->x, coords->y,
|
|
|
|
display);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2008-01-16 04:01:39 +08:00
|
|
|
static void
|
|
|
|
gimp_edit_selection_tool_active_modifier_key (GimpTool *tool,
|
|
|
|
GdkModifierType key,
|
|
|
|
gboolean press,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpEditSelectionTool *edit_select = GIMP_EDIT_SELECTION_TOOL (tool);
|
|
|
|
|
2011-10-07 03:59:07 +08:00
|
|
|
edit_select->constrain = (state & gimp_get_constrain_behavior_mask () ?
|
|
|
|
TRUE : FALSE);
|
2008-01-22 02:55:37 +08:00
|
|
|
|
|
|
|
/* If we didn't came here due to a mouse release, immediately update
|
|
|
|
* the position of the thing we move.
|
|
|
|
*/
|
|
|
|
if (state & GDK_BUTTON1_MASK)
|
|
|
|
{
|
|
|
|
gimp_edit_selection_tool_update_motion (edit_select,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->last_motion_x,
|
|
|
|
edit_select->last_motion_y,
|
2008-01-22 02:55:37 +08:00
|
|
|
display);
|
|
|
|
}
|
2008-01-16 04:01:39 +08:00
|
|
|
}
|
|
|
|
|
2001-02-28 10:29:25 +08:00
|
|
|
static void
|
|
|
|
gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2023-03-19 02:29:11 +08:00
|
|
|
GimpEditSelectionTool *edit_select = GIMP_EDIT_SELECTION_TOOL (draw_tool);
|
|
|
|
GimpDisplay *display = GIMP_TOOL (draw_tool)->display;
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
GimpDisplayShell *shell = gimp_display_get_shell (display);
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-26 02:55:21 +08:00
|
|
|
GimpUnit *unit = gimp_display_shell_get_unit (shell);
|
2023-04-03 11:43:10 +08:00
|
|
|
const gchar *abbreviation = gimp_unit_get_abbreviation (unit);
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *selected_items;
|
|
|
|
GList *iter;
|
2023-04-03 11:43:10 +08:00
|
|
|
gdouble xresolution, yresolution;
|
2023-03-19 02:29:11 +08:00
|
|
|
gint off_x = G_MAXINT;
|
|
|
|
gint off_y = G_MAXINT;
|
2001-02-28 10:29:25 +08:00
|
|
|
|
2023-04-03 11:43:10 +08:00
|
|
|
gimp_image_get_resolution (image, &xresolution, &yresolution);
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = gimp_edit_selection_tool_get_selected_items (edit_select, image);
|
|
|
|
g_return_if_fail (selected_items != NULL);
|
2003-09-17 00:23:38 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
for (iter = selected_items; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
gint item_off_x, item_off_y;
|
|
|
|
|
|
|
|
gimp_item_get_offset (iter->data, &item_off_x, &item_off_y);
|
|
|
|
off_x = MIN (off_x, item_off_x);
|
|
|
|
off_y = MIN (off_y, item_off_y);
|
|
|
|
}
|
2015-07-03 00:59:11 +08:00
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
switch (edit_select->edit_mode)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_CHANNEL:
|
|
|
|
case GIMP_TRANSLATE_MODE_LAYER_MASK:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK:
|
2003-05-09 21:05:37 +08:00
|
|
|
{
|
2004-01-12 22:13:24 +08:00
|
|
|
gboolean floating_sel = FALSE;
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_MASK)
|
2004-01-12 22:13:24 +08:00
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *layers = gimp_image_get_selected_layers (image);
|
2004-01-12 22:13:24 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
if (g_list_length (layers) == 1)
|
|
|
|
floating_sel = gimp_layer_is_floating_sel (layers->data);
|
2004-01-12 22:13:24 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-10-07 02:09:00 +08:00
|
|
|
if (! floating_sel && edit_select->segs_in)
|
|
|
|
{
|
2010-09-26 01:02:22 +08:00
|
|
|
gimp_draw_tool_add_boundary (draw_tool,
|
|
|
|
edit_select->segs_in,
|
|
|
|
edit_select->num_segs_in,
|
2010-10-10 04:00:19 +08:00
|
|
|
NULL,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_x + off_x,
|
|
|
|
edit_select->cuml_y + off_y);
|
2007-10-07 02:09:00 +08:00
|
|
|
}
|
2004-01-12 22:13:24 +08:00
|
|
|
|
|
|
|
if (edit_select->segs_out)
|
|
|
|
{
|
2010-09-26 01:02:22 +08:00
|
|
|
gimp_draw_tool_add_boundary (draw_tool,
|
|
|
|
edit_select->segs_out,
|
|
|
|
edit_select->num_segs_out,
|
2010-10-10 04:00:19 +08:00
|
|
|
NULL,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_x + off_x,
|
|
|
|
edit_select->cuml_y + off_y);
|
2004-01-12 22:13:24 +08:00
|
|
|
}
|
2004-07-26 22:50:51 +08:00
|
|
|
else if (edit_select->edit_mode != GIMP_TRANSLATE_MODE_MASK)
|
2004-01-12 22:13:24 +08:00
|
|
|
{
|
2010-09-26 01:02:22 +08:00
|
|
|
gimp_draw_tool_add_rectangle (draw_tool,
|
|
|
|
FALSE,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->cuml_x + off_x,
|
|
|
|
edit_select->cuml_y + off_y,
|
2020-05-05 19:29:25 +08:00
|
|
|
gimp_item_get_width (selected_items->data),
|
|
|
|
gimp_item_get_height (selected_items->data));
|
2004-01-12 22:13:24 +08:00
|
|
|
}
|
2003-05-09 21:05:37 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
|
2015-07-03 00:59:11 +08:00
|
|
|
gimp_draw_tool_add_rectangle (draw_tool,
|
|
|
|
FALSE,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->sel_x + off_x,
|
|
|
|
edit_select->sel_y + off_y,
|
|
|
|
edit_select->sel_width,
|
|
|
|
edit_select->sel_height);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_VECTORS:
|
2020-05-26 19:08:14 +08:00
|
|
|
{
|
2023-03-17 04:41:19 +08:00
|
|
|
GList *translate_items;
|
|
|
|
GimpAlignmentType snapped_side_horizontal = shell->snapped_side_horizontal;
|
|
|
|
GimpAlignmentType snapped_side_vertical = shell->snapped_side_vertical;
|
|
|
|
GimpAlignmentType equidistance_side_horizontal = shell->equidistance_side_horizontal;
|
|
|
|
GimpAlignmentType equidistance_side_vertical = shell->equidistance_side_vertical;
|
|
|
|
gint x, y, w, h;
|
2003-09-17 00:23:38 +08:00
|
|
|
|
2021-12-16 06:14:28 +08:00
|
|
|
translate_items = gimp_image_item_list_filter (g_list_copy (selected_items));
|
2020-05-26 19:08:14 +08:00
|
|
|
gimp_image_item_list_bounds (image, translate_items, &x, &y, &w, &h);
|
|
|
|
g_list_free (translate_items);
|
2003-09-17 00:23:38 +08:00
|
|
|
|
2020-05-26 19:08:14 +08:00
|
|
|
gimp_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h);
|
2023-03-17 04:41:19 +08:00
|
|
|
|
|
|
|
if (snapped_side_horizontal != GIMP_ARRANGE_HFILL)
|
|
|
|
{
|
|
|
|
GimpLayer *snapped_layer_horizontal = shell->snapped_layer_horizontal;
|
|
|
|
gint gx, gy, gw, gh;
|
|
|
|
|
|
|
|
gimp_item_bounds (GIMP_ITEM (snapped_layer_horizontal), &gx, &gy, &gw, &gh);
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (snapped_layer_horizontal), &gx, &gy);
|
|
|
|
|
|
|
|
switch (snapped_side_horizontal)
|
|
|
|
{
|
|
|
|
case GIMP_ALIGN_LEFT:
|
|
|
|
gimp_draw_tool_add_line (draw_tool, x, y+h/2, x, gy+gh/2);
|
|
|
|
break;
|
|
|
|
case GIMP_ALIGN_RIGHT:
|
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w, y+h/2, x+w, gy+gh/2);
|
|
|
|
break;
|
|
|
|
case GIMP_ALIGN_VCENTER:
|
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w/2, y+h/2, x+w/2, gy+gh/2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snapped_side_vertical != GIMP_ARRANGE_HFILL)
|
|
|
|
{
|
|
|
|
GimpLayer *snapped_layer_vertical = shell->snapped_layer_vertical;
|
|
|
|
gint gx, gy, gw, gh;
|
|
|
|
|
|
|
|
gimp_item_bounds (GIMP_ITEM (snapped_layer_vertical), &gx, &gy, &gw, &gh);
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (snapped_layer_vertical), &gx, &gy);
|
|
|
|
|
|
|
|
switch (snapped_side_vertical)
|
|
|
|
{
|
|
|
|
case GIMP_ALIGN_TOP:
|
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w/2, y, gx+gw/2, y);
|
|
|
|
break;
|
|
|
|
case GIMP_ALIGN_BOTTOM:
|
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w/2, y+h, gx+gw/2, y+h);
|
|
|
|
break;
|
|
|
|
case GIMP_ALIGN_HCENTER:
|
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w/2, y+h/2, gx+gw/2, y+h/2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (equidistance_side_horizontal != GIMP_ARRANGE_HFILL)
|
|
|
|
{
|
2023-03-19 02:29:11 +08:00
|
|
|
GimpLayer *near_layer1 = shell->near_layer_horizontal1;
|
|
|
|
GimpLayer *near_layer2 = shell->near_layer_horizontal2;
|
|
|
|
GtkStyleContext *style = gtk_widget_get_style_context (GTK_WIDGET (shell));
|
2023-04-03 11:43:10 +08:00
|
|
|
gdouble pixels_to_units;
|
2023-03-19 02:29:11 +08:00
|
|
|
gdouble font_size;
|
|
|
|
gint gx1 = 0;
|
|
|
|
gint gy1 = 0;
|
|
|
|
gint gw1 = 0;
|
|
|
|
gint gh1 = 0;
|
|
|
|
gint gx2 = 0;
|
|
|
|
gint gy2 = 0;
|
|
|
|
gint gw2 = 0;
|
|
|
|
gint gh2 = 0;
|
|
|
|
gint distance;
|
|
|
|
gchar distance_string[32];
|
|
|
|
|
|
|
|
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
|
|
|
"font-size", &font_size, NULL);
|
2023-03-17 04:41:19 +08:00
|
|
|
|
|
|
|
gimp_item_bounds (GIMP_ITEM (near_layer1), &gx1, &gy1, &gw1, &gh1);
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (near_layer1), &gx1, &gy1);
|
|
|
|
|
|
|
|
gimp_item_bounds (GIMP_ITEM (near_layer2), &gx2, &gy2, &gw2, &gh2);
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (near_layer2), &gx2, &gy2);
|
|
|
|
|
2023-03-19 02:29:11 +08:00
|
|
|
gimp_draw_tool_add_rectangle (draw_tool, FALSE, gx1, gy1, gw1, gh1);
|
|
|
|
gimp_draw_tool_add_rectangle (draw_tool, FALSE, gx2, gy2, gw2, gh2);
|
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
switch (equidistance_side_horizontal)
|
|
|
|
{
|
|
|
|
case GIMP_ALIGN_LEFT:
|
2023-03-19 02:29:11 +08:00
|
|
|
distance = x - (gx1+gw1);
|
2023-04-03 11:43:10 +08:00
|
|
|
pixels_to_units = gimp_pixels_to_units ((gdouble) distance, unit, xresolution);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
gimp_draw_tool_add_line (draw_tool, x, y+h/2, gx1+gw1, y+h/2);
|
|
|
|
gimp_draw_tool_add_line (draw_tool, gx1, gy1+gh1/2, gx2+gw2, gy1+gh1/2);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-04-03 11:43:10 +08:00
|
|
|
g_sprintf (distance_string, "%g %s", pixels_to_units, abbreviation);
|
2023-03-19 02:29:11 +08:00
|
|
|
gimp_draw_tool_add_text (draw_tool, x - distance/2, y+h/2, font_size, distance_string);
|
|
|
|
gimp_draw_tool_add_text (draw_tool, gx1 - distance/2, gy1+gh1/2, font_size, distance_string);
|
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_ALIGN_RIGHT:
|
2023-03-19 02:29:11 +08:00
|
|
|
distance = gx1 - (x+w);
|
2023-04-03 11:43:10 +08:00
|
|
|
pixels_to_units = gimp_pixels_to_units ((gdouble) distance, unit, xresolution);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w, y+h/2, gx1, y+h/2);
|
|
|
|
gimp_draw_tool_add_line (draw_tool, gx1+gw1, gy1+gh1/2, gx2, gy1+gh1/2);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-04-03 11:43:10 +08:00
|
|
|
g_sprintf (distance_string, "%g %s", pixels_to_units, abbreviation);
|
2023-03-19 02:29:11 +08:00
|
|
|
gimp_draw_tool_add_text (draw_tool, (x+w) + distance/2, y+h/2, font_size, distance_string);
|
|
|
|
gimp_draw_tool_add_text (draw_tool, (gx1+gw1) + distance/2, gy1+gh1/2, font_size, distance_string);
|
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (equidistance_side_vertical != GIMP_ARRANGE_HFILL)
|
|
|
|
{
|
2023-03-19 02:29:11 +08:00
|
|
|
GimpLayer *near_layer1 = shell->near_layer_vertical1;
|
|
|
|
GimpLayer *near_layer2 = shell->near_layer_vertical2;
|
|
|
|
GtkStyleContext *style = gtk_widget_get_style_context (GTK_WIDGET (shell));
|
2023-04-03 11:43:10 +08:00
|
|
|
gdouble pixels_to_units;
|
2023-03-19 02:29:11 +08:00
|
|
|
gdouble font_size;
|
|
|
|
gint gx1 = 0;
|
|
|
|
gint gy1 = 0;
|
|
|
|
gint gw1 = 0;
|
|
|
|
gint gh1 = 0;
|
|
|
|
gint gx2 = 0;
|
|
|
|
gint gy2 = 0;
|
|
|
|
gint gw2 = 0;
|
|
|
|
gint gh2 = 0;
|
|
|
|
gint distance;
|
|
|
|
gchar distance_string[32];
|
|
|
|
|
|
|
|
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
|
|
|
"font-size", &font_size, NULL);
|
2023-03-17 04:41:19 +08:00
|
|
|
|
|
|
|
gimp_item_bounds (GIMP_ITEM (near_layer1), &gx1, &gy1, &gw1, &gh1);
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (near_layer1), &gx1, &gy1);
|
|
|
|
|
|
|
|
gimp_item_bounds (GIMP_ITEM (near_layer2), &gx2, &gy2, &gw2, &gh2);
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (near_layer2), &gx2, &gy2);
|
|
|
|
|
2023-03-19 02:29:11 +08:00
|
|
|
gimp_draw_tool_add_rectangle (draw_tool, FALSE, gx1, gy1, gw1, gh1);
|
|
|
|
gimp_draw_tool_add_rectangle (draw_tool, FALSE, gx2, gy2, gw2, gh2);
|
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
switch (equidistance_side_vertical)
|
|
|
|
{
|
|
|
|
case GIMP_ALIGN_TOP:
|
2023-03-19 02:29:11 +08:00
|
|
|
distance = y - (gy1+gh1);
|
2023-04-03 11:43:10 +08:00
|
|
|
pixels_to_units = gimp_pixels_to_units ((gdouble) distance, unit, yresolution);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w/2, y, x+w/2, gy1+gh1);
|
|
|
|
gimp_draw_tool_add_line (draw_tool, gx1+gw1/2, gy1, gx1+gw1/2, gy2+gh2);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-04-03 11:43:10 +08:00
|
|
|
g_sprintf (distance_string, "%g %s", pixels_to_units, abbreviation);
|
2023-03-19 02:29:11 +08:00
|
|
|
gimp_draw_tool_add_text (draw_tool, x+w/2, y - distance/2, font_size, distance_string);
|
|
|
|
gimp_draw_tool_add_text (draw_tool, gx1+gw1/2, gy1 - distance/2, font_size, distance_string);
|
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_ALIGN_BOTTOM:
|
2023-03-19 02:29:11 +08:00
|
|
|
distance = gy1 - (y+h);
|
2023-04-03 11:43:10 +08:00
|
|
|
pixels_to_units = gimp_pixels_to_units ((gdouble) distance, unit, yresolution);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
gimp_draw_tool_add_line (draw_tool, x+w/2, y+h, x+w/2, gy1);
|
|
|
|
gimp_draw_tool_add_line (draw_tool, gx1+gw1/2, gy1+gh1, gx1+gw1/2, gy2);
|
2023-03-19 02:29:11 +08:00
|
|
|
|
2023-04-03 11:43:10 +08:00
|
|
|
g_sprintf (distance_string, "%g %s", pixels_to_units, abbreviation);
|
2023-03-19 02:29:11 +08:00
|
|
|
gimp_draw_tool_add_text (draw_tool, x+w/2, (y+h) + distance/2, font_size, distance_string);
|
|
|
|
gimp_draw_tool_add_text (draw_tool, gx1+gw1/2, (gy1+gh1) + distance/2, font_size, distance_string);
|
|
|
|
|
2023-03-17 04:41:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-05-26 19:08:14 +08:00
|
|
|
}
|
2003-09-17 00:23:38 +08:00
|
|
|
break;
|
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_FLOATING_SEL:
|
2017-12-07 21:38:22 +08:00
|
|
|
if (edit_select->segs_in)
|
|
|
|
{
|
|
|
|
gimp_draw_tool_add_boundary (draw_tool,
|
|
|
|
edit_select->segs_in,
|
|
|
|
edit_select->num_segs_in,
|
|
|
|
NULL,
|
|
|
|
edit_select->cuml_x,
|
|
|
|
edit_select->cuml_y);
|
|
|
|
}
|
1999-06-22 06:12:07 +08:00
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2003-09-12 02:02:39 +08:00
|
|
|
|
2008-07-05 17:47:39 +08:00
|
|
|
/* Mark the center because we snap to it */
|
2010-09-26 01:02:22 +08:00
|
|
|
gimp_draw_tool_add_handle (draw_tool,
|
|
|
|
GIMP_HANDLE_CROSS,
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->center_x + edit_select->cuml_x,
|
|
|
|
edit_select->center_y + edit_select->cuml_y,
|
2010-11-09 05:48:50 +08:00
|
|
|
GIMP_TOOL_HANDLE_SIZE_SMALL,
|
|
|
|
GIMP_TOOL_HANDLE_SIZE_SMALL,
|
2010-10-19 02:13:09 +08:00
|
|
|
GIMP_HANDLE_ANCHOR_CENTER);
|
2008-07-05 17:47:39 +08:00
|
|
|
|
2003-09-12 02:02:39 +08:00
|
|
|
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
|
2020-05-05 19:29:25 +08:00
|
|
|
|
|
|
|
g_list_free (selected_items);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
static GList *
|
|
|
|
gimp_edit_selection_tool_get_selected_items (GimpEditSelectionTool *edit_select,
|
|
|
|
GimpImage *image)
|
2008-01-18 05:41:21 +08:00
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *selected_items;
|
2008-01-18 05:41:21 +08:00
|
|
|
|
2015-06-27 18:34:19 +08:00
|
|
|
switch (edit_select->edit_mode)
|
|
|
|
{
|
|
|
|
case GIMP_TRANSLATE_MODE_VECTORS:
|
2024-07-11 08:07:44 +08:00
|
|
|
selected_items = g_list_copy (gimp_image_get_selected_paths (image));
|
2015-06-27 18:34:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TRANSLATE_MODE_LAYER:
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = g_list_copy (gimp_image_get_selected_layers (image));
|
2015-06-27 18:34:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK:
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = g_list_prepend (NULL, gimp_image_get_mask (image));
|
2015-06-27 18:34:19 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = gimp_image_get_selected_drawables (image);
|
2015-06-27 18:34:19 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-01-18 05:41:21 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
return selected_items;
|
2008-01-18 05:41:21 +08:00
|
|
|
}
|
|
|
|
|
2015-07-04 01:37:30 +08:00
|
|
|
static void
|
|
|
|
gimp_edit_selection_tool_calc_coords (GimpEditSelectionTool *edit_select,
|
2016-10-23 23:49:47 +08:00
|
|
|
GimpImage *image,
|
2015-07-04 01:37:30 +08:00
|
|
|
gdouble x,
|
|
|
|
gdouble y)
|
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *selected_items;
|
|
|
|
GList *iter;
|
|
|
|
gint off_x = G_MAXINT;
|
|
|
|
gint off_y = G_MAXINT;
|
2016-10-23 23:49:47 +08:00
|
|
|
gdouble x1, y1;
|
|
|
|
gdouble dx, dy;
|
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = gimp_edit_selection_tool_get_selected_items (edit_select, image);
|
|
|
|
g_return_if_fail (selected_items != NULL);
|
2016-10-23 23:49:47 +08:00
|
|
|
|
2020-05-05 19:29:25 +08:00
|
|
|
for (iter = selected_items; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
gint item_off_x, item_off_y;
|
|
|
|
|
|
|
|
gimp_item_get_offset (iter->data, &item_off_x, &item_off_y);
|
|
|
|
off_x = MIN (off_x, item_off_x);
|
|
|
|
off_y = MIN (off_y, item_off_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free (selected_items);
|
2015-07-04 01:37:30 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
dx = (x - off_x) - edit_select->last_x;
|
|
|
|
dy = (y - off_y) - edit_select->last_y;
|
2015-07-04 01:37:30 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
x1 = edit_select->sel_x + dx;
|
|
|
|
y1 = edit_select->sel_y + dy;
|
2015-07-04 01:37:30 +08:00
|
|
|
|
2016-10-23 23:49:47 +08:00
|
|
|
edit_select->current_x = ((gint) floor (x1) -
|
|
|
|
(edit_select->sel_x - edit_select->last_x));
|
|
|
|
edit_select->current_y = ((gint) floor (y1) -
|
|
|
|
(edit_select->sel_y - edit_select->last_y));
|
2015-07-04 01:37:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_edit_selection_tool_start_undo_group (GimpEditSelectionTool *edit_select,
|
|
|
|
GimpImage *image)
|
|
|
|
{
|
2020-05-05 19:29:25 +08:00
|
|
|
GList *selected_items;
|
2015-07-04 01:37:30 +08:00
|
|
|
const gchar *undo_desc = NULL;
|
|
|
|
|
|
|
|
switch (edit_select->edit_mode)
|
|
|
|
{
|
|
|
|
case GIMP_TRANSLATE_MODE_VECTORS:
|
|
|
|
case GIMP_TRANSLATE_MODE_CHANNEL:
|
|
|
|
case GIMP_TRANSLATE_MODE_LAYER_MASK:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK:
|
|
|
|
case GIMP_TRANSLATE_MODE_LAYER:
|
2020-05-05 19:29:25 +08:00
|
|
|
selected_items = gimp_edit_selection_tool_get_selected_items (edit_select, image);
|
|
|
|
undo_desc = GIMP_ITEM_GET_CLASS (selected_items->data)->translate_desc;
|
|
|
|
g_list_free (selected_items);
|
2015-07-04 01:37:30 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
|
|
|
|
case GIMP_TRANSLATE_MODE_FLOATING_SEL:
|
|
|
|
undo_desc = _("Move Floating Selection");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_return_if_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_undo_group_start (image,
|
|
|
|
edit_select->edit_mode ==
|
|
|
|
GIMP_TRANSLATE_MODE_MASK ?
|
|
|
|
GIMP_UNDO_GROUP_MASK :
|
|
|
|
GIMP_UNDO_GROUP_ITEM_DISPLACE,
|
|
|
|
undo_desc);
|
|
|
|
}
|
|
|
|
|
2007-03-07 17:34:47 +08:00
|
|
|
static gint
|
2003-07-10 06:40:27 +08:00
|
|
|
process_event_queue_keys (GdkEventKey *kevent,
|
2004-07-26 21:15:22 +08:00
|
|
|
... /* GdkKeyType, GdkModifierType, value ... 0 */)
|
1998-07-20 22:05:33 +08:00
|
|
|
{
|
2001-11-09 03:14:51 +08:00
|
|
|
|
1998-07-20 22:05:33 +08:00
|
|
|
#define FILTER_MAX_KEYS 50
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
va_list argp;
|
|
|
|
GdkEvent *event;
|
|
|
|
GList *event_list = NULL;
|
|
|
|
GList *list;
|
|
|
|
guint keys[FILTER_MAX_KEYS];
|
|
|
|
GdkModifierType modifiers[FILTER_MAX_KEYS];
|
|
|
|
gint values[FILTER_MAX_KEYS];
|
2003-03-19 00:42:45 +08:00
|
|
|
gint i = 0;
|
|
|
|
gint n_keys = 0;
|
|
|
|
gint value = 0;
|
|
|
|
gboolean done = FALSE;
|
2001-11-09 03:14:51 +08:00
|
|
|
GtkWidget *orig_widget;
|
1998-07-20 22:05:33 +08:00
|
|
|
|
2000-10-23 17:05:45 +08:00
|
|
|
va_start (argp, kevent);
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2004-07-07 06:58:33 +08:00
|
|
|
while (n_keys < FILTER_MAX_KEYS &&
|
|
|
|
(keys[n_keys] = va_arg (argp, guint)) != 0)
|
2000-10-23 17:05:45 +08:00
|
|
|
{
|
2003-03-19 00:42:45 +08:00
|
|
|
modifiers[n_keys] = va_arg (argp, GdkModifierType);
|
|
|
|
values[n_keys] = va_arg (argp, gint);
|
|
|
|
n_keys++;
|
2000-10-23 17:05:45 +08:00
|
|
|
}
|
2001-11-09 03:14:51 +08:00
|
|
|
|
|
|
|
va_end (argp);
|
1998-07-20 22:05:33 +08:00
|
|
|
|
2003-03-19 00:42:45 +08:00
|
|
|
for (i = 0; i < n_keys; i++)
|
|
|
|
if (kevent->keyval == keys[i] &&
|
|
|
|
(kevent->state & modifiers[i]) == modifiers[i])
|
|
|
|
value += values[i];
|
1998-07-20 22:05:33 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
orig_widget = gtk_get_event_widget ((GdkEvent *) kevent);
|
2000-10-23 17:05:45 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
while (gdk_events_pending () > 0 && ! done)
|
|
|
|
{
|
2003-03-19 00:42:45 +08:00
|
|
|
gboolean discard_event = FALSE;
|
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
event = gdk_event_get ();
|
2000-10-23 17:05:45 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
if (! event || orig_widget != gtk_get_event_widget (event))
|
|
|
|
{
|
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (event->any.type == GDK_KEY_PRESS)
|
|
|
|
{
|
2003-03-19 00:42:45 +08:00
|
|
|
for (i = 0; i < n_keys; i++)
|
|
|
|
if (event->key.keyval == keys[i] &&
|
|
|
|
(event->key.state & modifiers[i]) == modifiers[i])
|
2001-11-09 03:14:51 +08:00
|
|
|
{
|
|
|
|
discard_event = TRUE;
|
|
|
|
value += values[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! discard_event)
|
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
/* should there be more types here? */
|
|
|
|
else if (event->any.type != GDK_KEY_RELEASE &&
|
|
|
|
event->any.type != GDK_MOTION_NOTIFY &&
|
|
|
|
event->any.type != GDK_EXPOSE)
|
|
|
|
done = FALSE;
|
2003-03-19 00:42:45 +08:00
|
|
|
}
|
1998-07-20 22:05:33 +08:00
|
|
|
|
2003-03-19 00:42:45 +08:00
|
|
|
if (! event)
|
|
|
|
; /* Do nothing */
|
|
|
|
else if (! discard_event)
|
|
|
|
event_list = g_list_prepend (event_list, event);
|
|
|
|
else
|
|
|
|
gdk_event_free (event);
|
|
|
|
}
|
2000-10-23 17:05:45 +08:00
|
|
|
|
|
|
|
event_list = g_list_reverse (event_list);
|
|
|
|
|
|
|
|
/* unget the unused events and free the list */
|
2001-11-09 03:14:51 +08:00
|
|
|
for (list = event_list; list; list = g_list_next (list))
|
2000-10-23 17:05:45 +08:00
|
|
|
{
|
2001-11-09 03:14:51 +08:00
|
|
|
gdk_event_put ((GdkEvent *) list->data);
|
|
|
|
gdk_event_free ((GdkEvent *) list->data);
|
2000-10-23 17:05:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free (event_list);
|
|
|
|
|
1998-07-20 22:05:33 +08:00
|
|
|
return value;
|
2001-11-09 03:14:51 +08:00
|
|
|
|
1998-07-20 22:05:33 +08:00
|
|
|
#undef FILTER_MAX_KEYS
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-06-24 18:16:08 +08:00
|
|
|
gboolean
|
2004-06-13 02:41:52 +08:00
|
|
|
gimp_edit_selection_tool_key_press (GimpTool *tool,
|
2004-07-26 21:15:22 +08:00
|
|
|
GdkEventKey *kevent,
|
2006-03-29 01:55:52 +08:00
|
|
|
GimpDisplay *display)
|
2007-03-07 17:34:47 +08:00
|
|
|
{
|
|
|
|
GimpTransformType translate_type;
|
|
|
|
|
|
|
|
if (kevent->state & GDK_MOD1_MASK)
|
2015-10-17 21:31:08 +08:00
|
|
|
{
|
|
|
|
translate_type = GIMP_TRANSFORM_TYPE_SELECTION;
|
|
|
|
}
|
2011-10-07 03:59:07 +08:00
|
|
|
else if (kevent->state & gimp_get_toggle_behavior_mask ())
|
2015-10-17 21:31:08 +08:00
|
|
|
{
|
|
|
|
translate_type = GIMP_TRANSFORM_TYPE_PATH;
|
|
|
|
}
|
2007-03-07 17:34:47 +08:00
|
|
|
else
|
2015-10-17 21:31:08 +08:00
|
|
|
{
|
|
|
|
translate_type = GIMP_TRANSFORM_TYPE_LAYER;
|
|
|
|
}
|
2007-03-07 17:34:47 +08:00
|
|
|
|
|
|
|
return gimp_edit_selection_tool_translate (tool, kevent, translate_type,
|
2018-12-10 20:34:27 +08:00
|
|
|
display, NULL);
|
2007-03-07 17:34:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gimp_edit_selection_tool_translate (GimpTool *tool,
|
|
|
|
GdkEventKey *kevent,
|
|
|
|
GimpTransformType translate_type,
|
2018-12-10 20:34:27 +08:00
|
|
|
GimpDisplay *display,
|
2022-07-27 16:45:40 +08:00
|
|
|
GtkWidget **type_box)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2018-04-19 02:41:54 +08:00
|
|
|
gint inc_x = 0;
|
|
|
|
gint inc_y = 0;
|
2004-07-26 22:50:51 +08:00
|
|
|
GimpUndo *undo;
|
2018-04-19 02:41:54 +08:00
|
|
|
gboolean push_undo = TRUE;
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
2020-08-02 04:39:21 +08:00
|
|
|
GimpItem *active_item = NULL;
|
|
|
|
GList *selected_items = NULL;
|
2018-04-19 02:41:54 +08:00
|
|
|
GimpTranslateMode edit_mode = GIMP_TRANSLATE_MODE_MASK;
|
|
|
|
GimpUndoType undo_type = GIMP_UNDO_GROUP_MASK;
|
|
|
|
const gchar *undo_desc = NULL;
|
|
|
|
GdkModifierType extend_mask = gimp_get_extend_selection_mask ();
|
|
|
|
const gchar *null_message = NULL;
|
|
|
|
const gchar *locked_message = NULL;
|
2022-02-15 22:42:44 +08:00
|
|
|
GimpItem *locked_item = NULL;
|
2020-08-02 04:39:21 +08:00
|
|
|
GList *iter;
|
2004-07-26 22:50:51 +08:00
|
|
|
gint velocity;
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2004-07-07 06:58:33 +08:00
|
|
|
/* bail out early if it is not an arrow key event */
|
2004-06-13 03:29:50 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
if (kevent->keyval != GDK_KEY_Left &&
|
|
|
|
kevent->keyval != GDK_KEY_Right &&
|
|
|
|
kevent->keyval != GDK_KEY_Up &&
|
|
|
|
kevent->keyval != GDK_KEY_Down)
|
2004-06-24 18:16:08 +08:00
|
|
|
return FALSE;
|
2004-06-13 03:29:50 +08:00
|
|
|
|
2007-03-07 03:56:08 +08:00
|
|
|
/* adapt arrow velocity to the zoom factor when holding <shift> */
|
2005-09-26 01:03:03 +08:00
|
|
|
velocity = (ARROW_VELOCITY /
|
2009-10-05 01:56:39 +08:00
|
|
|
gimp_zoom_model_get_factor (gimp_display_get_shell (display)->zoom));
|
2005-09-26 01:03:03 +08:00
|
|
|
velocity = MAX (1.0, velocity);
|
2004-07-07 06:58:33 +08:00
|
|
|
|
2007-03-07 17:34:47 +08:00
|
|
|
/* check the event queue for key events with the same modifier mask
|
2015-10-17 21:31:08 +08:00
|
|
|
* as the current event, allowing only extend_mask to vary between
|
2007-03-07 17:34:47 +08:00
|
|
|
* them.
|
2003-03-19 00:42:45 +08:00
|
|
|
*/
|
2007-03-07 17:34:47 +08:00
|
|
|
inc_x = process_event_queue_keys (kevent,
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Left,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state | extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
-1 * velocity,
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Left,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state & ~extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
-1,
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Right,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state | extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
1 * velocity,
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Right,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state & ~extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
1,
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2007-03-07 17:34:47 +08:00
|
|
|
0);
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2007-03-07 17:34:47 +08:00
|
|
|
inc_y = process_event_queue_keys (kevent,
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Up,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state | extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
-1 * velocity,
|
2000-10-23 17:05:45 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Up,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state & ~extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
-1,
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Down,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state | extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
1 * velocity,
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2011-03-29 21:27:25 +08:00
|
|
|
GDK_KEY_Down,
|
2015-10-17 21:31:08 +08:00
|
|
|
kevent->state & ~extend_mask,
|
2007-03-07 17:34:47 +08:00
|
|
|
1,
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2007-03-07 17:34:47 +08:00
|
|
|
0);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
switch (translate_type)
|
2003-03-19 00:42:45 +08:00
|
|
|
{
|
2020-07-30 01:04:19 +08:00
|
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
2020-08-02 04:39:21 +08:00
|
|
|
active_item = GIMP_ITEM (gimp_image_get_mask (image));
|
2020-07-30 01:04:19 +08:00
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
if (gimp_channel_is_empty (GIMP_CHANNEL (active_item)))
|
|
|
|
active_item = NULL;
|
2020-07-30 01:04:19 +08:00
|
|
|
|
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_MASK;
|
|
|
|
undo_type = GIMP_UNDO_GROUP_MASK;
|
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
if (! active_item)
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
|
|
|
/* cannot happen, don't translate this message */
|
|
|
|
null_message = "There is no selection to move.";
|
|
|
|
}
|
2022-02-16 01:30:53 +08:00
|
|
|
else if (gimp_item_is_position_locked (active_item,
|
|
|
|
&locked_item))
|
2007-03-07 17:34:47 +08:00
|
|
|
{
|
2020-07-30 01:04:19 +08:00
|
|
|
/* cannot happen, don't translate this message */
|
|
|
|
locked_message = "The selection's position is locked.";
|
|
|
|
}
|
|
|
|
break;
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
2024-07-11 08:07:44 +08:00
|
|
|
selected_items = gimp_image_get_selected_paths (image);
|
2022-10-19 21:41:23 +08:00
|
|
|
selected_items = g_list_copy (selected_items);
|
2018-12-10 20:34:27 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_VECTORS;
|
|
|
|
undo_type = GIMP_UNDO_GROUP_ITEM_DISPLACE;
|
2018-04-19 02:41:54 +08:00
|
|
|
|
2022-10-19 21:41:23 +08:00
|
|
|
if (selected_items == NULL)
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
2022-10-19 21:41:23 +08:00
|
|
|
null_message = _("There are no paths to move.");
|
2020-07-30 01:04:19 +08:00
|
|
|
}
|
2022-10-19 21:41:23 +08:00
|
|
|
else
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
2022-10-19 21:41:23 +08:00
|
|
|
for (iter = selected_items; iter; iter = iter->next)
|
|
|
|
if (gimp_item_is_position_locked (iter->data, NULL))
|
|
|
|
{
|
|
|
|
locked_item = iter->data;
|
2022-10-19 21:47:11 +08:00
|
|
|
locked_message = _("A selected path's position is locked.");
|
2022-10-19 21:41:23 +08:00
|
|
|
break;
|
|
|
|
}
|
2020-07-30 01:04:19 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
2020-08-02 04:39:21 +08:00
|
|
|
selected_items = gimp_image_get_selected_drawables (image);
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
undo_type = GIMP_UNDO_GROUP_ITEM_DISPLACE;
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
if (! selected_items)
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
|
|
|
null_message = _("There is no layer to move.");
|
|
|
|
}
|
2020-08-02 04:39:21 +08:00
|
|
|
else if (GIMP_IS_LAYER_MASK (selected_items->data))
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_LAYER_MASK;
|
2018-04-19 02:41:54 +08:00
|
|
|
|
2022-02-16 01:30:53 +08:00
|
|
|
if (gimp_item_is_position_locked (selected_items->data,
|
|
|
|
&locked_item))
|
2018-04-19 02:41:54 +08:00
|
|
|
{
|
2022-02-16 01:30:53 +08:00
|
|
|
locked_message = _("The selected layer's position is locked.");
|
2018-04-19 02:41:54 +08:00
|
|
|
}
|
2022-02-15 22:42:44 +08:00
|
|
|
else if (gimp_item_is_content_locked (selected_items->data,
|
|
|
|
&locked_item))
|
2018-04-19 02:41:54 +08:00
|
|
|
{
|
2022-02-15 22:42:44 +08:00
|
|
|
locked_message = _("The selected layer's pixels are locked.");
|
2018-04-19 02:41:54 +08:00
|
|
|
}
|
2020-07-30 01:04:19 +08:00
|
|
|
}
|
2020-08-02 04:39:21 +08:00
|
|
|
else if (GIMP_IS_CHANNEL (selected_items->data))
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_CHANNEL;
|
2018-04-19 02:41:54 +08:00
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
for (iter = selected_items; iter; iter = iter->next)
|
2022-10-19 21:47:11 +08:00
|
|
|
if (gimp_item_is_position_locked (iter->data, NULL))
|
|
|
|
{
|
|
|
|
locked_item = iter->data;
|
|
|
|
locked_message = _("A selected channel's position is locked.");
|
|
|
|
break;
|
|
|
|
}
|
2020-07-30 01:04:19 +08:00
|
|
|
}
|
2020-08-02 04:39:21 +08:00
|
|
|
else if (gimp_layer_is_floating_sel (selected_items->data))
|
2020-07-30 01:04:19 +08:00
|
|
|
{
|
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_FLOATING_SEL;
|
|
|
|
|
2022-02-16 01:30:53 +08:00
|
|
|
if (gimp_item_is_position_locked (selected_items->data,
|
|
|
|
&locked_item))
|
2018-04-19 02:41:54 +08:00
|
|
|
{
|
2022-02-16 01:30:53 +08:00
|
|
|
locked_message = _("The selected layer's position is locked.");
|
2018-04-19 02:41:54 +08:00
|
|
|
}
|
2020-07-30 01:04:19 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
edit_mode = GIMP_TRANSLATE_MODE_LAYER;
|
2007-03-07 17:34:47 +08:00
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
for (iter = selected_items; iter; iter = iter->next)
|
2022-10-19 21:47:11 +08:00
|
|
|
if (gimp_item_is_position_locked (iter->data, NULL))
|
|
|
|
{
|
|
|
|
locked_item = iter->data;
|
|
|
|
locked_message = _("A selected layer's position is locked.");
|
|
|
|
break;
|
|
|
|
}
|
2020-07-30 01:04:19 +08:00
|
|
|
}
|
2018-04-19 02:41:54 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
break;
|
2019-08-11 03:57:55 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
case GIMP_TRANSFORM_TYPE_IMAGE:
|
|
|
|
g_return_val_if_reached (FALSE);
|
2003-03-19 00:42:45 +08:00
|
|
|
}
|
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
if (! active_item && ! selected_items)
|
2018-04-19 02:41:54 +08:00
|
|
|
{
|
|
|
|
gimp_tool_message_literal (tool, display, null_message);
|
2018-12-10 20:34:27 +08:00
|
|
|
if (type_box)
|
2022-07-27 16:45:40 +08:00
|
|
|
{
|
|
|
|
gimp_tools_show_tool_options (display->gimp);
|
|
|
|
if (*type_box)
|
|
|
|
gimp_widget_blink (*type_box);
|
|
|
|
}
|
2018-04-19 02:41:54 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (locked_message)
|
|
|
|
{
|
|
|
|
gimp_tool_message_literal (tool, display, locked_message);
|
2022-02-15 22:42:44 +08:00
|
|
|
|
|
|
|
if (locked_item == NULL)
|
|
|
|
locked_item = active_item ? active_item : selected_items->data;
|
|
|
|
|
|
|
|
gimp_tools_blink_lock_box (display->gimp, locked_item);
|
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
g_list_free (selected_items);
|
2018-04-19 02:41:54 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
2003-03-20 00:58:17 +08:00
|
|
|
|
2020-07-30 01:04:19 +08:00
|
|
|
if (inc_x == 0 && inc_y == 0)
|
2020-08-02 04:39:21 +08:00
|
|
|
{
|
|
|
|
g_list_free (selected_items);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else if (! selected_items)
|
|
|
|
{
|
|
|
|
selected_items = g_list_prepend (NULL, active_item);
|
|
|
|
}
|
2020-07-30 01:04:19 +08:00
|
|
|
|
2004-07-26 22:50:51 +08:00
|
|
|
switch (edit_mode)
|
2004-04-15 23:07:30 +08:00
|
|
|
{
|
2004-07-26 22:50:51 +08:00
|
|
|
case GIMP_TRANSLATE_MODE_FLOATING_SEL:
|
2004-09-22 20:46:35 +08:00
|
|
|
undo_desc = _("Move Floating Selection");
|
2004-04-15 23:07:30 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-08-02 04:39:21 +08:00
|
|
|
undo_desc = GIMP_ITEM_GET_CLASS (selected_items->data)->translate_desc;
|
2004-04-15 23:07:30 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-03-20 07:42:42 +08:00
|
|
|
/* compress undo */
|
2009-10-07 01:20:44 +08:00
|
|
|
undo = gimp_image_undo_can_compress (image, GIMP_TYPE_UNDO_STACK, undo_type);
|
2004-08-03 22:09:49 +08:00
|
|
|
|
2020-08-02 04:39:21 +08:00
|
|
|
if (undo &&
|
2004-08-03 22:09:49 +08:00
|
|
|
g_object_get_data (G_OBJECT (undo),
|
|
|
|
"edit-selection-tool") == (gpointer) tool &&
|
|
|
|
g_object_get_data (G_OBJECT (undo),
|
|
|
|
"edit-selection-type") == GINT_TO_POINTER (edit_mode))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2020-08-02 04:39:21 +08:00
|
|
|
GList *undo_items;
|
|
|
|
|
|
|
|
undo_items = g_object_get_data (G_OBJECT (undo), "edit-selection-items");
|
|
|
|
|
|
|
|
if (gimp_image_equal_selected_drawables (image, undo_items))
|
|
|
|
{
|
|
|
|
push_undo = FALSE;
|
|
|
|
}
|
2003-03-19 00:42:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (push_undo)
|
|
|
|
{
|
2009-10-07 01:20:44 +08:00
|
|
|
if (gimp_image_undo_group_start (image, undo_type, undo_desc))
|
2003-03-19 00:42:45 +08:00
|
|
|
{
|
2009-10-07 01:20:44 +08:00
|
|
|
undo = gimp_image_undo_can_compress (image,
|
2004-08-03 22:09:49 +08:00
|
|
|
GIMP_TYPE_UNDO_STACK,
|
|
|
|
undo_type);
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2004-08-03 22:09:49 +08:00
|
|
|
if (undo)
|
2003-03-19 00:42:45 +08:00
|
|
|
{
|
|
|
|
g_object_set_data (G_OBJECT (undo), "edit-selection-tool",
|
|
|
|
tool);
|
2020-08-02 04:39:21 +08:00
|
|
|
g_object_set_data_full (G_OBJECT (undo), "edit-selection-items",
|
|
|
|
g_list_copy (selected_items),
|
|
|
|
(GDestroyNotify) g_list_free);
|
2003-03-19 00:42:45 +08:00
|
|
|
g_object_set_data (G_OBJECT (undo), "edit-selection-type",
|
2004-07-26 22:50:51 +08:00
|
|
|
GINT_TO_POINTER (edit_mode));
|
2003-03-19 00:42:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-16 06:14:28 +08:00
|
|
|
gimp_image_item_list_translate (gimp_item_get_image (selected_items->data),
|
|
|
|
selected_items, inc_x, inc_y, push_undo);
|
2000-10-23 17:05:45 +08:00
|
|
|
|
2003-03-19 00:42:45 +08:00
|
|
|
if (push_undo)
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_image_undo_group_end (image);
|
2004-03-20 07:42:42 +08:00
|
|
|
else
|
2006-08-30 05:44:51 +08:00
|
|
|
gimp_undo_refresh_preview (undo,
|
2009-10-05 02:05:28 +08:00
|
|
|
gimp_get_user_context (display->gimp));
|
2003-03-19 00:42:45 +08:00
|
|
|
|
2009-10-07 01:20:44 +08:00
|
|
|
gimp_image_flush (image);
|
2020-08-02 04:39:21 +08:00
|
|
|
g_list_free (selected_items);
|
2004-06-24 18:16:08 +08:00
|
|
|
|
|
|
|
return TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|