~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/tools/gimprectangleselecttool.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GIMP - The GNU Image Manipulation Program
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include <gtk/gtk.h>
 
22
 
 
23
#include "libgimpwidgets/gimpwidgets.h"
 
24
 
 
25
#include "tools-types.h"
 
26
 
 
27
#include "base/boundary.h"
 
28
 
 
29
#include "core/gimpchannel.h"
 
30
#include "core/gimpchannel-select.h"
 
31
#include "core/gimplayer-floating-sel.h"
 
32
#include "core/gimpimage.h"
 
33
#include "core/gimpimage-undo.h"
 
34
#include "core/gimppickable.h"
 
35
#include "core/gimp-utils.h"
 
36
#include "core/gimpundostack.h"
 
37
 
 
38
#include "widgets/gimpdialogfactory.h"
 
39
#include "widgets/gimphelp-ids.h"
 
40
#include "widgets/gimpviewabledialog.h"
 
41
#include "widgets/gimpwidgets-utils.h"
 
42
 
 
43
#include "display/gimpdisplay.h"
 
44
#include "display/gimpdisplayshell.h"
 
45
#include "display/gimpdisplayshell-transform.h"
 
46
#include "display/gimpdisplayshell-appearance.h"
 
47
 
 
48
#include "gimpselectiontool.h"
 
49
#include "gimpselectionoptions.h"
 
50
#include "gimprectangletool.h"
 
51
#include "gimprectangleoptions.h"
 
52
#include "gimprectangleselecttool.h"
 
53
#include "gimprectangleselectoptions.h"
 
54
#include "gimptoolcontrol.h"
 
55
 
 
56
#include "gimp-intl.h"
 
57
 
 
58
 
 
59
static void     gimp_rect_select_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface);
 
60
 
 
61
static GObject *gimp_rect_select_tool_constructor         (GType              type,
 
62
                                                           guint              n_params,
 
63
                                                           GObjectConstructParam *params);
 
64
static void     gimp_rect_select_tool_control             (GimpTool          *tool,
 
65
                                                           GimpToolAction     action,
 
66
                                                           GimpDisplay       *display);
 
67
static void     gimp_rect_select_tool_button_press        (GimpTool          *tool,
 
68
                                                           GimpCoords        *coords,
 
69
                                                           guint32            time,
 
70
                                                           GdkModifierType    state,
 
71
                                                           GimpDisplay       *display);
 
72
static void     gimp_rect_select_tool_button_release      (GimpTool          *tool,
 
73
                                                           GimpCoords        *coords,
 
74
                                                           guint32            time,
 
75
                                                           GdkModifierType    state,
 
76
                                                           GimpButtonReleaseType release_type,
 
77
                                                           GimpDisplay       *display);
 
78
static void     gimp_rect_select_tool_active_modifier_key (GimpTool          *tool,
 
79
                                                           GdkModifierType    key,
 
80
                                                           gboolean           press,
 
81
                                                           GdkModifierType    state,
 
82
                                                           GimpDisplay       *display);
 
83
static gboolean gimp_rect_select_tool_key_press           (GimpTool          *tool,
 
84
                                                           GdkEventKey       *kevent,
 
85
                                                           GimpDisplay       *display);
 
86
static void     gimp_rect_select_tool_oper_update         (GimpTool          *tool,
 
87
                                                           GimpCoords        *coords,
 
88
                                                           GdkModifierType    state,
 
89
                                                           gboolean           proximity,
 
90
                                                           GimpDisplay       *display);
 
91
static void     gimp_rect_select_tool_cursor_update       (GimpTool          *tool,
 
92
                                                           GimpCoords        *coords,
 
93
                                                           GdkModifierType    state,
 
94
                                                           GimpDisplay       *display);
 
95
static void     gimp_rect_select_tool_draw                (GimpDrawTool      *draw_tool);
 
96
static gboolean gimp_rect_select_tool_select              (GimpRectangleTool *rect_tool,
 
97
                                                           gint               x,
 
98
                                                           gint               y,
 
99
                                                           gint               w,
 
100
                                                           gint               h);
 
