gimppainttool.c 23.5 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 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
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
 */
Sven Neumann's avatar
Sven Neumann committed
18

19 20
#include "config.h"

21
#include <gtk/gtk.h>
22
#include <gdk/gdkkeysyms.h>
Sven Neumann's avatar
Sven Neumann committed
23

24
#include "tools-types.h"
Sven Neumann's avatar
Sven Neumann committed
25

26
#include "core/gimp.h"
27 28
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
29
#include "core/gimppaintinfo.h"
30
#include "core/gimpprojection.h"
31
#include "core/gimptoolinfo.h"
32
#include "core/gimpunit.h"
33

34
#include "paint/gimppaintcore.h"
35
#include "paint/gimppaintoptions.h"
36

37
#include "widgets/gimpdevices.h"
38
#include "widgets/gimpwidgets-utils.h"
39

40
#include "display/gimpdisplay.h"
41
#include "display/gimpdisplayshell.h"
42

43
#include "gimpcoloroptions.h"
44
#include "gimppainttool.h"
45
#include "gimptoolcontrol.h"
46
#include "tools-utils.h"
47

48
#include "gimp-intl.h"
49

50

51
#define HANDLE_SIZE    15
52
#define STATUSBAR_SIZE 200
Elliot Lee's avatar
Elliot Lee committed
53

54

55 56 57
static GObject * gimp_paint_tool_constructor (GType                type,
                                              guint                n_params,
                                              GObjectConstructParam *params);
58 59
static void   gimp_paint_tool_finalize       (GObject             *object);

60
static void   gimp_paint_tool_control        (GimpTool            *tool,
61
                                              GimpToolAction       action,
62
                                              GimpDisplay         *display);
63 64 65
static void   gimp_paint_tool_button_press   (GimpTool            *tool,
                                              GimpCoords          *coords,
                                              guint32              time,
66
                                              GdkModifierType      state,
67
                                              GimpDisplay         *display);
68 69 70
static void   gimp_paint_tool_button_release (GimpTool            *tool,
                                              GimpCoords          *coords,
                                              guint32              time,
71
                                              GdkModifierType      state,
72
                                              GimpDisplay         *display);
73 74 75
static void   gimp_paint_tool_motion         (GimpTool            *tool,
                                              GimpCoords          *coords,
                                              guint32              time,
76
                                              GdkModifierType      state,
77
                                              GimpDisplay         *display);
78 79 80 81
static void   gimp_paint_tool_modifier_key   (GimpTool            *tool,
                                              GdkModifierType      key,
                                              gboolean             press,
                                              GdkModifierType      state,
82
                                              GimpDisplay         *display);
83
static void   gimp_paint_tool_oper_update    (GimpTool            *tool,
84
                                              GimpCoords          *coords,
85
                                              GdkModifierType      state,
86
                                              gboolean             proximity,
87
                                              GimpDisplay         *display);
88 89 90

static void   gimp_paint_tool_draw           (GimpDrawTool        *draw_tool);

Elliot Lee's avatar
Elliot Lee committed
91

92
G_DEFINE_TYPE (GimpPaintTool, gimp_paint_tool, GIMP_TYPE_COLOR_TOOL)
93

94
#define parent_class gimp_paint_tool_parent_class
95 96


97 98
static void
gimp_paint_tool_class_init (GimpPaintToolClass *klass)
99
{
100 101 102
  GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
  GimpToolClass     *tool_class      = GIMP_TOOL_CLASS (klass);
  GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
103

104
  object_class->constructor  = gimp_paint_tool_constructor;
105 106
  object_class->finalize     = gimp_paint_tool_finalize;

107
  tool_class->control        = gimp_paint_tool_control;
108 109 110
  tool_class->button_press   = gimp_paint_tool_button_press;
  tool_class->button_release = gimp_paint_tool_button_release;
  tool_class->motion         = gimp_paint_tool_motion;
111 112
  tool_class->modifier_key   = gimp_paint_tool_modifier_key;
  tool_class->oper_update    = gimp_paint_tool_oper_update;
113 114

  draw_tool_class->draw      = gimp_paint_tool_draw;
115
}
Elliot Lee's avatar
Elliot Lee committed
116

