gimpvectortool.c 60.4 KB
Newer Older
1 2 3 4
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * Vector tool
5
 * Copyright (C) 2003 Simon Budig  <simon@gimp.org>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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 <gtk/gtk.h>
25
#include <gdk/gdkkeysyms.h>
26 27 28 29 30

#include "libgimpmath/gimpmath.h"
#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"

31
#include "tools-types.h"
32

33 34
#include "core/gimp.h"
#include "core/gimpcontext.h"
35
#include "core/gimpchannel-select.h"
36
#include "core/gimpimage.h"
37
#include "core/gimpimage-undo-push.h"
38
#include "core/gimplist.h"
39
#include "core/gimptoolinfo.h"
40 41
#include "core/gimpundo.h"
#include "core/gimpundostack.h"
42 43 44

#include "vectors/gimpanchor.h"
#include "vectors/gimpvectors.h"
45
#include "vectors/gimpbezierstroke.h"
46

47 48
#include "widgets/gimphelp-ids.h"

49
#include "display/gimpdisplay.h"
50 51
#include "display/gimpdisplayshell.h"
#include "display/gimpdisplayshell-scale.h"
52

53
#include "gimptoolcontrol.h"
54
#include "gimpvectoroptions.h"
55 56
#include "gimpvectortool.h"

57
#include "dialogs/stroke-dialog.h"
58

59
#include "gimp-intl.h"
60 61


62
#define TARGET 9
63

64 65 66 67
#define TOGGLE_MASK GDK_SHIFT_MASK
#define MOVE_MASK   GDK_MOD1_MASK
#define INSDEL_MASK GDK_CONTROL_MASK

68 69

/*  local function prototypes  */
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
static void     gimp_vector_tool_class_init      (GimpVectorToolClass *klass);
static void     gimp_vector_tool_init            (GimpVectorTool      *tool);