101
static gboolean gimp_rect_select_tool_execute             (GimpRectangleTool *rect_tool,
 
102
                                                           gint               x,
 
103
                                                           gint               y,
 
104
                                                           gint               w,
 
105
                                                           gint               h);
 
106
static void     gimp_rect_select_tool_cancel              (GimpRectangleTool *rect_tool);
 
107
static gboolean gimp_rect_select_tool_rectangle_changed   (GimpRectangleTool *rect_tool);
 
108
static void     gimp_rect_select_tool_real_select         (GimpRectSelectTool *rect_select,
 
109
                                                           GimpChannelOps      operation,
 
110
                                                           gint                x,
 
111
                                                           gint                y,
 
112
                                                           gint                w,
 
113
                                                           gint                h);
 
114
 
 
115
static void    gimp_rect_select_tool_round_corners_notify (GimpRectSelectOptions *options,
 
116
                                                           GParamSpec            *pspec,
 
117
                                                           GimpRectSelectTool    *rect_sel);
 
118
 
 
119
 
 
120
G_DEFINE_TYPE_WITH_CODE (GimpRectSelectTool, gimp_rect_select_tool,
 
121
                         GIMP_TYPE_SELECTION_TOOL,
 
122
                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_RECTANGLE_TOOL,
 
123
                                                gimp_rect_select_tool_rectangle_tool_iface_init))
 
124
 
 
125
#define parent_class gimp_rect_select_tool_parent_class
 
126
 
 
127
 
 
128
void
 
129
gimp_rect_select_tool_register (GimpToolRegisterCallback  callback,
 
130
                                gpointer                  data)
 
131
{
 
132
  (* callback) (GIMP_TYPE_RECT_SELECT_TOOL,
 
133
                GIMP_TYPE_RECT_SELECT_OPTIONS,
 
134
                gimp_rect_select_options_gui,
 
135
                0,
 
136
                "gimp-rect-select-tool",
 
137
                _("Rectangle Select"),
 
138
                _("Rectangle Select Tool: Select a rectangular region"),
 
139
                N_("_Rectangle Select"), "R",
 
140
                NULL, GIMP_HELP_TOOL_RECT_SELECT,
 
141
                GIMP_STOCK_TOOL_RECT_SELECT,
 
142
                data);
 
143
}
 
144
 
 
145
static void
 
146
gimp_rect_select_tool_class_init (GimpRectSelectToolClass *klass)
 
147
{
 
148
  GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
 
149
  GimpToolClass     *tool_class      = GIMP_TOOL_CLASS (klass);
 
150
  GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
 
151
 
 
152
  object_class->constructor       = gimp_rect_select_tool_constructor;
 
153
  object_class->set_property      = gimp_rectangle_tool_set_property;
 
154
  object_class->get_property      = gimp_rectangle_tool_get_property;
 
155
 
 
156
  gimp_rectangle_tool_install_properties (object_class);
 
157
 
 
158
  tool_class->control             = gimp_rect_select_tool_control;
 
159
  tool_class->button_press        = gimp_rect_select_tool_button_press;
 
160
  tool_class->button_release      = gimp_rect_select_tool_button_release;
 
161
  tool_class->motion              = gimp_rectangle_tool_motion;
 
162
  tool_class->key_press           = gimp_rect_select_tool_key_press;
 
163
  tool_class->active_modifier_key = gimp_rect_select_tool_active_modifier_key;
 
164
  tool_class->oper_update         = gimp_rect_select_tool_oper_update;
 
165
  tool_class->cursor_update       = gimp_rect_select_tool_cursor_update;
 
166
 
 
167
  draw_tool_class->draw           = gimp_rect_select_tool_draw;
 
168
 
 
169
  klass->select                   = gimp_rect_select_tool_real_select;
 
170
}
 
171
 
 
172
static void
 
173
gimp_rect_select_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface)
 
174
{
 
175
  iface->execute           = gimp_rect_select_tool_execute;
 
176
  iface->cancel            = gimp_rect_select_tool_cancel;
 
177
  iface->rectangle_changed = gimp_rect_select_tool_rectangle_changed;
 
178
}
 