117
static void
118
gimp_paint_tool_init (GimpPaintTool *paint_tool)
119
{
120
  GimpTool *tool = GIMP_TOOL (paint_tool);
121

122 123 124 125
  gimp_tool_control_set_motion_mode     (tool->control,
                                         GIMP_MOTION_MODE_EXACT);
  gimp_tool_control_set_action_value_1  (tool->control,
                                         "context/context-opacity-set");
Michael Natterer's avatar
Michael Natterer committed
126

127 128
  paint_tool->pick_colors = FALSE;
  paint_tool->draw_line   = FALSE;
129

130 131 132 133
  paint_tool->status      = _("Click to paint.");
  paint_tool->status_line = _("Click to draw the line.");
  paint_tool->status_ctrl = _("%s to pick a color");

134 135 136 137 138 139 140 141 142 143
  paint_tool->core        = NULL;
}

static GObject *
gimp_paint_tool_constructor (GType                  type,
                             guint                  n_params,
                             GObjectConstructParam *params)
{
  GObject       *object;
  GimpTool      *tool;
144
  GimpPaintInfo *paint_info;
145 146 147 148 149 150 151 152
  GimpPaintTool *paint_tool;

  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);

  tool       = GIMP_TOOL (object);
  paint_tool = GIMP_PAINT_TOOL (object);

  g_assert (GIMP_IS_TOOL_INFO (tool->tool_info));
153
  g_assert (GIMP_IS_PAINT_INFO (tool->tool_info->paint_info));
154

155 156 157 158 159 160
  paint_info = tool->tool_info->paint_info;

  g_assert (g_type_is_a (paint_info->paint_type, GIMP_TYPE_PAINT_CORE));

  paint_tool->core = g_object_new (paint_info->paint_type,
                                   "undo-desc", paint_info->blurb,
161 162 163
                                   NULL);

  return object;
164 165 166 167 168
}

