mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-23 21:11:43 +00:00
30934d2395
2003-07-16 Michael Natterer <mitch@gimp.org> * app/tools/gimptransformtool.[ch]: implemented transforming of paths. Cleaned up initialize() and button_press() to activate the tool correctly. Use the transform tool's CREATING state *only* before the first mouse click (when there is no grid displayed). Preview the active path while transforming. Cache the transform direction in the GimpTransformTool struct so we can switch it while previewing the path. Lots of path transform related changes and cleanup.
1367 lines
44 KiB
C
1367 lines
44 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "tools-types.h"
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpchannel.h"
|
|
#include "core/gimpcontext.h"
|
|
#include "core/gimpdrawable-transform.h"
|
|
#include "core/gimpimage.h"
|
|
#include "core/gimpimage-mask.h"
|
|
#include "core/gimpimage-undo.h"
|
|
#include "core/gimpimage-undo-push.h"
|
|
#include "core/gimpitem-linked.h"
|
|
#include "core/gimplayer.h"
|
|
#include "core/gimptoolinfo.h"
|
|
|
|
#include "vectors/gimpvectors.h"
|
|
#include "vectors/gimpstroke.h"
|
|
|
|
#include "widgets/gimpdialogfactory.h"
|
|
#include "widgets/gimpviewabledialog.h"
|
|
|
|
#include "display/gimpdisplay.h"
|
|
#include "display/gimpprogress.h"
|
|
|
|
#ifdef __GNUC__
|
|
#warning FIXME #include "gui/gui-types.h"
|
|
#endif
|
|
#include "gui/gui-types.h"
|
|
#include "gui/info-dialog.h"
|
|
|
|
#include "gimptoolcontrol.h"
|
|
#include "gimptransformoptions.h"
|
|
#include "gimptransformtool.h"
|
|
#include "gimptransformtool-undo.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
#define HANDLE_SIZE 10
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void gimp_transform_tool_init (GimpTransformTool *tool);
|
|
static void gimp_transform_tool_class_init (GimpTransformToolClass *tool);
|
|
|
|
static void gimp_transform_tool_finalize (GObject *object);
|
|
|
|
static void gimp_transform_tool_initialize (GimpTool *tool,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_control (GimpTool *tool,
|
|
GimpToolAction action,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_button_press (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
guint32 time,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_button_release (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
guint32 time,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_motion (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
guint32 time,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_modifier_key (GimpTool *tool,
|
|
GdkModifierType key,
|
|
gboolean press,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_oper_update (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_cursor_update (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp);
|
|
|
|
static void gimp_transform_tool_draw (GimpDrawTool *draw_tool);
|
|
|
|
static TileManager *
|
|
gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
|
|
GimpItem *item,
|
|
GimpDisplay *gdisp);
|
|
|
|
static void gimp_transform_tool_halt (GimpTransformTool *tr_tool);
|
|
static void gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_dialog (GimpTransformTool *tr_tool);
|
|
static void gimp_transform_tool_prepare (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_recalc (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_doit (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp);
|
|
static void gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool);
|
|
|
|
static void transform_reset_callback (GtkWidget *widget,
|
|
GimpTransformTool *tr_tool);
|
|
static void transform_cancel_callback (GtkWidget *widget,
|
|
GimpTransformTool *tr_tool);
|
|
static void transform_ok_callback (GtkWidget *widget,
|
|
GimpTransformTool *tr_tool);
|
|
|
|
static void gimp_transform_tool_notify_type (GimpTransformOptions *options,
|
|
GParamSpec *pspec,
|
|
GimpTransformTool *tr_tool);
|
|
static void gimp_transform_tool_notify_grid (GimpTransformOptions *options,
|
|
GParamSpec *pspec,
|
|
GimpTransformTool *tr_tool);
|
|
|
|
|
|
static GimpDrawToolClass *parent_class = NULL;
|
|
|
|
|
|
GType
|
|
gimp_transform_tool_get_type (void)
|
|
{
|
|
static GType tool_type = 0;
|
|
|
|
if (! tool_type)
|
|
{
|
|
static const GTypeInfo tool_info =
|
|
{
|
|
sizeof (GimpTransformToolClass),
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
(GClassInitFunc) gimp_transform_tool_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (GimpTransformTool),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) gimp_transform_tool_init,
|
|
};
|
|
|
|
tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
|
|
"GimpTransformTool",
|
|
&tool_info, 0);
|
|
}
|
|
|
|
return tool_type;
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_class_init (GimpTransformToolClass *klass)
|
|
{
|
|
GObjectClass *object_class;
|
|
GimpToolClass *tool_class;
|
|
GimpDrawToolClass *draw_class;
|
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
|
tool_class = GIMP_TOOL_CLASS (klass);
|
|
draw_class = GIMP_DRAW_TOOL_CLASS (klass);
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
object_class->finalize = gimp_transform_tool_finalize;
|
|
|
|
tool_class->initialize = gimp_transform_tool_initialize;
|
|
tool_class->control = gimp_transform_tool_control;
|
|
tool_class->button_press = gimp_transform_tool_button_press;
|
|
tool_class->button_release = gimp_transform_tool_button_release;
|
|
tool_class->motion = gimp_transform_tool_motion;
|
|
tool_class->modifier_key = gimp_transform_tool_modifier_key;
|
|
tool_class->oper_update = gimp_transform_tool_oper_update;
|
|
tool_class->cursor_update = gimp_transform_tool_cursor_update;
|
|
|
|
draw_class->draw = gimp_transform_tool_draw;
|
|
|
|
klass->dialog = NULL;
|
|
klass->prepare = NULL;
|
|
klass->motion = NULL;
|
|
klass->recalc = NULL;
|
|
klass->transform = gimp_transform_tool_real_transform;
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_init (GimpTransformTool *tr_tool)
|
|
{
|
|
GimpTool *tool;
|
|
gint i;
|
|
|
|
tool = GIMP_TOOL (tr_tool);
|
|
|
|
gimp_tool_control_set_scroll_lock (tool->control, TRUE);
|
|
gimp_tool_control_set_preserve (tool->control, FALSE);
|
|
|
|
tr_tool->function = TRANSFORM_CREATING;
|
|
tr_tool->original = NULL;
|
|
|
|
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
|
{
|
|
tr_tool->trans_info[i] = 0.0;
|
|
tr_tool->old_trans_info[i] = 0.0;
|
|
}
|
|
|
|
gimp_matrix3_identity (&tr_tool->transform);
|
|
|
|
tr_tool->use_grid = TRUE;
|
|
tr_tool->use_center = TRUE;
|
|
tr_tool->ngx = 0;
|
|
tr_tool->ngy = 0;
|
|
tr_tool->grid_coords = NULL;
|
|
tr_tool->tgrid_coords = NULL;
|
|
|
|
tr_tool->notify_connected = FALSE;
|
|
tr_tool->type = GIMP_TRANSFORM_TYPE_LAYER;
|
|
tr_tool->direction = GIMP_TRANSFORM_FORWARD;
|
|
|
|
tr_tool->shell_desc = NULL;
|
|
tr_tool->progress_text = _("Transforming...");
|
|
tr_tool->info_dialog = NULL;
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_finalize (GObject *object)
|
|
{
|
|
GimpTransformTool *tr_tool;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (object);
|
|
|
|
if (tr_tool->original)
|
|
{
|
|
tile_manager_unref (tr_tool->original);
|
|
tr_tool->original = NULL;
|
|
}
|
|
|
|
if (tr_tool->info_dialog)
|
|
{
|
|
info_dialog_free (tr_tool->info_dialog);
|
|
tr_tool->info_dialog = NULL;
|
|
}
|
|
|
|
if (tr_tool->grid_coords)
|
|
{
|
|
g_free (tr_tool->grid_coords);
|
|
tr_tool->grid_coords = NULL;
|
|
}
|
|
|
|
if (tr_tool->tgrid_coords)
|
|
{
|
|
g_free (tr_tool->tgrid_coords);
|
|
tr_tool->tgrid_coords = NULL;
|
|
}
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_initialize (GimpTool *tool,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
if (gdisp != tool->gdisp)
|
|
{
|
|
GimpDrawable *drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
gint i;
|
|
|
|
if (GIMP_IS_LAYER (drawable) &&
|
|
gimp_layer_get_mask (GIMP_LAYER (drawable)))
|
|
{
|
|
g_message (_("Transformations do not work on\n"
|
|
"layers that contain layer masks."));
|
|
return;
|
|
}
|
|
|
|
/* Set the pointer to the active display */
|
|
tool->gdisp = gdisp;
|
|
tool->drawable = drawable;
|
|
|
|
/* Initialize the transform tool dialog */
|
|
if (! tr_tool->info_dialog)
|
|
gimp_transform_tool_dialog (tr_tool);
|
|
|
|
/* Find the transform bounds for some tools (like scale,
|
|
* perspective) that actually need the bounds for
|
|
* initializing
|
|
*/
|
|
gimp_transform_tool_bounds (tr_tool, gdisp);
|
|
|
|
gimp_transform_tool_prepare (tr_tool, gdisp);
|
|
|
|
/* Recalculate the transform tool */
|
|
gimp_transform_tool_recalc (tr_tool, gdisp);
|
|
|
|
if (tr_tool->use_grid && ! tr_tool->notify_connected)
|
|
{
|
|
tr_tool->type =
|
|
GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options)->type;
|
|
tr_tool->direction =
|
|
GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options)->direction;
|
|
|
|
g_signal_connect_object (tool->tool_info->tool_options,
|
|
"notify::type",
|
|
G_CALLBACK (gimp_transform_tool_notify_type),
|
|
tr_tool, 0);
|
|
g_signal_connect_object (tool->tool_info->tool_options,
|
|
"notify::direction",
|
|
G_CALLBACK (gimp_transform_tool_notify_type),
|
|
tr_tool, 0);
|
|
g_signal_connect_object (tool->tool_info->tool_options,
|
|
"notify::grid-type",
|
|
G_CALLBACK (gimp_transform_tool_notify_grid),
|
|
tr_tool, 0);
|
|
g_signal_connect_object (tool->tool_info->tool_options,
|
|
"notify::grid-size",
|
|
G_CALLBACK (gimp_transform_tool_notify_grid),
|
|
tr_tool, 0);
|
|
|
|
tr_tool->notify_connected = TRUE;
|
|
}
|
|
|
|
/* start drawing the bounding box and handles... */
|
|
gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), gdisp);
|
|
|
|
tr_tool->function = TRANSFORM_CREATING;
|
|
|
|
/* Save the current transformation info */
|
|
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
|
tr_tool->old_trans_info[i] = tr_tool->trans_info[i];
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_control (GimpTool *tool,
|
|
GimpToolAction action,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformTool *tr_tool;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
switch (action)
|
|
{
|
|
case PAUSE:
|
|
break;
|
|
|
|
case RESUME:
|
|
gimp_transform_tool_recalc (tr_tool, gdisp);
|
|
break;
|
|
|
|
case HALT:
|
|
gimp_transform_tool_halt (tr_tool);
|
|
return; /* don't upchain */
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_button_press (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
guint32 time,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformTool *tr_tool;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
if (tr_tool->function == TRANSFORM_CREATING && tr_tool->use_grid)
|
|
gimp_transform_tool_oper_update (tool, coords, state, gdisp);
|
|
|
|
tr_tool->lastx = tr_tool->startx = coords->x;
|
|
tr_tool->lasty = tr_tool->starty = coords->y;
|
|
|
|
gimp_tool_control_activate (tool->control);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_button_release (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
guint32 time,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformTool *tr_tool;
|
|
gint i;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
/* if we are creating, there is nothing to be done...exit */
|
|
if (tr_tool->function == TRANSFORM_CREATING && tr_tool->use_grid)
|
|
return;
|
|
|
|
/* if the 3rd button isn't pressed, transform the selected mask */
|
|
if (! (state & GDK_BUTTON3_MASK))
|
|
{
|
|
/* Shift-clicking is another way to approve the transform */
|
|
if ((state & GDK_SHIFT_MASK) || ! tr_tool->use_grid)
|
|
{
|
|
gimp_transform_tool_doit (tr_tool, gdisp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
|
|
|
|
/* Restore the previous transformation info */
|
|
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
|
tr_tool->trans_info[i] = tr_tool->old_trans_info[i];
|
|
|
|
/* recalculate the tool's transformation matrix */
|
|
gimp_transform_tool_recalc (tr_tool, gdisp);
|
|
|
|
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
|
|
}
|
|
|
|
gimp_tool_control_halt (tool->control);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_motion (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
guint32 time,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformToolClass *tr_tool_class;
|
|
GimpTransformTool *tr_tool;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
/* if we are creating, there is nothing to be done so exit. */
|
|
if (tr_tool->function == TRANSFORM_CREATING || ! tr_tool->use_grid)
|
|
return;
|
|
|
|
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
|
|
|
|
tr_tool->curx = coords->x;
|
|
tr_tool->cury = coords->y;
|
|
tr_tool->state = state;
|
|
|
|
/* recalculate the tool's transformation matrix */
|
|
tr_tool_class = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool);
|
|
|
|
if (tr_tool_class->motion)
|
|
{
|
|
tr_tool_class->motion (tr_tool, gdisp);
|
|
|
|
if (tr_tool_class->recalc)
|
|
tr_tool_class->recalc (tr_tool, gdisp);
|
|
}
|
|
|
|
tr_tool->lastx = tr_tool->curx;
|
|
tr_tool->lasty = tr_tool->cury;
|
|
|
|
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_modifier_key (GimpTool *tool,
|
|
GdkModifierType key,
|
|
gboolean press,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformOptions *options;
|
|
|
|
options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
|
|
|
|
if (key == GDK_CONTROL_MASK)
|
|
{
|
|
g_object_set (options,
|
|
"constrain-1", ! options->constrain_1,
|
|
NULL);
|
|
}
|
|
else if (key == GDK_MOD1_MASK)
|
|
{
|
|
g_object_set (options,
|
|
"constrain-2", ! options->constrain_2,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_oper_update (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformTool *tr_tool;
|
|
GimpDrawTool *draw_tool;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
draw_tool = GIMP_DRAW_TOOL (tool);
|
|
|
|
if (! tr_tool->use_grid)
|
|
return;
|
|
|
|
if (gdisp == tool->gdisp)
|
|
{
|
|
gdouble closest_dist;
|
|
gdouble dist;
|
|
|
|
closest_dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
|
|
coords->x, coords->y,
|
|
tr_tool->tx1, tr_tool->ty1);
|
|
tr_tool->function = TRANSFORM_HANDLE_1;
|
|
|
|
dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
|
|
coords->x, coords->y,
|
|
tr_tool->tx2, tr_tool->ty2);
|
|
if (dist < closest_dist)
|
|
{
|
|
closest_dist = dist;
|
|
tr_tool->function = TRANSFORM_HANDLE_2;
|
|
}
|
|
|
|
dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
|
|
coords->x, coords->y,
|
|
tr_tool->tx3, tr_tool->ty3);
|
|
if (dist < closest_dist)
|
|
{
|
|
closest_dist = dist;
|
|
tr_tool->function = TRANSFORM_HANDLE_3;
|
|
}
|
|
|
|
dist = gimp_draw_tool_calc_distance (draw_tool, gdisp,
|
|
coords->x, coords->y,
|
|
tr_tool->tx4, tr_tool->ty4);
|
|
if (dist < closest_dist)
|
|
{
|
|
closest_dist = dist;
|
|
tr_tool->function = TRANSFORM_HANDLE_4;
|
|
}
|
|
|
|
if (gimp_draw_tool_on_handle (draw_tool, gdisp,
|
|
coords->x, coords->y,
|
|
GIMP_HANDLE_CIRCLE,
|
|
tr_tool->tcx, tr_tool->tcy,
|
|
HANDLE_SIZE, HANDLE_SIZE,
|
|
GTK_ANCHOR_CENTER,
|
|
FALSE))
|
|
{
|
|
tr_tool->function = TRANSFORM_HANDLE_CENTER;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_cursor_update (GimpTool *tool,
|
|
GimpCoords *coords,
|
|
GdkModifierType state,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformTool *tr_tool;
|
|
GimpTransformOptions *options;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
|
|
|
|
if (tr_tool->use_grid)
|
|
{
|
|
GdkCursorType ctype = GDK_TOP_LEFT_ARROW;
|
|
GimpCursorModifier cmodifier = GIMP_CURSOR_MODIFIER_NONE;
|
|
|
|
switch (options->type)
|
|
{
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
|
{
|
|
GimpDrawable *drawable;
|
|
|
|
drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
if (drawable)
|
|
{
|
|
if (GIMP_IS_LAYER (drawable) &&
|
|
gimp_layer_get_mask (GIMP_LAYER (drawable)))
|
|
{
|
|
ctype = GIMP_BAD_CURSOR;
|
|
}
|
|
else if (gimp_display_coords_in_active_drawable (gdisp, coords))
|
|
{
|
|
if (gimp_image_mask_is_empty (gdisp->gimage) ||
|
|
gimp_image_mask_value (gdisp->gimage,
|
|
coords->x, coords->y))
|
|
{
|
|
ctype = GIMP_MOUSE_CURSOR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
|
if (gimp_image_mask_is_empty (gdisp->gimage) ||
|
|
gimp_image_mask_value (gdisp->gimage, coords->x, coords->y))
|
|
{
|
|
ctype = GIMP_MOUSE_CURSOR;
|
|
}
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
|
if (gimp_image_get_active_vectors (gdisp->gimage))
|
|
ctype = GIMP_MOUSE_CURSOR;
|
|
else
|
|
ctype = GIMP_BAD_CURSOR;
|
|
break;
|
|
}
|
|
|
|
if (tr_tool->use_center && tr_tool->function == TRANSFORM_HANDLE_CENTER)
|
|
{
|
|
cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
|
|
}
|
|
|
|
gimp_tool_control_set_cursor (tool->control, ctype);
|
|
gimp_tool_control_set_cursor_modifier (tool->control, cmodifier);
|
|
}
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, gdisp);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_draw (GimpDrawTool *draw_tool)
|
|
{
|
|
GimpTool *tool;
|
|
GimpTransformTool *tr_tool;
|
|
GimpTransformOptions *options;
|
|
|
|
tr_tool = GIMP_TRANSFORM_TOOL (draw_tool);
|
|
|
|
if (! tr_tool->use_grid)
|
|
return;
|
|
|
|
tool = GIMP_TOOL (draw_tool);
|
|
options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
|
|
|
|
/* draw the bounding box */
|
|
gimp_draw_tool_draw_line (draw_tool,
|
|
tr_tool->tx1, tr_tool->ty1,
|
|
tr_tool->tx2, tr_tool->ty2,
|
|
FALSE);
|
|
gimp_draw_tool_draw_line (draw_tool,
|
|
tr_tool->tx2, tr_tool->ty2,
|
|
tr_tool->tx4, tr_tool->ty4,
|
|
FALSE);
|
|
gimp_draw_tool_draw_line (draw_tool,
|
|
tr_tool->tx3, tr_tool->ty3,
|
|
tr_tool->tx4, tr_tool->ty4,
|
|
FALSE);
|
|
gimp_draw_tool_draw_line (draw_tool,
|
|
tr_tool->tx3, tr_tool->ty3,
|
|
tr_tool->tx1, tr_tool->ty1,
|
|
FALSE);
|
|
|
|
/* Draw the grid (not for path transform since it looks ugly) */
|
|
|
|
if (tr_tool->type != GIMP_TRANSFORM_TYPE_PATH &&
|
|
tr_tool->grid_coords &&
|
|
tr_tool->tgrid_coords &&
|
|
tr_tool->transform.coeff[0][0] >= 0.0 &&
|
|
tr_tool->transform.coeff[1][1] >= 0.0 &&
|
|
tr_tool->transform.coeff[1][0] >= -1.0 &&
|
|
tr_tool->transform.coeff[0][1] >= -1.0)
|
|
{
|
|
gint gci, i, k;
|
|
|
|
k = tr_tool->ngx + tr_tool->ngy;
|
|
|
|
for (i = 0, gci = 0; i < k; i++, gci += 4)
|
|
{
|
|
gimp_draw_tool_draw_line (draw_tool,
|
|
tr_tool->tgrid_coords[gci],
|
|
tr_tool->tgrid_coords[gci + 1],
|
|
tr_tool->tgrid_coords[gci + 2],
|
|
tr_tool->tgrid_coords[gci + 3],
|
|
FALSE);
|
|
}
|
|
}
|
|
|
|
/* draw the tool handles */
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
GIMP_HANDLE_SQUARE,
|
|
tr_tool->tx1, tr_tool->ty1,
|
|
HANDLE_SIZE, HANDLE_SIZE,
|
|
GTK_ANCHOR_CENTER,
|
|
FALSE);
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
GIMP_HANDLE_SQUARE,
|
|
tr_tool->tx2, tr_tool->ty2,
|
|
HANDLE_SIZE, HANDLE_SIZE,
|
|
GTK_ANCHOR_CENTER,
|
|
FALSE);
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
GIMP_HANDLE_SQUARE,
|
|
tr_tool->tx3, tr_tool->ty3,
|
|
HANDLE_SIZE, HANDLE_SIZE,
|
|
GTK_ANCHOR_CENTER,
|
|
FALSE);
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
GIMP_HANDLE_SQUARE,
|
|
tr_tool->tx4, tr_tool->ty4,
|
|
HANDLE_SIZE, HANDLE_SIZE,
|
|
GTK_ANCHOR_CENTER,
|
|
FALSE);
|
|
|
|
/* draw the center */
|
|
if (tr_tool->use_center)
|
|
{
|
|
gimp_draw_tool_draw_handle (draw_tool,
|
|
GIMP_HANDLE_FILLED_CIRCLE,
|
|
tr_tool->tcx, tr_tool->tcy,
|
|
HANDLE_SIZE, HANDLE_SIZE,
|
|
GTK_ANCHOR_CENTER,
|
|
FALSE);
|
|
}
|
|
|
|
if (tr_tool->type == GIMP_TRANSFORM_TYPE_PATH)
|
|
{
|
|
GimpVectors *vectors;
|
|
GimpStroke *stroke = NULL;
|
|
GimpMatrix3 matrix = tr_tool->transform;
|
|
|
|
vectors = gimp_image_get_active_vectors (tool->gdisp->gimage);
|
|
|
|
if (vectors)
|
|
{
|
|
if (tr_tool->direction == GIMP_TRANSFORM_BACKWARD)
|
|
gimp_matrix3_invert (&matrix);
|
|
|
|
while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
|
|
{
|
|
GArray *coords;
|
|
gboolean closed;
|
|
gint i;
|
|
|
|
coords = gimp_stroke_interpolate (stroke, 1.0, &closed);
|
|
|
|
for (i = 0; i < coords->len; i++)
|
|
{
|
|
GimpCoords *curr = &g_array_index (coords, GimpCoords, i);
|
|
|
|
gimp_matrix3_transform_point (&matrix,
|
|
curr->x, curr->y,
|
|
&curr->x, &curr->y);
|
|
}
|
|
|
|
if (coords->len)
|
|
gimp_draw_tool_draw_strokes (draw_tool,
|
|
&g_array_index (coords,
|
|
GimpCoords, 0),
|
|
coords->len, FALSE, FALSE);
|
|
|
|
g_array_free (coords, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static TileManager *
|
|
gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
|
|
GimpItem *active_item,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTool *tool;
|
|
GimpTransformOptions *options;
|
|
GimpProgress *progress;
|
|
TileManager *ret = NULL;
|
|
|
|
tool = GIMP_TOOL (tr_tool);
|
|
options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
|
|
|
|
if (tr_tool->info_dialog)
|
|
gtk_widget_set_sensitive (GTK_WIDGET (tr_tool->info_dialog->shell), FALSE);
|
|
|
|
progress = gimp_progress_start (gdisp, tr_tool->progress_text, FALSE,
|
|
NULL, NULL);
|
|
|
|
if (gimp_item_get_linked (active_item))
|
|
gimp_item_linked_transform (active_item, &tr_tool->transform,
|
|
options->direction,
|
|
options->interpolation, options->clip,
|
|
progress ?
|
|
gimp_progress_update_and_flush : NULL,
|
|
progress);
|
|
|
|
switch (options->type)
|
|
{
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
|
{
|
|
gboolean clip_result = options->clip;
|
|
|
|
/* always clip the selction and unfloated channels
|
|
* so they keep their size
|
|
*/
|
|
if (GIMP_IS_CHANNEL (active_item) &&
|
|
tile_manager_bpp (tr_tool->original) == 1)
|
|
clip_result = TRUE;
|
|
|
|
ret =
|
|
gimp_drawable_transform_tiles_affine (GIMP_DRAWABLE (active_item),
|
|
tr_tool->original,
|
|
&tr_tool->transform,
|
|
options->direction,
|
|
options->interpolation,
|
|
clip_result,
|
|
progress ?
|
|
gimp_progress_update_and_flush :
|
|
NULL,
|
|
progress);
|
|
}
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
|
gimp_item_transform (active_item,
|
|
&tr_tool->transform,
|
|
options->direction,
|
|
options->interpolation,
|
|
options->clip,
|
|
progress ?
|
|
gimp_progress_update_and_flush :
|
|
NULL,
|
|
progress);
|
|
break;
|
|
}
|
|
|
|
if (progress)
|
|
gimp_progress_end (progress);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_doit (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTool *tool;
|
|
GimpTransformOptions *options;
|
|
GimpItem *active_item = NULL;
|
|
TileManager *new_tiles;
|
|
gboolean new_layer;
|
|
|
|
tool = GIMP_TOOL (tr_tool);
|
|
options = GIMP_TRANSFORM_OPTIONS (tool->tool_info->tool_options);
|
|
|
|
switch (options->type)
|
|
{
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
|
active_item = (GimpItem *) gimp_image_active_drawable (gdisp->gimage);
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
|
active_item = (GimpItem *) gimp_image_get_mask (gdisp->gimage);
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
|
active_item = (GimpItem *) gimp_image_get_active_vectors (gdisp->gimage);
|
|
break;
|
|
}
|
|
|
|
if (! active_item)
|
|
return;
|
|
|
|
gimp_set_busy (gdisp->gimage->gimp);
|
|
|
|
/* undraw the tool before we muck around with the transform matrix */
|
|
gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
|
|
|
|
/* We're going to dirty this image, but we want to keep the tool around */
|
|
gimp_tool_control_set_preserve (tool->control, TRUE);
|
|
|
|
/* Start a transform undo group */
|
|
gimp_image_undo_group_start (gdisp->gimage, GIMP_UNDO_GROUP_TRANSFORM,
|
|
tool->tool_info->blurb);
|
|
|
|
/* With the old UI, if original is NULL, then this is the
|
|
* first transformation. In the new UI, it is always so, right?
|
|
*/
|
|
g_assert (tr_tool->original == NULL);
|
|
|
|
/* Copy the current selection to the transform tool's private
|
|
* selection pointer, so that the original source can be repeatedly
|
|
* modified.
|
|
*/
|
|
tool->drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
switch (options->type)
|
|
{
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
|
tr_tool->original = gimp_drawable_transform_cut (tool->drawable,
|
|
&new_layer);
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
|
tr_tool->original = tile_manager_ref (GIMP_DRAWABLE (active_item)->tiles);
|
|
tile_manager_set_offsets (tr_tool->original, 0, 0);
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
|
tr_tool->original = NULL;
|
|
break;
|
|
}
|
|
|
|
/* Send the request for the transformation to the tool...
|
|
*/
|
|
new_tiles = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->transform (tr_tool,
|
|
active_item,
|
|
gdisp);
|
|
|
|
gimp_transform_tool_prepare (tr_tool, gdisp);
|
|
gimp_transform_tool_recalc (tr_tool, gdisp);
|
|
|
|
switch (options->type)
|
|
{
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
|
if (new_tiles)
|
|
{
|
|
/* paste the new transformed image to the gimage...also implement
|
|
* undo...
|
|
*/
|
|
/* FIXME: we should check if the drawable is still valid */
|
|
gimp_drawable_transform_paste (tool->drawable,
|
|
new_tiles,
|
|
new_layer);
|
|
tile_manager_unref (new_tiles);
|
|
}
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
|
if (new_tiles)
|
|
{
|
|
gimp_image_mask_push_undo (gdisp->gimage, NULL);
|
|
|
|
tile_manager_unref (GIMP_DRAWABLE (active_item)->tiles);
|
|
GIMP_DRAWABLE (active_item)->tiles = new_tiles;
|
|
|
|
GIMP_CHANNEL (active_item)->bounds_known = FALSE;
|
|
|
|
gimp_image_mask_changed (gdisp->gimage);
|
|
}
|
|
|
|
tile_manager_unref (tr_tool->original);
|
|
tr_tool->original = NULL;
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
|
/* Nothing to be done */
|
|
break;
|
|
}
|
|
|
|
/* Make a note of the new current drawable (since we may have
|
|
* a floating selection, etc now.
|
|
*/
|
|
tool->drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
gimp_transform_tool_push_undo (gdisp->gimage, NULL,
|
|
tool->ID,
|
|
G_TYPE_FROM_INSTANCE (tool),
|
|
tr_tool->old_trans_info,
|
|
NULL);
|
|
|
|
/* push the undo group end */
|
|
gimp_image_undo_group_end (gdisp->gimage);
|
|
|
|
/* We're done dirtying the image, and would like to be restarted
|
|
* if the image gets dirty while the tool exists
|
|
*/
|
|
gimp_tool_control_set_preserve (tool->control, FALSE);
|
|
|
|
gimp_unset_busy (gdisp->gimage->gimp);
|
|
|
|
gimp_image_flush (gdisp->gimage);
|
|
|
|
gimp_transform_tool_halt (tr_tool);
|
|
}
|
|
|
|
void
|
|
gimp_transform_tool_transform_bounding_box (GimpTransformTool *tr_tool)
|
|
{
|
|
g_return_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool));
|
|
|
|
gimp_matrix3_transform_point (&tr_tool->transform,
|
|
tr_tool->x1, tr_tool->y1,
|
|
&tr_tool->tx1, &tr_tool->ty1);
|
|
gimp_matrix3_transform_point (&tr_tool->transform,
|
|
tr_tool->x2, tr_tool->y1,
|
|
&tr_tool->tx2, &tr_tool->ty2);
|
|
gimp_matrix3_transform_point (&tr_tool->transform,
|
|
tr_tool->x1, tr_tool->y2,
|
|
&tr_tool->tx3, &tr_tool->ty3);
|
|
gimp_matrix3_transform_point (&tr_tool->transform,
|
|
tr_tool->x2, tr_tool->y2,
|
|
&tr_tool->tx4, &tr_tool->ty4);
|
|
|
|
gimp_matrix3_transform_point (&tr_tool->transform,
|
|
tr_tool->cx, tr_tool->cy,
|
|
&tr_tool->tcx, &tr_tool->tcy);
|
|
|
|
if (tr_tool->grid_coords != NULL && tr_tool->tgrid_coords != NULL)
|
|
{
|
|
gint i, k;
|
|
gint gci;
|
|
|
|
gci = 0;
|
|
k = (tr_tool->ngx + tr_tool->ngy) * 2;
|
|
|
|
for (i = 0; i < k; i++)
|
|
{
|
|
gimp_matrix3_transform_point (&tr_tool->transform,
|
|
tr_tool->grid_coords[gci],
|
|
tr_tool->grid_coords[gci + 1],
|
|
&tr_tool->tgrid_coords[gci],
|
|
&tr_tool->tgrid_coords[gci + 1]);
|
|
gci += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_halt (GimpTransformTool *tr_tool)
|
|
{
|
|
GimpTool *tool = GIMP_TOOL (tr_tool);
|
|
|
|
if (tr_tool->original)
|
|
{
|
|
tile_manager_unref (tr_tool->original);
|
|
tr_tool->original = NULL;
|
|
}
|
|
|
|
/* inactivate the tool */
|
|
tr_tool->function = TRANSFORM_CREATING;
|
|
|
|
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tr_tool)))
|
|
gimp_draw_tool_stop (GIMP_DRAW_TOOL (tr_tool));
|
|
|
|
if (tr_tool->info_dialog)
|
|
info_dialog_popdown (tr_tool->info_dialog);
|
|
|
|
tool->gdisp = NULL;
|
|
tool->drawable = NULL;
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
GimpTransformOptions *options;
|
|
|
|
options =
|
|
GIMP_TRANSFORM_OPTIONS (GIMP_TOOL (tr_tool)->tool_info->tool_options);
|
|
|
|
/* find the boundaries */
|
|
if (tr_tool->original)
|
|
{
|
|
tile_manager_get_offsets (tr_tool->original, &tr_tool->x1, &tr_tool->y1);
|
|
|
|
tr_tool->x2 = tr_tool->x1 + tile_manager_width (tr_tool->original);
|
|
tr_tool->y2 = tr_tool->y1 + tile_manager_height (tr_tool->original);
|
|
}
|
|
else
|
|
{
|
|
switch (options->type)
|
|
{
|
|
case GIMP_TRANSFORM_TYPE_LAYER:
|
|
{
|
|
GimpDrawable *drawable;
|
|
gint offset_x, offset_y;
|
|
|
|
drawable = gimp_image_active_drawable (gdisp->gimage);
|
|
|
|
gimp_item_offsets (GIMP_ITEM (drawable), &offset_x, &offset_y);
|
|
|
|
gimp_drawable_mask_bounds (drawable,
|
|
&tr_tool->x1, &tr_tool->y1,
|
|
&tr_tool->x2, &tr_tool->y2);
|
|
tr_tool->x1 += offset_x;
|
|
tr_tool->y1 += offset_y;
|
|
tr_tool->x2 += offset_x;
|
|
tr_tool->y2 += offset_y;
|
|
}
|
|
break;
|
|
|
|
case GIMP_TRANSFORM_TYPE_SELECTION:
|
|
case GIMP_TRANSFORM_TYPE_PATH:
|
|
gimp_image_mask_bounds (gdisp->gimage,
|
|
&tr_tool->x1, &tr_tool->y1,
|
|
&tr_tool->x2, &tr_tool->y2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
tr_tool->cx = (gdouble) (tr_tool->x1 + tr_tool->x2) / 2.0;
|
|
tr_tool->cy = (gdouble) (tr_tool->y1 + tr_tool->y2) / 2.0;
|
|
|
|
/* changing the bounds invalidates any grid we may have */
|
|
if (tr_tool->use_grid)
|
|
gimp_transform_tool_grid_recalc (tr_tool);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_grid_recalc (GimpTransformTool *tr_tool)
|
|
{
|
|
GimpTransformOptions *options;
|
|
|
|
options =
|
|
GIMP_TRANSFORM_OPTIONS (GIMP_TOOL (tr_tool)->tool_info->tool_options);
|
|
|
|
if (tr_tool->grid_coords != NULL)
|
|
{
|
|
g_free (tr_tool->grid_coords);
|
|
tr_tool->grid_coords = NULL;
|
|
}
|
|
|
|
if (tr_tool->tgrid_coords != NULL)
|
|
{
|
|
g_free (tr_tool->tgrid_coords);
|
|
tr_tool->tgrid_coords = NULL;
|
|
}
|
|
|
|
switch (options->grid_type)
|
|
{
|
|
case GIMP_TRANSFORM_GRID_TYPE_N_LINES:
|
|
case GIMP_TRANSFORM_GRID_TYPE_SPACING:
|
|
{
|
|
GimpTool *tool;
|
|
gint i, gci;
|
|
gdouble *coords;
|
|
gint width, height;
|
|
|
|
width = MAX (1, tr_tool->x2 - tr_tool->x1);
|
|
height = MAX (1, tr_tool->y2 - tr_tool->y1);
|
|
|
|
tool = GIMP_TOOL (tr_tool);
|
|
|
|
if (options->grid_type == GIMP_TRANSFORM_GRID_TYPE_N_LINES)
|
|
{
|
|
if (width <= height)
|
|
{
|
|
tr_tool->ngx = options->grid_size;
|
|
tr_tool->ngy = tr_tool->ngx * MAX (1, height / width);
|
|
}
|
|
else
|
|
{
|
|
tr_tool->ngy = options->grid_size;
|
|
tr_tool->ngx = tr_tool->ngy * MAX (1, width / height);
|
|
}
|
|
}
|
|
else /* GIMP_TRANSFORM_GRID_TYPE_SPACING */
|
|
{
|
|
gint grid_size = MAX (2, options->grid_size);
|
|
|
|
tr_tool->ngx = width / grid_size;
|
|
tr_tool->ngy = height / grid_size;
|
|
}
|
|
|
|
tr_tool->grid_coords = coords =
|
|
g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
|
|
|
|
tr_tool->tgrid_coords =
|
|
g_new (gdouble, (tr_tool->ngx + tr_tool->ngy) * 4);
|
|
|
|
gci = 0;
|
|
|
|
for (i = 1; i <= tr_tool->ngx; i++)
|
|
{
|
|
coords[gci] = tr_tool->x1 + (((gdouble) i) / (tr_tool->ngx + 1) *
|
|
(tr_tool->x2 - tr_tool->x1));
|
|
coords[gci + 1] = tr_tool->y1;
|
|
coords[gci + 2] = coords[gci];
|
|
coords[gci + 3] = tr_tool->y2;
|
|
|
|
gci += 4;
|
|
}
|
|
|
|
for (i = 1; i <= tr_tool->ngy; i++)
|
|
{
|
|
coords[gci] = tr_tool->x1;
|
|
coords[gci + 1] = tr_tool->y1 + (((gdouble) i) / (tr_tool->ngy + 1) *
|
|
(tr_tool->y2 - tr_tool->y1));
|
|
coords[gci + 2] = tr_tool->x2;
|
|
coords[gci + 3] = coords[gci + 1];
|
|
|
|
gci += 4;
|
|
}
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_dialog (GimpTransformTool *tr_tool)
|
|
{
|
|
if (GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->dialog)
|
|
{
|
|
GimpToolInfo *tool_info;
|
|
const gchar *stock_id;
|
|
|
|
tool_info = GIMP_TOOL (tr_tool)->tool_info;
|
|
|
|
stock_id = gimp_viewable_get_stock_id (GIMP_VIEWABLE (tool_info));
|
|
|
|
tr_tool->info_dialog =
|
|
info_dialog_new (NULL,
|
|
tool_info->blurb,
|
|
GIMP_OBJECT (tool_info)->name,
|
|
stock_id,
|
|
tr_tool->shell_desc,
|
|
gimp_standard_help_func, tool_info->help_data);
|
|
|
|
gimp_dialog_create_action_area (GIMP_DIALOG (tr_tool->info_dialog->shell),
|
|
|
|
GIMP_STOCK_RESET,
|
|
transform_reset_callback,
|
|
tr_tool, NULL, NULL, FALSE, FALSE,
|
|
|
|
GTK_STOCK_CANCEL,
|
|
transform_cancel_callback,
|
|
tr_tool, NULL, NULL, FALSE, TRUE,
|
|
|
|
stock_id,
|
|
transform_ok_callback,
|
|
tr_tool, NULL, NULL, TRUE, FALSE,
|
|
|
|
NULL);
|
|
|
|
GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->dialog (tr_tool);
|
|
|
|
if (tr_tool->shell_identifier)
|
|
{
|
|
GimpDialogFactory *dialog_factory;
|
|
|
|
dialog_factory = gimp_dialog_factory_from_name ("toplevel");
|
|
|
|
gimp_dialog_factory_add_foreign (dialog_factory,
|
|
tr_tool->shell_identifier,
|
|
tr_tool->info_dialog->shell);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_prepare (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
if (tr_tool->info_dialog)
|
|
{
|
|
gimp_viewable_dialog_set_viewable (GIMP_VIEWABLE_DIALOG (tr_tool->info_dialog->shell),
|
|
GIMP_VIEWABLE (gimp_image_active_drawable (gdisp->gimage)));
|
|
|
|
gtk_widget_set_sensitive (GTK_WIDGET (tr_tool->info_dialog->shell), TRUE);
|
|
}
|
|
|
|
if (GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->prepare)
|
|
GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->prepare (tr_tool, gdisp);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_recalc (GimpTransformTool *tr_tool,
|
|
GimpDisplay *gdisp)
|
|
{
|
|
gimp_transform_tool_bounds (tr_tool, gdisp);
|
|
|
|
if (GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->recalc)
|
|
GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->recalc (tr_tool, gdisp);
|
|
}
|
|
|
|
static void
|
|
transform_reset_callback (GtkWidget *widget,
|
|
GimpTransformTool *tr_tool)
|
|
{
|
|
GimpTool *tool;
|
|
gint i;
|
|
|
|
tool = GIMP_TOOL (tr_tool);
|
|
|
|
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
|
|
|
|
/* Restore the previous transformation info */
|
|
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
|
tr_tool->trans_info[i] = tr_tool->old_trans_info[i];
|
|
|
|
/* recalculate the tool's transformation matrix */
|
|
gimp_transform_tool_recalc (tr_tool, tool->gdisp);
|
|
|
|
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
|
|
}
|
|
|
|
static void
|
|
transform_cancel_callback (GtkWidget *widget,
|
|
GimpTransformTool *tr_tool)
|
|
{
|
|
gimp_transform_tool_halt (tr_tool);
|
|
}
|
|
|
|
static void
|
|
transform_ok_callback (GtkWidget *widget,
|
|
GimpTransformTool *tr_tool)
|
|
{
|
|
gimp_transform_tool_doit (tr_tool, GIMP_TOOL (tr_tool)->gdisp);
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_notify_type (GimpTransformOptions *options,
|
|
GParamSpec *pspec,
|
|
GimpTransformTool *tr_tool)
|
|
{
|
|
if (tr_tool->function == TRANSFORM_CREATING)
|
|
return;
|
|
|
|
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));
|
|
|
|
tr_tool->type = options->type;
|
|
tr_tool->direction = options->direction;
|
|
|
|
/* recalculate the tool's transformation matrix */
|
|
gimp_transform_tool_recalc (tr_tool, GIMP_TOOL (tr_tool)->gdisp);
|
|
|
|
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
|
|
}
|
|
|
|
static void
|
|
gimp_transform_tool_notify_grid (GimpTransformOptions *options,
|
|
GParamSpec *pspec,
|
|
GimpTransformTool *tr_tool)
|
|
{
|
|
if (tr_tool->function == TRANSFORM_CREATING)
|
|
return;
|
|
|
|
gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));
|
|
|
|
gimp_transform_tool_grid_recalc (tr_tool);
|
|
gimp_transform_tool_transform_bounding_box (tr_tool);
|
|
|
|
gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
|
|
}
|