179
 
 
180
static void
 
181
gimp_rect_select_tool_init (GimpRectSelectTool *rect_select)
 
182
{
 
183
  GimpTool *tool = GIMP_TOOL (rect_select);
 
184
 
 
185
  gimp_tool_control_set_wants_click (tool->control, TRUE);
 
186
  gimp_tool_control_set_tool_cursor (tool->control,
 
187
                                     GIMP_TOOL_CURSOR_RECT_SELECT);
 
188
  gimp_tool_control_set_dirty_mask  (tool->control,
 
189
                                     GIMP_DIRTY_IMAGE_SIZE |
 
190
                                     GIMP_DIRTY_SELECTION);
 
191
 
 
192
  rect_select->undo = NULL;
 
193
  rect_select->redo = NULL;
 
194
}
 
195
 
 
196
static GObject *
 
197
gimp_rect_select_tool_constructor (GType                  type,
 
198
                                   guint                  n_params,
 
199
                                   GObjectConstructParam *params)
 
200
{
 
201
  GObject               *object;
 
202
  GimpRectSelectTool    *rect_sel;
 
203
  GimpRectSelectOptions *options;
 
204
 
 
205
  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
206
 
 
207
  gimp_rectangle_tool_constructor (object);
 
208
 
 
209
  rect_sel = GIMP_RECT_SELECT_TOOL (object);
 
210
  options  = GIMP_RECT_SELECT_TOOL_GET_OPTIONS (rect_sel);
 
211
 
 
212
  rect_sel->round_corners = options->round_corners;
 
213
  rect_sel->corner_radius = options->corner_radius;
 
214
 
 
215
  g_signal_connect_object (options, "notify::round-corners",
 
216
                           G_CALLBACK (gimp_rect_select_tool_round_corners_notify),
 
217
                           object, 0);
 
218
  g_signal_connect_object (options, "notify::corner-radius",
 
219
                           G_CALLBACK (gimp_rect_select_tool_round_corners_notify),
 
220
                           object, 0);
 
221
 
 
222
  return object;
 
223
}
 
224
 
 
225
static void
 
226
gimp_rect_select_tool_control (GimpTool       *tool,
 
227
                               GimpToolAction  action,
 
228
                               GimpDisplay    *display)
 
229
{
 
230
  gimp_rectangle_tool_control (tool, action, display);
 
231
 
 
232
  GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
 
233
}
 
234
 
 
235
static void
 
236
gimp_rect_select_tool_draw (GimpDrawTool *draw_tool)
 
237
{
 
238
  GimpRectSelectTool *rect_sel = GIMP_RECT_SELECT_TOOL (draw_tool);
 
239
 
 
240
  gimp_rectangle_tool_draw (draw_tool);
 
241
 
 
242
  if (rect_sel->round_corners)
 
243
    {
 
244
      gint    x1, y1, x2, y2;
 
245
      gdouble radius;
 
246
      gint    square_size;
 
247
 
 
248
      g_object_get (rect_sel,
 
249
                    "x1", &x1,
 
250
                    "y1", &y1,
 
251
                    "x2", &x2,
 
252
                    "y2", &y2,
 
253
                    NULL);
 
254
 
 
255
      radius = MIN (rect_sel->corner_radius,
 
256
                    MIN ((x2 - x1) / 2.0, (y2 - y1) / 2.0));
 
257
 
 
258
      square_size = (int) (radius * 2);
 
259
 
 
260
      gimp_draw_tool_draw_arc (draw_tool, FALSE,
 
261
                               x1, y1,
 
262
                               square_size, square_size,
 
263
                               90 * 64,  90 * 64,
 
264
                               FALSE);
 
265
 
 
266
      gimp_draw_tool_draw_arc (draw_tool, FALSE,
 
267
                               x2 - square_size, y1,
 
268
                               square_size, square_size,
 
269
                               0,        90 * 64,
 
270
                               FALSE);
 
271
 
 
272
      gimp_draw_tool_draw_arc (draw_tool, FALSE,
 
273
                               x2 - square_size, y2 - square_size,
 
274
                               square_size, square_size,
 
275
                               270 * 64, 90 * 64,
 
276
                               FALSE);
 
277
 
 
278
      gimp_draw_tool_draw_arc (draw_tool, FALSE,
 
279
                               x1, y2 - square_size,
 
280
                               square_size, square_size,
 
281
                               180 * 64, 90 * 64,
 
282
                               FALSE);
 
283
    }
 
284
}
 