static void
gimp_paint_tool_finalize (GObject *object)
{
169
  GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (object);
170

171
  if (paint_tool->core)
172
    {
173
      g_object_unref (paint_tool->core);
174
      paint_tool->core = NULL;
175 176 177
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
178
}
Elliot Lee's avatar
Elliot Lee committed
179

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
/**
 * gimp_paint_tool_enable_color_picker:
 * @tool: a #GimpPaintTool
 * @mode: the #GimpColorPickMode to set
 *
 * This is a convenience function used from the init method of paint
 * tools that want the color picking functionality. The @mode that is
 * set here is used to decide what cursor modifier to draw and if the
 * picked color goes to the foreground or background color.
 **/
void
gimp_paint_tool_enable_color_picker (GimpPaintTool     *tool,
                                     GimpColorPickMode  mode)
{
  g_return_if_fail (GIMP_IS_PAINT_TOOL (tool));

  tool->pick_colors = TRUE;

  GIMP_COLOR_TOOL (tool)->pick_mode = mode;
}

201
static void
202
gimp_paint_tool_control (GimpTool       *tool,
203 204
                         GimpToolAction  action,
                         GimpDisplay    *display)
205
{
206
  GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
207 208
  GimpDrawable  *drawable;

209
  drawable = gimp_image_active_drawable (display->image);
210 211

  switch (action)
212
    {
213 214 215 216 217
    case GIMP_TOOL_ACTION_PAUSE:
    case GIMP_TOOL_ACTION_RESUME:
      break;

    case GIMP_TOOL_ACTION_HALT:
218 219
      gimp_paint_core_paint (paint_tool->core,
                             drawable,
220
                             GIMP_PAINT_TOOL_GET_OPTIONS (tool),
221
                             GIMP_PAINT_STATE_FINISH, 0);
222
      gimp_paint_core_cleanup (paint_tool->core);
223
      break;
224 225
    }

226
  GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
227
}
228

229 230
/**
 * gimp_paint_tool_round_line:
231 232 233
 * @core:          the #GimpPaintCore
 * @center_pixels: push coordinates to pixel centers?
 * @state:         the modifier state
234 235
 *
 * Adjusts core->last_coords and core_cur_coords in preparation to
236 237 238
 * drawing a straight line. If @center_pixels is TRUE the endpoints
 * get pushed to the center of the pixels. This avoids artefacts
 * for e.g. the hard mode. The rounding of the slope to 15 degree
239 240 241 242 243 244
 * steps if ctrl is pressed happens, as does rounding the start and
 * end coordinates (which may be fractional in high zoom modes) to
 * the center of pixels.
 **/
static void
gimp_paint_tool_round_line (GimpPaintCore   *core,
245
                            gboolean         center_pixels,
246 247
                            GdkModifierType  state)
{
248 249 250 251 252 253 254
  if (center_pixels)
    {
      core->last_coords.x = floor (core->last_coords.x) + 0.5;
      core->last_coords.y = floor (core->last_coords.y) + 0.5;
      core->cur_coords.x  = floor (core->cur_coords.x ) + 0.5;
      core->cur_coords.y  = floor (core->cur_coords.y ) + 0.5;
    }
255

256 257
  /* Restrict to multiples of 15 degrees if ctrl is pressed */
  if (state & GDK_CONTROL_MASK)
258 259
    gimp_tool_motion_constrain (core->last_coords.x, core->last_coords.y,
                                &core->cur_coords.x, &core->cur_coords.y);
260 261
}

262
static void
263 264 265
gimp_paint_tool_button_press (GimpTool        *tool,
                              GimpCoords      *coords,
                              guint32          time,
266 267
                              GdkModifierType  state,
                              GimpDisplay     *display)
Elliot Lee's avatar
Elliot Lee committed
268
{
269 270 271
  GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (tool);
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
272
  GimpPaintCore    *core;
273
  GimpDrawable     *drawable;
274
  GdkDisplay       *gdk_display;
275
  GimpCoords        curr_coords;
276
  gint              off_x, off_y;
277

278 279
  core = paint_tool->core;

280
  drawable = gimp_image_active_drawable (display->image);
Elliot Lee's avatar
Elliot Lee committed
281

282 283
  curr_coords = *coords;

284
  gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
285

286 287
  curr_coords.x -= off_x;
  curr_coords.y -= off_y;
288

289 290 291
  if (gimp_draw_tool_is_active (draw_tool))
    gimp_draw_tool_stop (draw_tool);

292 293 294
  if (tool->display          &&
      tool->display != display &&
      tool->display->image == display->image)
295 296 297 298 299 300 301
    {
      /*  if this is a different display, but the same image, HACK around
       *  in tool internals AFTER stopping the current draw_tool, so
       *  straight line drawing works across different views of the
       *  same image.
       */

302
      tool->display = display;
303 304
    }

305
  gdk_display = gtk_widget_get_display (display->shell);
306

307
  core->use_pressure = (gimp_devices_get_current (display->image->gimp) !=
308
                        gdk_display_get_core_pointer (gdk_display));
309

310
  if (! gimp_paint_core_start (core, drawable, paint_options, &curr_coords))
Elliot Lee's avatar
Elliot Lee committed
311 312
    return;

313
  if ((display != tool->display) || ! paint_tool->draw_line)
Elliot Lee's avatar
Elliot Lee committed
314
    {
315 316
      /*  if this is a new image, reinit the core vals  */

317 318
      core->start_coords = core->cur_coords;
      core->last_coords  = core->cur_coords;
319 320 321

      core->distance     = 0.0;
      core->pixel_dist   = 0.0;
Elliot Lee's avatar
Elliot Lee committed
322
    }
323
  else if (paint_tool->draw_line)
Elliot Lee's avatar
Elliot Lee committed
324
    {
325 326 327
      /*  If shift is down and this is not the first paint
       *  stroke, then draw a line from the last coords to the pointer
       */
328
      gboolean hard;
329

330
      core->start_coords = core->last_coords;
331

332 333
      hard = (gimp_paint_options_get_brush_mode (paint_options) ==
              GIMP_BRUSH_HARD);
334
      gimp_paint_tool_round_line (core, hard, state);
Elliot Lee's avatar
Elliot Lee committed
335 336
    }

337 338
  /*  let the parent class activate the tool  */
  GIMP_TOOL_CLASS (parent_class)->button_press (tool,
339
                                                coords, time, state, display);
340 341 342

  if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
    return;
Elliot Lee's avatar
Elliot Lee committed
343

344
  /*  pause the current selection  */
345
  gimp_image_selection_control (display->image, GIMP_SELECTION_PAUSE);
Elliot Lee's avatar
Elliot Lee committed
346 347

  /*  Let the specific painting function initialize itself  */
348 349
  gimp_paint_core_paint (core, drawable, paint_options,
                         GIMP_PAINT_STATE_INIT, time);
Elliot Lee's avatar
Elliot Lee committed
350 351

  /*  Paint to the image  */
352
  if (paint_tool->draw_line)
Elliot Lee's avatar
Elliot Lee committed
353
    {
354
      gimp_paint_core_interpolate (core, drawable, paint_options, time);
Elliot Lee's avatar
Elliot Lee committed
355 356
    }
  else
357
    {
358 359
      gimp_paint_core_paint (core, drawable, paint_options,
                             GIMP_PAINT_STATE_MOTION, time);
360
    }
361

362 363
  gimp_projection_flush_now (display->image->projection);
  gimp_display_flush_now (display);
364

365
  gimp_draw_tool_start (draw_tool, display);
Elliot Lee's avatar
Elliot Lee committed
366 367
}

368
static void
369 370 371
gimp_paint_tool_button_release (GimpTool        *tool,
                                GimpCoords      *coords,
                                guint32          time,
372 373
                                GdkModifierType  state,
                                GimpDisplay     *display)
Elliot Lee's avatar
Elliot Lee committed
374
{
375 376
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
377
  GimpPaintCore    *core;
378
  GimpDrawable     *drawable;
Elliot Lee's avatar
Elliot Lee committed
379

380 381
  core = paint_tool->core;

382
  drawable = gimp_image_active_drawable (display->image);
Michael Natterer's avatar
Michael Natterer committed
383

384 385
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));