static void     gimp_vector_tool_control         (GimpTool        *tool,
                                                  GimpToolAction   action,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_button_press    (GimpTool        *tool,
                                                  GimpCoords      *coords,
                                                  guint32          time,
                                                  GdkModifierType  state,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_button_release  (GimpTool        *tool,
                                                  GimpCoords      *coords,
                                                  guint32          time,
                                                  GdkModifierType  state,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_motion          (GimpTool        *tool,
                                                  GimpCoords      *coords,
                                                  guint32          time,
                                                  GdkModifierType  state,
                                                  GimpDisplay     *gdisp);
static gboolean gimp_vector_tool_key_press       (GimpTool        *tool,
                                                  GdkEventKey     *kevent,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_modifier_key    (GimpTool        *tool,
                                                  GdkModifierType  key,
                                                  gboolean         press,
                                                  GdkModifierType  state,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_oper_update     (GimpTool        *tool,
                                                  GimpCoords      *coords,
                                                  GdkModifierType  state,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_status_update   (GimpTool        *tool,
                                                  GimpDisplay     *gdisp);
static void     gimp_vector_tool_cursor_update   (GimpTool        *tool,
                                                  GimpCoords      *coords,
                                                  GdkModifierType  state,
                                                  GimpDisplay     *gdisp);

static void     gimp_vector_tool_draw            (GimpDrawTool    *draw_tool);

static void     gimp_vector_tool_vectors_changed (GimpImage       *gimage,
                                                  GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_vectors_removed (GimpVectors     *vectors,
                                                  GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_vectors_visible (GimpVectors     *vectors,
                                                  GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_vectors_freeze  (GimpVectors     *vectors,
                                                  GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_vectors_thaw    (GimpVectors     *vectors,
                                                  GimpVectorTool  *vector_tool);

static void     gimp_vector_tool_move_selected_anchors
                                                 (GimpVectorTool  *vector_tool,
                                                  gdouble          x,
                                                  gdouble          y);
static void     gimp_vector_tool_delete_selected_anchors
                                                 (GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_verify_state    (GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_undo_push       (GimpVectorTool  *vector_tool,
                                                  const gchar     *desc);

static void     gimp_vector_tool_to_selection    (GimpVectorTool  *vector_tool);
static void     gimp_vector_tool_to_selection_extended
                                                 (GimpVectorTool  *vector_tool,
                                                  gint             state);
static void     gimp_vector_tool_stroke_vectors  (GimpVectorTool  *vector_tool,
                                                  GtkWidget       *button);
140

141

142
static GimpDrawToolClass *parent_class = NULL;
143 144 145


void
146 147
gimp_vector_tool_register (GimpToolRegisterCallback callback,
                           gpointer                 data)
148
{
Nate Summers's avatar
Nate Summers committed
149
  (* callback) (GIMP_TYPE_VECTOR_TOOL,
150 151
                GIMP_TYPE_VECTOR_OPTIONS,
                gimp_vector_options_gui,
152
                0,
153
                "gimp-vector-tool",
154 155
                _("Paths"),
                _("Create and edit paths"),
156
                N_("_Paths"), "b",
157
                NULL, GIMP_HELP_TOOL_PATH,
Nate Summers's avatar
Nate Summers committed
158
                GIMP_STOCK_TOOL_PATH,
159
                data);
160 161 162 163 164 165 166 167 168 169 170 171
}

GType
gimp_vector_tool_get_type (void)
{
  static GType tool_type = 0;

  if (! tool_type)
    {
      static const GTypeInfo tool_info =
      {
        sizeof (GimpVectorToolClass),
172 173 174 175 176 177 178 179
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gimp_vector_tool_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data     */
        sizeof (GimpVectorTool),
        0,              /* n_preallocs    */
        (GInstanceInitFunc) gimp_vector_tool_init,
180 181
      };

182
      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
183
                                          "GimpVectorTool",
184 185 186 187 188 189 190 191 192
                                          &tool_info, 0);
    }

  return tool_type;
}

static void
gimp_vector_tool_class_init (GimpVectorToolClass *klass)
{
193
  GObjectClass      *object_class;
194 195 196
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_tool_class;

197
  object_class    = G_OBJECT_CLASS (klass);
198 199 200 201 202 203 204 205 206
  tool_class      = GIMP_TOOL_CLASS (klass);
  draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);

  parent_class = g_type_class_peek_parent (klass);

  tool_class->control        = gimp_vector_tool_control;
  tool_class->button_press   = gimp_vector_tool_button_press;
  tool_class->button_release = gimp_vector_tool_button_release;
  tool_class->motion         = gimp_vector_tool_motion;
207
  tool_class->key_press      = gimp_vector_tool_key_press;
208
  tool_class->modifier_key   = gimp_vector_tool_modifier_key;
209
  tool_class->oper_update    = gimp_vector_tool_oper_update;
210 211 212 213 214 215 216 217
  tool_class->cursor_update  = gimp_vector_tool_cursor_update;

  draw_tool_class->draw      = gimp_vector_tool_draw;
}

static void
gimp_vector_tool_init (GimpVectorTool *vector_tool)
{
218
  GimpTool *tool = GIMP_TOOL (vector_tool);
219

220 221 222 223 224 225
  gimp_tool_control_set_scroll_lock         (tool->control, TRUE);
  gimp_tool_control_set_handles_empty_image (tool->control, TRUE);
  gimp_tool_control_set_motion_mode         (tool->control,
                                             GIMP_MOTION_MODE_COMPRESS);
  gimp_tool_control_set_tool_cursor         (tool->control,
                                             GIMP_TOOL_CURSOR_PATHS);
226

227
  vector_tool->function       = VECTORS_CREATE_VECTOR;
228
  vector_tool->restriction    = GIMP_ANCHOR_FEATURE_NONE;
229 230 231
  vector_tool->modifier_lock  = FALSE;
  vector_tool->last_x         = 0.0;
  vector_tool->last_y         = 0.0;
232
  vector_tool->undo_motion    = FALSE;
233
  vector_tool->have_undo      = FALSE;
234 235

  vector_tool->cur_anchor     = NULL;
236
  vector_tool->cur_anchor2    = NULL;
237
  vector_tool->cur_stroke     = NULL;
238
  vector_tool->cur_position   = 0.0;
239
  vector_tool->cur_vectors    = NULL;
240
  vector_tool->vectors        = NULL;
241 242 243 244

  vector_tool->sel_count      = 0;
  vector_tool->sel_anchor     = NULL;
  vector_tool->sel_stroke     = NULL;
245

246
  vector_tool->saved_mode     = GIMP_VECTOR_MODE_DESIGN;
247 248
}

249

250 251
static void
gimp_vector_tool_control (GimpTool       *tool,
252 253
                          GimpToolAction  action,
                          GimpDisplay    *gdisp)
254
{
255
  GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
256 257 258 259 260 261 262 263 264 265

  switch (action)
    {
    case PAUSE:
      break;

    case RESUME:
      break;

    case HALT:
266
      gimp_vector_tool_set_vectors (vector_tool, NULL);
267
      gimp_tool_pop_status (tool, gdisp);
268 269 270 271 272 273 274 275 276 277 278
      break;

    default:
      break;
    }

  GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
}

static void
gimp_vector_tool_button_press (GimpTool        *tool,
279 280 281 282
                               GimpCoords      *coords,
                               guint32          time,
                               GdkModifierType  state,
                               GimpDisplay     *gdisp)
283
{
284
  GimpDrawTool      *draw_tool;
285 286
  GimpVectorTool    *vector_tool;
  GimpVectorOptions *options;
287
  GimpVectors       *vectors;
288

289
  draw_tool   = GIMP_DRAW_TOOL (tool);
290
  vector_tool = GIMP_VECTOR_TOOL (tool);
291
  options     = GIMP_VECTOR_OPTIONS (tool->tool_info->tool_options);
292

293 294 295 296
  /* do nothing if we are an FINISHED state */
  if (vector_tool->function == VECTORS_FINISHED)
    return;

297 298
  g_return_if_fail (vector_tool->vectors  != NULL                  ||
                    vector_tool->function == VECTORS_SELECT_VECTOR ||
299 300
                    vector_tool->function == VECTORS_CREATE_VECTOR);

301 302
  vector_tool->undo_motion = FALSE;

303
  /* save the current modifier state */
304 305

  vector_tool->saved_state = state;
306

307 308 309 310 311 312
  gimp_draw_tool_pause (draw_tool);

  if (gimp_draw_tool_is_active (draw_tool) && draw_tool->gdisp != gdisp)
    {
      gimp_draw_tool_stop (draw_tool);
    }
313

Simon Budig's avatar
Simon Budig committed
314
  gimp_tool_control_activate (tool->control);
315 316
  tool->gdisp = gdisp;

317 318 319 320
  /* select a vectors object */

  if (vector_tool->function == VECTORS_SELECT_VECTOR)
    {
321
      if (gimp_draw_tool_on_vectors (draw_tool, gdisp, coords, TARGET, TARGET,
322
                                     NULL, NULL, NULL, NULL, NULL, &vectors))
323
        {
324
          gimp_vector_tool_set_vectors (vector_tool, vectors);
325 326
          gimp_image_set_active_vectors (gdisp->gimage, vectors);
        }
327 328 329
      vector_tool->function = VECTORS_FINISHED;
    }

330 331 332 333
  /* create a new vector from scratch */

  if (vector_tool->function == VECTORS_CREATE_VECTOR)
    {
334 335
      vectors = gimp_vectors_new (gdisp->gimage, _("Unnamed"));

336 337 338
      /* Undo step gets added implicitely */
      vector_tool->have_undo = TRUE;

339 340
      vector_tool->undo_motion = TRUE;

341 342 343 344 345 346
      gimp_image_add_vectors (gdisp->gimage, vectors, -1);
      gimp_image_flush (gdisp->gimage);

      gimp_vector_tool_set_vectors (vector_tool, vectors);

      vector_tool->function = VECTORS_CREATE_STROKE;
347

348
    }
349

350 351
  gimp_vectors_freeze (vector_tool->vectors);

352
  /* create a new stroke */
353

354 355
  if (vector_tool->function == VECTORS_CREATE_STROKE)
    {
356
      g_return_if_fail (vector_tool->vectors != NULL);
357

358 359
      gimp_vector_tool_undo_push (vector_tool, _("Add Stroke"));

360 361
      vector_tool->cur_stroke = gimp_bezier_stroke_new ();
      gimp_vectors_stroke_add (vector_tool->vectors, vector_tool->cur_stroke);
362

363 364
      vector_tool->undo_motion = TRUE;

365
      vector_tool->sel_stroke = vector_tool->cur_stroke;
366
      vector_tool->cur_anchor = NULL;
367
      vector_tool->sel_anchor = NULL;
368
      vector_tool->function = VECTORS_ADD_ANCHOR;
369
    }
370

371

372
  /* add an anchor to an existing stroke */
373

374 375
  if (vector_tool->function == VECTORS_ADD_ANCHOR)
    {
376 377
      gimp_vector_tool_undo_push (vector_tool, _("Add Anchor"));

378 379
      vector_tool->undo_motion = TRUE;

380 381 382 383
      vector_tool->cur_anchor =
                     gimp_bezier_stroke_extend (vector_tool->sel_stroke, coords,
                                                vector_tool->sel_anchor,
                                                EXTEND_EDITABLE);
384

385 386
      vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;

387 388 389 390
      if (!options->polygonal)
        vector_tool->function = VECTORS_MOVE_HANDLE;
      else
        vector_tool->function = VECTORS_MOVE_ANCHOR;
391 392
      vector_tool->cur_stroke = vector_tool->sel_stroke;
    }
393 394


395
  /* insertion of an anchor in a curve segment */
396 397

  if (vector_tool->function == VECTORS_INSERT_ANCHOR)
398
    {
399 400
      gimp_vector_tool_undo_push (vector_tool, _("Insert Anchor"));

401 402
      vector_tool->undo_motion = TRUE;

403 404
      vector_tool->cur_anchor =
                         gimp_stroke_anchor_insert (vector_tool->cur_stroke,
405
                                                    vector_tool->cur_anchor,
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
                                                    vector_tool->cur_position);
      if (vector_tool->cur_anchor)
        {
          if (options->polygonal)
            {
              gimp_stroke_anchor_convert (vector_tool->cur_stroke,
                                          vector_tool->cur_anchor,
                                          GIMP_ANCHOR_FEATURE_EDGE);
            }
          vector_tool->function = VECTORS_MOVE_ANCHOR;
        }
      else
        {
          vector_tool->function = VECTORS_FINISHED;
        }
421
    }
422

423

424 425 426
  /* move a handle */

  if (vector_tool->function == VECTORS_MOVE_HANDLE)
427
    {
428 429
      gimp_vector_tool_undo_push (vector_tool, _("Drag Handle"));

430
      if (vector_tool->cur_anchor->type == GIMP_ANCHOR_ANCHOR)
431
        {
432 433 434 435 436 437 438 439
          if (!vector_tool->cur_anchor->selected)
            {
              gimp_vectors_anchor_select (vector_tool->vectors,
                                          vector_tool->cur_stroke,
                                          vector_tool->cur_anchor,
                                          TRUE, TRUE);
              vector_tool->undo_motion = TRUE;
            }
440

441 442 443
          gimp_draw_tool_on_vectors_handle (GIMP_DRAW_TOOL (tool), gdisp,
                                            vector_tool->vectors, coords,
                                            TARGET, TARGET,
444
                                            GIMP_ANCHOR_CONTROL, TRUE,
445 446
                                            &vector_tool->cur_anchor,
                                            &vector_tool->cur_stroke);
447 448
          if (!vector_tool->cur_anchor)
            vector_tool->function = VECTORS_FINISHED;
449
        }
450
    }
451

452 453 454 455 456

  /* move an anchor */

  if (vector_tool->function == VECTORS_MOVE_ANCHOR)
    {
457 458
      gimp_vector_tool_undo_push (vector_tool, _("Drag Anchor"));

459 460 461 462 463 464 465 466
      if (!vector_tool->cur_anchor->selected)
        {
          gimp_vectors_anchor_select (vector_tool->vectors,
                                      vector_tool->cur_stroke,
                                      vector_tool->cur_anchor,
                                      TRUE, TRUE);
          vector_tool->undo_motion = TRUE;
        }
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
    }


  /* move multiple anchors */

  if (vector_tool->function == VECTORS_MOVE_ANCHORSET)
    {
      gimp_vector_tool_undo_push (vector_tool, _("Drag Anchors"));

      if (state & TOGGLE_MASK)
        {
          gimp_vectors_anchor_select (vector_tool->vectors,
                                      vector_tool->cur_stroke,
                                      vector_tool->cur_anchor,
                                      !vector_tool->cur_anchor->selected,
                                      FALSE);
483
          vector_tool->undo_motion = TRUE;
484 485 486
          if (vector_tool->cur_anchor->selected == FALSE)
            vector_tool->function = VECTORS_FINISHED;
        }
487 488 489
    }


490 491 492 493 494 495 496 497 498
  /* move a curve segment directly */

  if (vector_tool->function == VECTORS_MOVE_CURVE)
    {
      gimp_vector_tool_undo_push (vector_tool, _("Drag Curve"));

      /* the magic numbers are taken from the "feel good" parameter
       * from gimp_bezier_stroke_point_move_relative in gimpbezierstroke.c. */
      if (vector_tool->cur_position < 5.0 / 6.0)
499 500 501 502 503 504
        {
          gimp_vectors_anchor_select (vector_tool->vectors,
                                      vector_tool->cur_stroke,
                                      vector_tool->cur_anchor, TRUE, TRUE);
          vector_tool->undo_motion = TRUE;
        }
505

506
      if (vector_tool->cur_position > 1.0 / 6.0)
507 508 509 510 511 512 513
        {
          gimp_vectors_anchor_select (vector_tool->vectors,
                                      vector_tool->cur_stroke,
                                      vector_tool->cur_anchor2, TRUE,
                                      (vector_tool->cur_position >= 5.0 / 6.0));
          vector_tool->undo_motion = TRUE;
        }
514

515 516 517
    }


518
  /* connect two strokes */
519

520 521
  if (vector_tool->function == VECTORS_CONNECT_STROKES)
    {
522 523
      gimp_vector_tool_undo_push (vector_tool, _("Connect Strokes"));

524 525 526 527
      gimp_stroke_connect_stroke (vector_tool->sel_stroke,
                                  vector_tool->sel_anchor,
                                  vector_tool->cur_stroke,
                                  vector_tool->cur_anchor);
528 529
      vector_tool->undo_motion = TRUE;

530 531
      if (vector_tool->cur_stroke != vector_tool->sel_stroke &&
          gimp_stroke_is_empty (vector_tool->cur_stroke))
532
        {
533 534
          gimp_vectors_stroke_remove (vector_tool->vectors,
                                      vector_tool->cur_stroke);
535
        }
536 537 538 539 540
      vector_tool->sel_anchor = vector_tool->cur_anchor;
      vector_tool->cur_stroke = vector_tool->sel_stroke;

      gimp_vectors_anchor_select (vector_tool->vectors,
                                  vector_tool->sel_stroke,
541
                                  vector_tool->sel_anchor, TRUE, TRUE);
542

543 544
      vector_tool->function = VECTORS_FINISHED;
    }
545

546 547 548 549 550 551

  /* move a stroke or all strokes of a vectors object */

  if (vector_tool->function == VECTORS_MOVE_STROKE ||
      vector_tool->function == VECTORS_MOVE_VECTORS)
    {
552 553
      gimp_vector_tool_undo_push (vector_tool, _("Drag Path"));

554 555 556 557
      /* Work is being done in gimp_vector_tool_motion ()... */
    }


558
  /* convert an anchor to something that looks like an edge */
559

560 561
  if (vector_tool->function == VECTORS_CONVERT_EDGE)
    {
562 563
      gimp_vector_tool_undo_push (vector_tool, _("Convert Edge"));

564 565 566
      gimp_stroke_anchor_convert (vector_tool->cur_stroke,
                                  vector_tool->cur_anchor,
                                  GIMP_ANCHOR_FEATURE_EDGE);
567
      vector_tool->undo_motion = TRUE;
568

569 570 571 572
      if (vector_tool->cur_anchor->type == GIMP_ANCHOR_ANCHOR)
        {
          gimp_vectors_anchor_select (vector_tool->vectors,
                                      vector_tool->cur_stroke,
573
                                      vector_tool->cur_anchor, TRUE, TRUE);
574

575
          vector_tool->function = VECTORS_MOVE_ANCHOR;
576
        }
577 578 579 580
      else
        {
          vector_tool->cur_stroke = NULL;
          vector_tool->cur_anchor = NULL;
581

582 583 584 585
          /* avoid doing anything stupid */
          vector_tool->function = VECTORS_FINISHED;
        }
    }
Simon Budig's avatar
Simon Budig committed
586

587

588 589 590
  /* removal of a node in a stroke */

  if (vector_tool->function == VECTORS_DELETE_ANCHOR)
591
    {
592 593
      gimp_vector_tool_undo_push (vector_tool, _("Delete Anchor"));

594 595
      gimp_stroke_anchor_delete (vector_tool->cur_stroke,
                                 vector_tool->cur_anchor);
596
      vector_tool->undo_motion = TRUE;
597 598

      if (gimp_stroke_is_empty (vector_tool->cur_stroke))
599
        gimp_vectors_stroke_remove (vector_tool->vectors,
600 601 602 603 604 605 606 607 608 609 610 611 612
                                    vector_tool->cur_stroke);

      vector_tool->cur_stroke = NULL;
      vector_tool->cur_anchor = NULL;
      vector_tool->function = VECTORS_FINISHED;
    }


  /* deleting a segment (opening up a stroke) */

  if (vector_tool->function == VECTORS_DELETE_SEGMENT)
    {
      GimpStroke *new_stroke;
613 614 615

      gimp_vector_tool_undo_push (vector_tool, _("Delete Segment"));

616 617 618 619 620
      new_stroke = gimp_stroke_open (vector_tool->cur_stroke,
                                     vector_tool->cur_anchor);
      if (new_stroke)
        gimp_vectors_stroke_add (vector_tool->vectors, new_stroke);

621
      vector_tool->undo_motion = TRUE;
622 623 624
      vector_tool->cur_stroke = NULL;
      vector_tool->cur_anchor = NULL;
      vector_tool->function = VECTORS_FINISHED;
625 626
    }

627 628 629
  vector_tool->last_x = coords->x;
  vector_tool->last_y = coords->y;

630 631
  gimp_vectors_thaw (vector_tool->vectors);

632
  if (! gimp_draw_tool_is_active (draw_tool))
633 634 635
    {
      gimp_draw_tool_start (draw_tool, gdisp);
    }
636 637

  gimp_draw_tool_resume (draw_tool);
638 639 640 641 642 643 644 645 646
}

static void
gimp_vector_tool_button_release (GimpTool        *tool,
                                 GimpCoords      *coords,
                                 guint32          time,
                                 GdkModifierType  state,
                                 GimpDisplay     *gdisp)
{
647
  GimpVectorTool *vector_tool = GIMP_VECTOR_TOOL (tool);
648

649
  vector_tool->function = VECTORS_FINISHED;
650

651 652
  if (vector_tool->have_undo &&
      (! vector_tool->undo_motion || (state & GDK_BUTTON3_MASK)))
653 654 655 656 657 658
    {
      GimpUndo            *undo;
      GimpUndoAccumulator  accum = { 0, };

      undo = gimp_undo_stack_pop_undo (gdisp->gimage->undo_stack,
                                       GIMP_UNDO_MODE_UNDO, &accum);
659

660
      gimp_image_undo_event (gdisp->gimage, GIMP_UNDO_EVENT_UNDO_EXPIRED, undo);
661 662

      gimp_undo_free (undo, GIMP_UNDO_MODE_UNDO);
663
      g_object_unref (undo);
664 665 666
    }

  vector_tool->have_undo = FALSE;
667
  vector_tool->undo_motion = FALSE;
668

669
  gimp_tool_control_halt (tool->control);
670
  gimp_image_flush (gdisp->gimage);
671 672 673 674 675 676 677 678 679
}

static void
gimp_vector_tool_motion (GimpTool        *tool,
                         GimpCoords      *coords,
                         guint32          time,
                         GdkModifierType  state,
                         GimpDisplay     *gdisp)
{
680 681 682
  GimpVectorTool    *vector_tool;
  GimpVectorOptions *options;
  GimpAnchor        *anchor;
683 684

  vector_tool = GIMP_VECTOR_TOOL (tool);
685
  options     = GIMP_VECTOR_OPTIONS (tool->tool_info->tool_options);
686

687 688 689
  if (vector_tool->function == VECTORS_FINISHED)
    return;

690
  gimp_vectors_freeze (vector_tool->vectors);
691

692 693 694 695
  if ((vector_tool->saved_state & TOGGLE_MASK) != (state & TOGGLE_MASK))
    vector_tool->modifier_lock = FALSE;

  if (!vector_tool->modifier_lock)
696
    {
697 698 699 700 701 702 703 704
      if (state & TOGGLE_MASK)
        {
          vector_tool->restriction = GIMP_ANCHOR_FEATURE_SYMMETRIC;
        }
      else
        {
          vector_tool->restriction = GIMP_ANCHOR_FEATURE_NONE;
        }
705 706
    }

707 708
  switch (vector_tool->function)
    {
709 710
    case VECTORS_MOVE_ANCHOR:
    case VECTORS_MOVE_HANDLE:
711 712 713
      anchor = vector_tool->cur_anchor;

      if (anchor)
714 715 716 717 718 719
        {
          gimp_stroke_anchor_move_absolute (vector_tool->cur_stroke,
                                            vector_tool->cur_anchor,
                                            coords, vector_tool->restriction);
          vector_tool->undo_motion = TRUE;
        }
720 721 722
      break;

    case VECTORS_MOVE_CURVE:
723 724 725 726 727
      if (options->polygonal)
        {
          gimp_vector_tool_move_selected_anchors (vector_tool,
                                               coords->x - vector_tool->last_x,
                                               coords->y - vector_tool->last_y);
728
          vector_tool->undo_motion = TRUE;
729 730 731 732 733 734 735
        }
      else
        {
          gimp_stroke_point_move_absolute (vector_tool->cur_stroke,
                                           vector_tool->cur_anchor,
                                           vector_tool->cur_position,
                                           coords, vector_tool->restriction);
736
          vector_tool->undo_motion = TRUE;
737
        }
738
      break;
739

740 741 742 743
    case VECTORS_MOVE_ANCHORSET:
      gimp_vector_tool_move_selected_anchors (vector_tool,
                                              coords->x - vector_tool->last_x,
                                              coords->y - vector_tool->last_y);
744
      vector_tool->undo_motion = TRUE;
745 746
      break;

747
    case VECTORS_MOVE_STROKE:
748 749 750 751 752
      if (vector_tool->cur_stroke)
        {
          gimp_stroke_translate (vector_tool->cur_stroke,
                                 coords->x - vector_tool->last_x,
                                 coords->y - vector_tool->last_y);
753
          vector_tool->undo_motion = TRUE;
754 755 756 757 758 759
        }
      else if (vector_tool->sel_stroke)
        {
          gimp_stroke_translate (vector_tool->sel_stroke,
                                 coords->x - vector_tool->last_x,
                                 coords->y - vector_tool->last_y);
760
          vector_tool->undo_motion = TRUE;
761
        }
762 763 764 765 766 767
      break;

    case VECTORS_MOVE_VECTORS:
      gimp_item_translate (GIMP_ITEM (vector_tool->vectors),
                           coords->x - vector_tool->last_x,
                           coords->y - vector_tool->last_y, FALSE);
768
      vector_tool->undo_motion = TRUE;
769 770
      break;

771 772 773 774
    default:
      break;
    }

775 776 777
  vector_tool->last_x = coords->x;
  vector_tool->last_y = coords->y;

778
  gimp_vectors_thaw (vector_tool->vectors);
779 780
}

781
static gboolean
782
gimp_vector_tool_key_press (GimpTool     *tool,
783 784 785
                            GdkEventKey  *kevent,
                            GimpDisplay  *gdisp)
{
786 787 788 789 790 791 792
  GimpVectorTool    *vector_tool = GIMP_VECTOR_TOOL (tool);
  GimpDrawTool      *draw_tool   = GIMP_DRAW_TOOL (tool);
  GimpVectorOptions *options;

  GimpDisplayShell  *shell;
  gdouble            xdist, ydist;
  gdouble            pixels = 1.0;
793

794
  if (! vector_tool->vectors)
795
    return FALSE;
796

797 798 799
  if (gdisp != draw_tool->gdisp)
    return FALSE;

800 801 802 803 804 805 806 807
  shell = GIMP_DISPLAY_SHELL (draw_tool->gdisp->shell);

  if (kevent->state & GDK_SHIFT_MASK)
    pixels = 10.0;

  if (kevent->state & GDK_CONTROL_MASK)
    pixels = 50.0;

808
  switch (kevent->keyval)
809
    {
810 811 812 813
    case GDK_KP_Enter:
    case GDK_Return:
      gimp_vector_tool_to_selection_extended (vector_tool, kevent->state);
      break;
814

815 816 817 818
    case GDK_BackSpace:
    case GDK_Delete:
      gimp_vector_tool_delete_selected_anchors (vector_tool);
      break;
819

820 821 822 823 824 825
    case GDK_Left:
    case GDK_Right:
    case GDK_Up:
    case GDK_Down:
      xdist = FUNSCALEX (shell, pixels);
      ydist = FUNSCALEY (shell, pixels);
826

827
      gimp_vector_tool_undo_push (vector_tool, _("Move Anchors"));
828

829
      gimp_vectors_freeze (vector_tool->vectors);
830

831 832 833 834 835
      switch (kevent->keyval)
        {
        case GDK_Left:
          gimp_vector_tool_move_selected_anchors (vector_tool, -xdist, 0);
          break;
836

837 838
        case GDK_Right:
          gimp_vector_tool_move_selected_anchors (vector_tool, xdist, 0);
839 840
          break;

841 842 843
        case GDK_Up:
          gimp_vector_tool_move_selected_anchors (vector_tool, 0, -ydist);
          break;
844

845 846
        case GDK_Down:
          gimp_vector_tool_move_selected_anchors (vector_tool, 0, ydist);
847
          break;
848 849

        default:
850
          break;
851 852
        }

853 854 855 856 857 858 859 860 861 862 863 864 865 866
      gimp_vectors_thaw (vector_tool->vectors);
      vector_tool->have_undo = FALSE;
      break;

    case GDK_Escape:
      options = GIMP_VECTOR_OPTIONS (tool->tool_info->tool_options);

      if (options->edit_mode != GIMP_VECTOR_MODE_DESIGN)
        g_object_set (options, "vectors-edit-mode",
                      GIMP_VECTOR_MODE_DESIGN, NULL);
      break;

    default:
      return FALSE;
867
    }
868

869 870
  gimp_image_flush (gdisp->gimage);

871
  return TRUE;
872 873
}

874 875 876 877 878 879 880
static void
gimp_vector_tool_modifier_key (GimpTool        *tool,
                               GdkModifierType  key,
                               gboolean         press,
                               GdkModifierType  state,
                               GimpDisplay     *gdisp)
{
881
  GimpVectorTool    *vector_tool = GIMP_VECTOR_TOOL (tool);
882 883
  GimpVectorOptions *options;

884
  options = GIMP_VECTOR_OPTIONS (tool->tool_info->tool_options);
885 886 887 888

  if (key == TOGGLE_MASK)
    return;

889
  if (key == INSDEL_MASK || key == MOVE_MASK)
890
    {
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
      GimpVectorMode button_mode;

      button_mode = options->edit_mode;

      if (press)
        {
          if (key == (state & (INSDEL_MASK | MOVE_MASK)))
            {
              /*  first modifier pressed  */

              vector_tool->saved_mode = options->edit_mode;
            }
        }
      else
        {
          if (! (state & (INSDEL_MASK | MOVE_MASK)))
            {
              /*  last modifier released  */

              button_mode = vector_tool->saved_mode;
            }
        }

914
      if (state & MOVE_MASK)
915
        {
916
          button_mode = GIMP_VECTOR_MODE_MOVE;
917
        }
918
      else if (state & INSDEL_MASK)
919
        {
920
          button_mode = GIMP_VECTOR_MODE_EDIT;
921 922 923 924 925 926
        }

      if (button_mode != options->edit_mode)
        {
          g_object_set (options, "vectors-edit-mode", button_mode, NULL);
        }
927
    }
928 929
}

930 931 932 933 934 935
static void
gimp_vector_tool_oper_update (GimpTool        *tool,
                              GimpCoords      *coords,
                              GdkModifierType  state,
                              GimpDisplay     *gdisp)
{
936
  GimpVectorTool    *vector_tool;
937
  GimpDrawTool      *draw_tool;
938
  GimpVectorOptions *options;
939 940 941 942 943 944 945
  GimpAnchor        *anchor     = NULL;
  GimpAnchor        *anchor2    = NULL;
  GimpStroke        *stroke     = NULL;
  gdouble            position   = -1;
  gboolean           on_handle  = FALSE;
  gboolean           on_curve   = FALSE;
  gboolean           on_vectors = FALSE;
946

947
  vector_tool = GIMP_VECTOR_TOOL (tool);
948
  options     = GIMP_VECTOR_OPTIONS (tool->tool_info->tool_options);