285
 
 
286
static void
 
287
gimp_rect_select_tool_button_press (GimpTool        *tool,
 
288
                                    GimpCoords      *coords,
 
289
                                    guint32          time,
 
290
                                    GdkModifierType  state,
 
291
                                    GimpDisplay     *display)
 
292
{
 
293
  GimpRectangleTool     *rectangle   = GIMP_RECTANGLE_TOOL (tool);
 
294
  GimpRectSelectTool    *rect_select = GIMP_RECT_SELECT_TOOL (tool);
 
295
  GimpRectangleFunction  function;
 
296
 
 
297
  if (tool->display && display != tool->display)
 
298
    gimp_rectangle_tool_cancel (GIMP_RECTANGLE_TOOL (tool));
 
299
 
 
300
  function = gimp_rectangle_tool_get_function (rectangle);
 
301
 
 
302
  rect_select->saved_show_selection
 
303
    = gimp_display_shell_get_show_selection (GIMP_DISPLAY_SHELL (display->shell));
 
304
 
 
305
  if (function == RECT_INACTIVE)
 
306
    {
 
307
      GimpDisplay *old_display;
 
308
      gboolean     edit_started;
 
309
 
 
310
      old_display = tool->display;
 
311
      tool->display = display;
 
312
      gimp_tool_control_activate (tool->control);
 
313
 
 
314
      edit_started = gimp_selection_tool_start_edit (GIMP_SELECTION_TOOL (tool),
 
315
                                                     coords);
 
316
 
 
317
      if (gimp_tool_control_is_active (tool->control))
 
318
        gimp_tool_control_halt (tool->control);
 
319
      tool->display = old_display;
 
320
 
 
321
      if (edit_started)
 
322
        return;
 
323
    }
 
324
 
 
325
  /* if the shift or ctrl keys are down, we don't want to adjust, we
 
326
   * want to create a new rectangle, regardless of pointer loc */
 
327
  if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
 
328
    gimp_rectangle_tool_set_function (rectangle, RECT_CREATING);
 
329
 
 
330
  gimp_rectangle_tool_button_press (tool, coords, time, state, display);
 
331
 
 
332
  /* if we have an existing rectangle in the current display, then
 
333
   * we have already "executed", and need to undo at this point,
 
334
   * unless the user has done something in the meantime
 
335
   */
 
336
  function = gimp_rectangle_tool_get_function (rectangle);
 
337
 
 
338
  if (function == RECT_CREATING)
 
339
    {
 
340
      rect_select->use_saved_op = FALSE;
 
341
    }
 
342
  else
 
343
    {
 
344
      GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
 
345
      GimpImage            *image   = tool->display->image;
 
346
      GimpUndo             *undo;
 
347
      GimpChannelOps        operation;
 
348
 
 
349
      if (rect_select->use_saved_op)
 
350
        operation = rect_select->operation;
 
351
      else
 
352
        operation = options->operation;
 
353
 
 
354
      undo = gimp_undo_stack_peek (image->undo_stack);
 
355
 
 
356
      if (undo && rect_select->undo == undo)
 
357
        {
 
358
          /* prevent this change from halting the tool */
 
359
          gimp_tool_control_set_preserve (tool->control, TRUE);
 
360
 
 
361
          gimp_image_undo (image);
 
362
 
 
363
          gimp_tool_control_set_preserve (tool->control, FALSE);
 
364
 
 
365
          /* we will need to redo if the user cancels or executes */
 
366
          rect_select->redo = gimp_undo_stack_peek (image->redo_stack);
 
367
        }
 
368
 
 
369
      /* if the operation is "Replace", turn off the marching ants,
 
370
         because they are confusing */
 
371
      if (operation == GIMP_CHANNEL_OP_REPLACE)
 
372
        gimp_display_shell_set_show_selection (GIMP_DISPLAY_SHELL (display->shell),
 
373
                                               FALSE);
 
374
    }
 
375
 
 
376
  rect_select->undo = NULL;
 
377
}
 