Elliot Lee's avatar
Elliot Lee committed
386
  /*  Let the specific painting function finish up  */
387 388
  gimp_paint_core_paint (core, drawable, paint_options,
                         GIMP_PAINT_STATE_FINISH, time);
Elliot Lee's avatar
Elliot Lee committed
389

390
  /*  resume the current selection  */
391
  gimp_image_selection_control (display->image, GIMP_SELECTION_RESUME);
392

393 394
  /*  chain up to halt the tool */
  GIMP_TOOL_CLASS (parent_class)->button_release (tool,
395
                                                  coords, time, state, display);
Elliot Lee's avatar
Elliot Lee committed
396

397 398 399 400
  if (state & GDK_BUTTON3_MASK)
    gimp_paint_core_cancel (core, drawable);
  else
    gimp_paint_core_finish (core, drawable);
401

402
  gimp_image_flush (display->image);
403 404

  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Elliot Lee's avatar
Elliot Lee committed
405 406
}

407
static void
408 409 410
gimp_paint_tool_motion (GimpTool        *tool,
                        GimpCoords      *coords,
                        guint32          time,
411 412
                        GdkModifierType  state,
                        GimpDisplay     *display)
Elliot Lee's avatar
Elliot Lee committed
413
{
414 415
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
416
  GimpPaintCore    *core;
417
  GimpDrawable     *drawable;
418
  gint              off_x, off_y;
Elliot Lee's avatar
Elliot Lee committed
419

420 421
  core = paint_tool->core;

422
  drawable = gimp_image_active_drawable (display->image);
Michael Natterer's avatar
Michael Natterer committed
423

424
  core->cur_coords = *coords;
425

426
  gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
427

428 429
  core->cur_coords.x -= off_x;
  core->cur_coords.y -= off_y;
430

431
  GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display);
432

433 434
  if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
    return;
435

436
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
437

438
  gimp_paint_core_interpolate (core, drawable, paint_options, time);
439

440 441
  gimp_projection_flush_now (display->image->projection);
  gimp_display_flush_now (display);
442

443
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
Elliot Lee's avatar
Elliot Lee committed
444 445
}

446
static void
447 448 449 450
gimp_paint_tool_modifier_key (GimpTool        *tool,
                              GdkModifierType  key,
                              gboolean         press,
                              GdkModifierType  state,
451
                              GimpDisplay     *display)