378
 
 
379
static void
 
380
gimp_rect_select_tool_button_release (GimpTool              *tool,
 
381
                                      GimpCoords            *coords,
 
382
                                      guint32                time,
 
383
                                      GdkModifierType        state,
 
384
                                      GimpButtonReleaseType  release_type,
 
385
                                      GimpDisplay           *display)
 
386
{
 
387
  GimpRectSelectTool *rect_select = GIMP_RECT_SELECT_TOOL (tool);
 
388
 
 
389
  gimp_tool_pop_status (tool, display);
 
390
  gimp_display_shell_set_show_selection (GIMP_DISPLAY_SHELL (display->shell),
 
391
                                         rect_select->saved_show_selection);
 
392
 
 
393
  /*
 
394
   * if the user has not moved the mouse, we need to redo the operation
 
395
   * that was undone on button press.
 
396
   */
 
397
  if (release_type == GIMP_BUTTON_RELEASE_CLICK)
 
398
    {
 
399
      GimpImage *image = tool->display->image;
 
400
      GimpUndo  *redo;
 
401
 
 
402
      redo = gimp_undo_stack_peek (image->redo_stack);
 
403
 
 
404
      if (redo && rect_select->redo == redo)
 
405
        {
 
406
          /* prevent this from halting the tool */
 
407
          gimp_tool_control_set_preserve (tool->control, TRUE);
 
408
 
 
409
          gimp_image_redo (image);
 
410
          rect_select->redo = NULL;
 
411
 
 
412
          gimp_tool_control_set_preserve (tool->control, FALSE);
 
413
        }
 
414
    }
 
415
 
 
416
  gimp_rectangle_tool_button_release (tool, coords, time, state, release_type,
 
417
                                      display);
 
418
 
 
419
  if (release_type == GIMP_BUTTON_RELEASE_CANCEL)
 
420
    {
 
421
      if (rect_select->redo)
 
422
        {
 
423
          /* prevent this from halting the tool */
 
424
          gimp_tool_control_set_preserve (tool->control, TRUE);
 
425
 
 
426
          gimp_image_redo (tool->display->image);
 
427
 
 
428
          gimp_tool_control_set_preserve (tool->control, FALSE);
 
429
        }
 
430
 
 
431
      rect_select->use_saved_op = TRUE;  /* is this correct? */
 
432
    }
 
433
 
 
434
  rect_select->redo = NULL;
 
435
}
 
436
 
 
437
static void
 
438
gimp_rect_select_tool_active_modifier_key (GimpTool        *tool,
 
439
                                           GdkModifierType  key,
 
440
                                           gboolean         press,
 
441
                                           GdkModifierType  state,
 
442
                                           GimpDisplay     *display)
 
443
{
 
444
  GIMP_TOOL_CLASS (parent_class)->active_modifier_key (tool, key, press, state,
 
445
                                                       display);
 
446
 
 
447
  gimp_rectangle_tool_active_modifier_key (tool, key, press, state, display);
 
448
}
 
449
 
 
450
static gboolean
 
451
gimp_rect_select_tool_key_press (GimpTool    *tool,
 
452
                                 GdkEventKey *kevent,
 
453
                                 GimpDisplay *display)
 
454
{
 
455
  return (gimp_rectangle_tool_key_press (tool, kevent, display) ||
 
456
          gimp_edit_selection_tool_key_press (tool, kevent, display));
 
457
}
 
458
 
 
459
static void
 
460
gimp_rect_select_tool_oper_update (GimpTool        *tool,
 
461
                                   GimpCoords      *coords,
 
462
                                   GdkModifierType  state,
 
463
                                   gboolean         proximity,
 
464
                                   GimpDisplay     *display)
 
465
{
 
466
  GimpRectangleFunction function;
 
467
 
 
468
  gimp_rectangle_tool_oper_update (tool, coords, state, proximity, display);
 
469
 
 
470
  function = gimp_rectangle_tool_get_function (GIMP_RECTANGLE_TOOL (tool));
 
471
 
 
472
  if (function == RECT_INACTIVE)
 
473
    GIMP_SELECTION_TOOL (tool)->allow_move = TRUE;
 
474
  else
 
475
    GIMP_SELECTION_TOOL (tool)->allow_move = FALSE;
 
476
 
 
477
  GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
 
478
                                               display);
 
479
}
 
480
 
 
481
static void
 
482
gimp_rect_select_tool_cursor_update (GimpTool        *tool,
 
483
                                     GimpCoords      *coords,
 
484
                                     GdkModifierType  state,
 
485
                                     GimpDisplay     *display)
 
486
{
 
487
  gimp_rectangle_tool_cursor_update (tool, coords, state, display);
 
488
 
 
489
  /* override the previous if shift or ctrl are down */
 
490
  if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
 
491
    gimp_tool_control_set_cursor (tool->control, GIMP_CURSOR_CROSSHAIR_SMALL);
 
492
 
 
493
  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
 
494
}
 
495
 
 
496
 
 
497
static gboolean
 
498
gimp_rect_select_tool_select (GimpRectangleTool *rectangle,
 
499
                              gint               x,
 
500
                              gint               y,
 
501
                              gint               w,
 
502
                              gint               h)
 
503
{
 
504
  GimpTool             *tool        = GIMP_TOOL (rectangle);
 
505
  GimpRectSelectTool   *rect_select = GIMP_RECT_SELECT_TOOL (rectangle);
 
506
  GimpSelectionOptions *options     = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
 
507
  GimpImage            *image;
 
508
  gboolean              rectangle_exists;
 
509
  GimpChannelOps        operation;
 
510
 
 
511
  gimp_tool_pop_status (tool, tool->display);
 
512
 
 
513
  image = tool->display->image;
 
514
 
 
515
  rectangle_exists = (x <= image->width && y <= image->height &&
 
516
                      x + w >= 0 && y + h >= 0 &&
 
517
                      w > 0 && h > 0);
 
518
 
 
519
  if (rect_select->use_saved_op)
 
520
    operation = rect_select->operation;
 
521
  else
 
522
    operation = options->operation;
 
523
 
 
524
  /* if rectangle exists, turn it into a selection */
 
525
  if (rectangle_exists)
 
526
    GIMP_RECT_SELECT_TOOL_GET_CLASS (rect_select)->select (rect_select,
 
527
                                                           operation,
 
528
                                                           x, y, w, h);
 
529
 
 
530
  return rectangle_exists;
 
531
}
 
532
 
 
533
static void
 
534
gimp_rect_select_tool_real_select (GimpRectSelectTool *rect_select,
 
535
                                   GimpChannelOps      operation,
 
536
                                   gint                x,
 
537
                                   gint                y,
 
538
                                   gint                w,
 
539
                                   gint                h)
 
540
{
 
541
  GimpTool              *tool = GIMP_TOOL (rect_select);
 
542
  GimpSelectionOptions  *options;
 
543
  GimpRectSelectOptions *rect_select_options;
 
544
 
 
545
  options             = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
 
546
  rect_select_options = GIMP_RECT_SELECT_TOOL_GET_OPTIONS (tool);
 
547
 
 
548
  if (rect_select_options->round_corners)
 
549
    {
 
550
      /* To prevent elliptification of the rect, we must cap the corner radius */
 
551
      gdouble radius = MIN (rect_select_options->corner_radius,
 
552
                            MIN (w / 2.0, h / 2.0));
 
553
 
 
554
      gimp_channel_select_round_rect (gimp_image_get_mask (tool->display->image),
 
555
                                      x, y, w, h,
 
556
                                      radius, radius,
 
557
                                      operation,
 
558
                                      options->antialias,
 
559
                                      options->feather,
 
560
                                      options->feather_radius,
 
561
                                      options->feather_radius,
 
562
                                      TRUE);
 
563
    }
 
564
  else
 
565
    {
 
566
      gimp_channel_select_rectangle (gimp_image_get_mask (tool->display->image),
 
567
                                     x, y, w, h,
 
568
                                     operation,
 
569
                                     options->feather,
 
570
                                     options->feather_radius,
 
571
                                     options->feather_radius,
 
572
                                     TRUE);
 
573
    }
 
574
}
 