452
{
453 454
  GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
  GimpDrawTool  *draw_tool  = GIMP_DRAW_TOOL (tool);
455

456 457 458
  if (state & GDK_BUTTON1_MASK)
    return;

459 460 461
  if (key != GDK_CONTROL_MASK)
    return;

462
  if (paint_tool->pick_colors && ! paint_tool->draw_line)
463 464 465
    {
      if (press)
        {
466 467
          GimpToolInfo *info = gimp_get_tool_info (display->image->gimp,
                                                   "gimp-color-picker-tool");
468

469 470 471 472 473 474 475
          if (GIMP_IS_TOOL_INFO (info))
            {
              if (gimp_draw_tool_is_active (draw_tool))
                gimp_draw_tool_stop (draw_tool);

              gimp_color_tool_enable (GIMP_COLOR_TOOL (tool),
                                      GIMP_COLOR_OPTIONS (info->tool_options));
476

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
              switch (GIMP_COLOR_TOOL (tool)->pick_mode)
                {
                case GIMP_COLOR_PICK_MODE_FOREGROUND:
                  gimp_tool_push_status (tool, display,
                                         _("Click in any image to pick the "
                                           "foreground color."));
                  break;

                case GIMP_COLOR_PICK_MODE_BACKGROUND:
                  gimp_tool_push_status (tool, display,
                                         _("Click in any image to pick the "
                                           "background color."));
                  break;

                default:
                  break;
                }
494
            }
495 496 497
        }
      else
        {
498
          if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
499 500 501 502
            {
              gimp_tool_pop_status (tool, display);
              gimp_color_tool_disable (GIMP_COLOR_TOOL (tool));
            }
503 504 505 506 507 508 509 510
        }
    }
}

static void
gimp_paint_tool_oper_update (GimpTool        *tool,
                             GimpCoords      *coords,
                             GdkModifierType  state,
511
                             gboolean         proximity,
512
                             GimpDisplay     *display)
Elliot Lee's avatar
Elliot Lee committed
513
{
514 515 516
  GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
  GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (tool);
  GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
517
  GimpPaintCore    *core;
518
  GimpDisplayShell *shell;
519
  GimpDrawable     *drawable;
Elliot Lee's avatar
Elliot Lee committed
520

521 522
  if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (draw_tool)))
    {
523
      GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
524
                                                   proximity, display);
525 526 527
      return;
    }

528 529
  core = paint_tool->core;

530
  shell = GIMP_DISPLAY_SHELL (display->shell);
531

532
  if (gimp_draw_tool_is_active (draw_tool))
533
    gimp_draw_tool_stop (draw_tool);
534

535
  gimp_tool_pop_status (tool, display);
536

537 538 539
  if (tool->display          &&
      tool->display != display &&
      tool->display->image == display->image)
540 541 542 543 544 545 546
    {
      /*  if this is a different display, but the same image, HACK around
       *  in tool internals AFTER stopping the current draw_tool, so
       *  straight line drawing works across different views of the
       *  same image.
       */

547
      tool->display = display;
548 549
    }

550
  drawable = gimp_image_active_drawable (display->image);
551

552
  if (drawable && proximity)