575
 
 
576
/*
 
577
 * This function is called if the user clicks and releases the left
 
578
 * button without moving it.  There are the things we might want
 
579
 * to do here:
 
580
 * 1) If there is an existing rectangle and we are inside it, we
 
581
 *    convert it into a selection.
 
582
 * 2) If there is an existing rectangle and we are outside it, we
 
583
 *    clear it.
 
584
 * 3) If there is no rectangle and there is a floating selection,
 
585
 *    we anchor it.
 
586
 * 4) If there is no rectangle and we are inside the selection, we
 
587
 *    create a rectangle from the selection bounds.
 
588
 * 5) If there is no rectangle and we are outside the selection,
 
589
 *    we clear the selection.
 
590
 */
 
591
static gboolean
 
592
gimp_rect_select_tool_execute (GimpRectangleTool *rectangle,
 
593
                               gint               x,
 
594
                               gint               y,
 
595
                               gint               w,
 
596
                               gint               h)
 
597
{
 
598
  if (w == 0 && h == 0)
 
599
    {
 
600
      GimpImage   *image     = GIMP_TOOL (rectangle)->display->image;
 
601
      GimpChannel *selection = gimp_image_get_mask (image);
 
602
      gint         pressx;
 
603
      gint         pressy;
 
604
 
 
605
      if (gimp_image_floating_sel (image))
 
606
        {
 
607
          floating_sel_anchor (gimp_image_floating_sel (image));
 
608
          gimp_image_flush (image);
 
609
          return TRUE;
 
610
        }
 
611
 
 
612
      gimp_rectangle_tool_get_press_coords (rectangle, &pressx, &pressy);
 
613
 
 
614
      /*  if the click was inside the marching ants  */
 
615
      if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (selection),
 
616
                                        pressx, pressy) > BOUNDARY_HALF_WAY)
 
617
        {
 
618
          gint x1, y1, x2, y2;
 
619
 
 
620
          if (gimp_channel_bounds (selection, &x1, &y1, &x2, &y2))
 
621
            {
 
622
              g_object_set (rectangle,
 
623
                            "x1", x1,
 
624
                            "y1", y1,
 
625
                            "x2", x2,
 
626
                            "y2", y2,
 
627
                            NULL);
 
628
            }
 
629
 
 
630
          gimp_rectangle_tool_set_function (rectangle, RECT_MOVING);
 
631
 
 
632
          return FALSE;
 
633
        }
 
634
      else
 
635
        {
 
636
          GimpTool *tool = GIMP_TOOL (rectangle);
 
637
 
 
638
          /* prevent this change from halting the tool */
 
639
          gimp_tool_control_set_preserve (tool->control, TRUE);
 
640
 
 
641
          /* otherwise clear the selection */
 
642
          gimp_channel_clear (selection, NULL, TRUE);
 
643
          gimp_image_flush (image);
 
644
 
 
645
          gimp_tool_control_set_preserve (tool->control, FALSE);
 
646
        }
 
647
    }
 
648
 
 
649
  return TRUE;
 
650
}
 
651
 
 
652
static void
 
653
gimp_rect_select_tool_cancel (GimpRectangleTool *rectangle)
 
654
{
 
655
  GimpTool           *tool        = GIMP_TOOL (rectangle);
 
656
  GimpRectSelectTool *rect_select = GIMP_RECT_SELECT_TOOL (rectangle);
 
657
 
 
658
  if (tool->display)
 
659
    {
 
660
      GimpImage *image = tool->display->image;
 
661
      GimpUndo  *undo;
 
662
 
 
663
      /* if we have an existing rectangle in the current display, then
 
664
       * we have already "executed", and need to undo at this point,
 
665
       * unless the user has done something in the meantime
 
666
       */
 
667
      undo = gimp_undo_stack_peek (image->undo_stack);
 
668
 
 
669
      if (undo && rect_select->undo == undo)
 
670
        {
 
671
          /* prevent this change from halting the tool */
 
672
          gimp_tool_control_set_preserve (tool->control, TRUE);
 
673
 
 
674
          gimp_image_undo (image);
 
675
          gimp_image_flush (image);
 
676
 
 
677
          gimp_tool_control_set_preserve (tool->control, FALSE);
 
678
        }
 
679
    }
 
680
 
 
681
  rect_select->undo = NULL;
 
682
  rect_select->redo = NULL;
 
683
}
 
684
 
 
685
static gboolean
 
686
gimp_rect_select_tool_rectangle_changed (GimpRectangleTool *rectangle)
 
687
{
 
688
  GimpTool *tool = GIMP_TOOL (rectangle);
 
689
 
 
690
  /* prevent change in selection from halting the tool */
 
691
  gimp_tool_control_set_preserve (tool->control, TRUE);
 
692
 
 
693
  if (tool->display && ! gimp_tool_control_is_active (tool->control))
 
694
    {
 
695
      GimpRectSelectTool *rect_select = GIMP_RECT_SELECT_TOOL (tool);
 
696
      GimpImage          *image       = tool->display->image;
 
697
      GimpUndo           *undo;
 
698
      gint                x1, y1, x2, y2;
 
699
 
 
700
      /* if we got here via button release, we have already undone the
 
701
       * previous operation.  But if we got here by some other means,
 
702
       * we need to undo it now.
 
703
       */
 
704
      undo = gimp_undo_stack_peek (image->undo_stack);
 
705
 
 
706
      if (undo && rect_select->undo == undo)
 
707
        {
 
708
          gimp_image_undo (image);
 
709
          rect_select->undo = NULL;
 
710
        }
 
711
 
 
712
      g_object_get (rectangle,
 
713
                    "x1", &x1,
 
714
                    "y1", &y1,
 
715
                    "x2", &x2,
 
716
                    "y2", &y2,
 
717
                    NULL);
 
718
 
 
719
      if (gimp_rect_select_tool_select (rectangle, x1, y1, x2 - x1, y2 - y1))
 
720
        {
 
721
          /* save the undo that we got when executing, but only if
 
722
           * we actually selected something
 
723
           */
 
724
          rect_select->undo = gimp_undo_stack_peek (image->undo_stack);
 
725
          rect_select->redo = NULL;
 
726
        }
 
727
 
 
728
      if (! rect_select->use_saved_op)
 
729
        {
 
730
          GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
 
731
 
 
732
          /* remember the operation now in case we modify the rectangle */
 
733
          rect_select->operation    = options->operation;
 
734
          rect_select->use_saved_op = TRUE;
 
735
        }
 
736
 
 
737
      gimp_image_flush (image);
 
738
    }
 
739
 
 
740
  gimp_tool_control_set_preserve (tool->control, FALSE);
 
741
 
 
742
  return TRUE;
 
743
}
 
744
 
 
745
static void
 
746
gimp_rect_select_tool_round_corners_notify (GimpRectSelectOptions *options,
 
747
                                            GParamSpec            *pspec,
 
748
                                            GimpRectSelectTool    *rect_sel)
 
749
{
 
750
  gimp_draw_tool_pause (GIMP_DRAW_TOOL (rect_sel));
 
751
 
 
752
  rect_sel->round_corners = options->round_corners;
 
753
  rect_sel->corner_radius = options->corner_radius;
 
754
 
 
755
  gimp_draw_tool_resume (GIMP_DRAW_TOOL (rect_sel));
 
756
}