553
    {
554
      if (display == tool->display && (state & GDK_SHIFT_MASK))
555
        {
556
          /*  If shift is down and this is not the first paint stroke,
557
           *  draw a line.
558 559
           */

560 561
          gdouble      dx, dy, dist;
          gchar        status_str[STATUSBAR_SIZE];
562
          gchar       *status_help;
563 564
          gint         off_x, off_y;
          gboolean     hard;
565

566
          core->cur_coords = *coords;
567

568
          gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
569

570 571
          core->cur_coords.x -= off_x;
          core->cur_coords.y -= off_y;
Sven Neumann's avatar
Sven Neumann committed
572

573 574
          hard = (gimp_paint_options_get_brush_mode (paint_options) ==
                  GIMP_BRUSH_HARD);
575
          gimp_paint_tool_round_line (core, hard, state);
576

577 578
          dx = core->cur_coords.x - core->last_coords.x;
          dy = core->cur_coords.y - core->last_coords.y;
579

580 581 582 583 584
          status_help = gimp_suggest_modifiers (paint_tool->status_line,
                                                GDK_CONTROL_MASK & ~state,
                                                NULL,
                                                _("%s for constrained angles"),
                                                NULL);
585

586
          /*  show distance in statusbar  */
587
          if (shell->unit == GIMP_UNIT_PIXEL)
588 589
            {
              dist = sqrt (SQR (dx) + SQR (dy));
590

591 592
              g_snprintf (status_str, sizeof (status_str), "%.1f %s.  %s",
                          dist, _("pixels"), status_help);
593 594 595
            }
          else
            {
596
              GimpImage *image = display->image;
597
              gchar      format_str[64];
598

599
              g_snprintf (format_str, sizeof (format_str), "%%.%df %s.  %%s",
600 601
                          _gimp_unit_get_digits (image->gimp, shell->unit),
                          _gimp_unit_get_symbol (image->gimp, shell->unit));
602

603 604 605
              dist = (_gimp_unit_get_factor (image->gimp, shell->unit) *
                      sqrt (SQR (dx / image->xresolution) +
                            SQR (dy / image->yresolution)));
606

607 608
              g_snprintf (status_str, sizeof (status_str), format_str, dist,
                          status_help);
609
            }
610
          g_free (status_help);
611
          gimp_tool_push_status (tool, display, status_str);
612

613 614 615 616
          paint_tool->draw_line = TRUE;
        }
      else
        {
617 618 619 620 621 622 623 624 625 626
          gchar           *status;
          GdkModifierType  modifiers = 0;

          /* HACK: A paint tool may set status_ctrl to NULL to indicate that
           * it ignores the Ctrl modifier (temporarily or permanently), so
           * it should not be suggested.  This is different from how
           * gimp_suggest_modifiers() would interpret this parameter. */
          if (paint_tool->status_ctrl != NULL)
            modifiers |= GDK_CONTROL_MASK;
          /* suggest drawing lines only after the first point is set */
627
          if (display == tool->display)
628 629 630 631 632 633 634
            modifiers |= GDK_SHIFT_MASK;

          status = gimp_suggest_modifiers (paint_tool->status,
                                           modifiers & ~state,
                                           _("%s for a straight line"),
                                           paint_tool->status_ctrl,
                                           NULL);
635 636
          gimp_tool_push_status (tool, display, status);
          g_free (status);
637

638 639 640
          paint_tool->draw_line = FALSE;
        }

641
      gimp_draw_tool_start (draw_tool, display);
642
    }
Michael Natterer's avatar
Michael Natterer committed
643

644
  GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
645
                                               display);
Elliot Lee's avatar
Elliot Lee committed
646 647
}

648 649
static void
gimp_paint_tool_draw (GimpDrawTool *draw_tool)
Elliot Lee's avatar
Elliot Lee committed
650
{
651
  if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (draw_tool)))
652
    {
653 654
      GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (draw_tool);
      GimpPaintCore *core       = paint_tool->core;
655

656 657
      if (paint_tool->draw_line &&
          ! gimp_tool_control_is_active (GIMP_TOOL (draw_tool)->control))
658 659 660 661 662 663
        {
          /*  Draw start target  */
          gimp_draw_tool_draw_handle (draw_tool,
                                      GIMP_HANDLE_CROSS,
                                      core->last_coords.x,
                                      core->last_coords.y,
664 665
                                      HANDLE_SIZE,
                                      HANDLE_SIZE,
666 667 668 669 670 671 672 673
                                      GTK_ANCHOR_CENTER,
                                      TRUE);

          /*  Draw end target  */
          gimp_draw_tool_draw_handle (draw_tool,
                                      GIMP_HANDLE_CROSS,
                                      core->cur_coords.x,
                                      core->cur_coords.y,
674 675
                                      HANDLE_SIZE,
                                      HANDLE_SIZE,
676 677 678 679 680 681 682 683 684 685 686
                                      GTK_ANCHOR_CENTER,
                                      TRUE);

          /*  Draw the line between the start and end coords  */
          gimp_draw_tool_draw_line (draw_tool,
                                    core->last_coords.x,
                                    core->last_coords.y,
                                    core->cur_coords.x,
                                    core->cur_coords.y,
                                    TRUE);
        }
687
    }
688 689

  GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
690
}