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

« back to all changes in this revision

Viewing changes to app/tools/gimpselectiontool.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
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
27
27
 
28
28
#include "core/gimpchannel.h"
29
29
#include "core/gimpimage.h"
30
 
#include "core/gimptoolinfo.h"
 
30
#include "core/gimppickable.h"
31
31
 
32
32
#include "display/gimpdisplay.h"
33
33
 
 
34
#include "widgets/gimpwidgets-utils.h"
 
35
 
34
36
#include "gimpeditselectiontool.h"
35
37
#include "gimpselectiontool.h"
36
38
#include "gimpselectionoptions.h"
37
39
#include "gimptoolcontrol.h"
38
40
 
 
41
#include "gimp-intl.h"
39
42
 
40
 
static void   gimp_selection_tool_class_init (GimpSelectionToolClass *klass);
41
 
static void   gimp_selection_tool_init       (GimpSelectionTool      *sel_tool);
42
43
 
43
44
static void   gimp_selection_tool_modifier_key  (GimpTool        *tool,
44
45
                                                 GdkModifierType  key,
45
46
                                                 gboolean         press,
46
47
                                                 GdkModifierType  state,
47
 
                                                 GimpDisplay     *gdisp);
 
48
                                                 GimpDisplay     *display);
48
49
static void   gimp_selection_tool_oper_update   (GimpTool        *tool,
49
50
                                                 GimpCoords      *coords,
50
51
                                                 GdkModifierType  state,
51
 
                                                 GimpDisplay     *gdisp);
 
52
                                                 gboolean         proximity,
 
53
                                                 GimpDisplay     *display);
52
54
static void   gimp_selection_tool_cursor_update (GimpTool        *tool,
53
55
                                                 GimpCoords      *coords,
54
56
                                                 GdkModifierType  state,
55
 
                                                 GimpDisplay     *gdisp);
56
 
 
57
 
 
58
 
static GimpDrawToolClass *parent_class = NULL;
59
 
 
60
 
 
61
 
GType
62
 
gimp_selection_tool_get_type (void)
63
 
{
64
 
  static GType tool_type = 0;
65
 
 
66
 
  if (! tool_type)
67
 
    {
68
 
      static const GTypeInfo tool_info =
69
 
      {
70
 
        sizeof (GimpSelectionToolClass),
71
 
        (GBaseInitFunc) NULL,
72
 
        (GBaseFinalizeFunc) NULL,
73
 
        (GClassInitFunc) gimp_selection_tool_class_init,
74
 
        NULL,           /* class_finalize */
75
 
        NULL,           /* class_data     */
76
 
        sizeof (GimpSelectionTool),
77
 
        0,              /* n_preallocs    */
78
 
        (GInstanceInitFunc) gimp_selection_tool_init,
79
 
      };
80
 
 
81
 
      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
82
 
                                          "GimpSelectionTool",
83
 
                                          &tool_info, 0);
84
 
    }
85
 
 
86
 
  return tool_type;
87
 
}
 
57
                                                 GimpDisplay     *display);
 
58
 
 
59
 
 
60
G_DEFINE_TYPE (GimpSelectionTool, gimp_selection_tool, GIMP_TYPE_DRAW_TOOL)
 
61
 
 
62
#define parent_class gimp_selection_tool_parent_class
 
63
 
88
64
 
89
65
static void
90
66
gimp_selection_tool_class_init (GimpSelectionToolClass *klass)
91
67
{
92
68
  GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
93
69
 
94
 
  parent_class = g_type_class_peek_parent (klass);
95
 
 
96
70
  tool_class->modifier_key  = gimp_selection_tool_modifier_key;
97
71
  tool_class->key_press     = gimp_edit_selection_tool_key_press;
98
72
  tool_class->oper_update   = gimp_selection_tool_oper_update;
102
76
static void
103
77
gimp_selection_tool_init (GimpSelectionTool *selection_tool)
104
78
{
105
 
  selection_tool->op       = SELECTION_REPLACE;
106
 
  selection_tool->saved_op = SELECTION_REPLACE;
 
79
  selection_tool->function        = SELECTION_SELECT;
 
80
  selection_tool->saved_operation = GIMP_CHANNEL_OP_REPLACE;
 
81
 
 
82
  selection_tool->allow_move      = TRUE;
107
83
}
108
84
 
109
85
static void
111
87
                                  GdkModifierType  key,
112
88
                                  gboolean         press,
113
89
                                  GdkModifierType  state,
114
 
                                  GimpDisplay     *gdisp)
 
90
                                  GimpDisplay     *display)
115
91
{
116
92
  GimpSelectionTool    *selection_tool = GIMP_SELECTION_TOOL (tool);
117
93
  GimpSelectionOptions *options;
118
94
 
119
 
  options = GIMP_SELECTION_OPTIONS (tool->tool_info->tool_options);
 
95
  options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
120
96
 
121
 
  if (key == GDK_SHIFT_MASK || key == GDK_CONTROL_MASK)
 
97
  if (key == GDK_SHIFT_MASK   ||
 
98
      key == GDK_CONTROL_MASK ||
 
99
      key == GDK_MOD1_MASK)
122
100
    {
123
 
      SelectOps button_op = options->operation;
 
101
      GimpChannelOps button_op = options->operation;
124
102
 
125
103
      if (press)
126
104
        {
127
 
          if (key == (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)))
 
105
          if (key == (state & (GDK_SHIFT_MASK   |
 
106
                               GDK_CONTROL_MASK |
 
107
                               GDK_MOD1_MASK)))
128
108
            {
129
109
              /*  first modifier pressed  */
130
110
 
131
 
              selection_tool->saved_op = options->operation;
 
111
              selection_tool->saved_operation = options->operation;
132
112
            }
133
113
        }
134
114
      else
135
115
        {
136
 
          if (! (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)))
 
116
          if (! (state & (GDK_SHIFT_MASK   |
 
117
                          GDK_CONTROL_MASK |
 
118
                          GDK_MOD1_MASK)))
137
119
            {
138
120
              /*  last modifier released  */
139
121
 
140
 
              button_op = selection_tool->saved_op;
 
122
              button_op = selection_tool->saved_operation;
141
123
            }
142
124
        }
143
125
 
144
 
      if ((state & GDK_CONTROL_MASK) && (state & GDK_SHIFT_MASK))
145
 
        {
146
 
          button_op = SELECTION_INTERSECT;
 
126
      if (state & GDK_MOD1_MASK)
 
127
        {
 
128
          /*  if alt is down, pretend that neither
 
129
           *  shift nor control are down
 
130
           */
 
131
          button_op = selection_tool->saved_operation;
 
132
        }
 
133
      else if ((state & GDK_CONTROL_MASK) && (state & GDK_SHIFT_MASK))
 
134
        {
 
135
          button_op = GIMP_CHANNEL_OP_INTERSECT;
147
136
        }
148
137
      else if (state & GDK_SHIFT_MASK)
149
138
        {
150
 
          button_op = SELECTION_ADD;
 
139
          button_op = GIMP_CHANNEL_OP_ADD;
151
140
        }
152
141
      else if (state & GDK_CONTROL_MASK)
153
142
        {
154
 
          button_op = SELECTION_SUBTRACT;
 
143
          button_op = GIMP_CHANNEL_OP_SUBTRACT;
155
144
        }
156
145
 
157
146
      if (button_op != options->operation)
165
154
gimp_selection_tool_oper_update (GimpTool        *tool,
166
155
                                 GimpCoords      *coords,
167
156
                                 GdkModifierType  state,
168
 
                                 GimpDisplay     *gdisp)
 
157
                                 gboolean         proximity,
 
158
                                 GimpDisplay     *display)
169
159
{
170
160
  GimpSelectionTool    *selection_tool = GIMP_SELECTION_TOOL (tool);
171
161
  GimpSelectionOptions *options;
172
162
  GimpChannel          *selection;
 
163
  GimpDrawable         *drawable;
173
164
  GimpLayer            *layer;
174
165
  GimpLayer            *floating_sel;
175
166
  gboolean              move_layer        = FALSE;
176
167
  gboolean              move_floating_sel = FALSE;
177
 
 
178
 
  options = GIMP_SELECTION_OPTIONS (tool->tool_info->tool_options);
179
 
 
180
 
  selection    = gimp_image_get_mask (gdisp->gimage);
181
 
  layer        = gimp_image_pick_correlate_layer (gdisp->gimage,
 
168
  gboolean              selection_empty;
 
169
 
 
170
  options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
 
171
 
 
172
  selection    = gimp_image_get_mask (display->image);
 
173
  drawable     = gimp_image_active_drawable (display->image);
 
174
  layer        = gimp_image_pick_correlate_layer (display->image,
182
175
                                                  coords->x, coords->y);
183
 
  floating_sel = gimp_image_floating_sel (gdisp->gimage);
 
176
  floating_sel = gimp_image_floating_sel (display->image);
184
177
 
185
 
  if (layer)
 
178
  if (drawable)
186
179
    {
187
180
      if (floating_sel)
188
181
        {
189
182
          if (layer == floating_sel)
190
183
            move_floating_sel = TRUE;
191
184
        }
192
 
      else if (gimp_channel_value (selection, coords->x, coords->y))
 
185
      else if (gimp_drawable_mask_intersect (drawable,
 
186
                                             NULL, NULL, NULL, NULL))
193
187
        {
194
188
          move_layer = TRUE;
195
189
        }
196
190
    }
197
191
 
198
 
  if ((state & GDK_MOD1_MASK) && (state & GDK_CONTROL_MASK) && move_layer)
199
 
    {
200
 
      selection_tool->op = SELECTION_MOVE_COPY; /* move a copy of the selection */
201
 
    }
202
 
  else if ((state & GDK_MOD1_MASK) && ! gimp_channel_is_empty (selection))
203
 
    {
204
 
      selection_tool->op = SELECTION_MOVE_MASK; /* move the selection mask */
205
 
    }
206
 
  else if (! (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) &&
207
 
           (move_layer || move_floating_sel))
208
 
    {
209
 
      selection_tool->op = SELECTION_MOVE;      /* move the selection */
210
 
    }
211
 
  else if ((state & GDK_CONTROL_MASK) && (state & GDK_SHIFT_MASK))
212
 
    {
213
 
      selection_tool->op = SELECTION_INTERSECT; /* intersect with selection */
214
 
    }
215
 
  else if (state & GDK_SHIFT_MASK)
216
 
    {
217
 
      selection_tool->op = SELECTION_ADD;       /* add to the selection */
218
 
    }
219
 
  else if (state & GDK_CONTROL_MASK)
220
 
    {
221
 
      selection_tool->op = SELECTION_SUBTRACT;  /* subtract from the selection */
 
192
  selection_empty = gimp_channel_is_empty (selection);
 
193
 
 
194
  selection_tool->function = SELECTION_SELECT;
 
195
 
 
196
  if (selection_tool->allow_move &&
 
197
      (state & GDK_MOD1_MASK) && (state & GDK_CONTROL_MASK) && move_layer)
 
198
    {
 
199
      /* move the selection */
 
200
      selection_tool->function = SELECTION_MOVE;
 
201
    }
 
202
  else if (selection_tool->allow_move &&
 
203
           (state & GDK_MOD1_MASK) && (state & GDK_SHIFT_MASK) && move_layer)
 
204
    {
 
205
      /* move a copy of the selection */
 
206
      selection_tool->function = SELECTION_MOVE_COPY;
 
207
    }
 
208
  else if (selection_tool->allow_move &&
 
209
           (state & GDK_MOD1_MASK) && ! selection_empty)
 
210
    {
 
211
      /* move the selection mask */
 
212
      selection_tool->function = SELECTION_MOVE_MASK;
 
213
    }
 
214
  else if (selection_tool->allow_move &&
 
215
           ! (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) &&
 
216
           move_floating_sel)
 
217
    {
 
218
      /* move the selection */
 
219
      selection_tool->function = SELECTION_MOVE;
 
220
    }
 
221
  else if ((state & GDK_CONTROL_MASK) || (state & GDK_SHIFT_MASK))
 
222
    {
 
223
      /* select */
 
224
      selection_tool->function = SELECTION_SELECT;
222
225
    }
223
226
  else if (floating_sel)
224
227
    {
225
 
      selection_tool->op = SELECTION_ANCHOR;    /* anchor the selection */
 
228
      /* anchor the selection */
 
229
      selection_tool->function = SELECTION_ANCHOR;
226
230
    }
227
 
  else
 
231
 
 
232
  gimp_tool_pop_status (tool, display);
 
233
 
 
234
  if (proximity)
228
235
    {
229
 
      selection_tool->op = options->operation;
 
236
      gchar           *status      = NULL;
 
237
      gboolean         free_status = FALSE;
 
238
      GdkModifierType  modifiers   = (GDK_SHIFT_MASK | GDK_CONTROL_MASK);
 
239
 
 
240
      if (! selection_empty)
 
241
        modifiers |= GDK_MOD1_MASK;
 
242
 
 
243
      switch (selection_tool->function)
 
244
        {
 
245
        case SELECTION_SELECT:
 
246
          switch (options->operation)
 
247
            {
 
248
            case GIMP_CHANNEL_OP_REPLACE:
 
249
              if (! selection_empty)
 
250
                {
 
251
                  status = gimp_suggest_modifiers (_("Click-Drag to replace the "
 
252
                                                     "current selection"),
 
253
                                                   modifiers & ~state,
 
254
                                                   NULL, NULL, NULL);
 
255
                  free_status = TRUE;
 
256
                }
 
257
              else
 
258
                {
 
259
                  status = _("Click-Drag to create a new selection");
 
260
                }
 
261
              break;
 
262
 
 
263
            case GIMP_CHANNEL_OP_ADD:
 
264
              status = gimp_suggest_modifiers (_("Click-Drag to add to the "
 
265
                                                 "current selection"),
 
266
                                               modifiers
 
267
                                               & ~(state | GDK_SHIFT_MASK),
 
268
                                               NULL, NULL, NULL);
 
269
              free_status = TRUE;
 
270
              break;
 
271
 
 
272
            case GIMP_CHANNEL_OP_SUBTRACT:
 
273
              status = gimp_suggest_modifiers (_("Click-Drag to subtract from the "
 
274
                                                 "current selection"),
 
275
                                               modifiers
 
276
                                               & ~(state | GDK_CONTROL_MASK),
 
277
                                               NULL, NULL, NULL);
 
278
              free_status = TRUE;
 
279
              break;
 
280
 
 
281
            case GIMP_CHANNEL_OP_INTERSECT:
 
282
              status = gimp_suggest_modifiers (_("Click-Drag to intersect with "
 
283
                                                 "the current selection"),
 
284
                                               modifiers & ~state,
 
285
                                               NULL, NULL, NULL);
 
286
              free_status = TRUE;
 
287
              break;
 
288
            }
 
289
          break;
 
290
 
 
291
        case SELECTION_MOVE_MASK:
 
292
          status = gimp_suggest_modifiers (_("Click-Drag to move the "
 
293
                                             "selection mask"),
 
294
                                           modifiers & ~state,
 
295
                                           NULL, NULL, NULL);
 
296
          free_status = TRUE;
 
297
          break;
 
298
 
 
299
        case SELECTION_MOVE:
 
300
          status = _("Click-Drag to move the selected pixels");
 
301
          break;
 
302
 
 
303
        case SELECTION_MOVE_COPY:
 
304
          status = _("Click-Drag to move a copy of the selected pixels");
 
305
          break;
 
306
 
 
307
        case SELECTION_ANCHOR:
 
308
          status = _("Click to anchor the floating selection");
 
309
          break;
 
310
 
 
311
        default:
 
312
          g_return_if_reached ();
 
313
        }
 
314
 
 
315
      if (status)
 
316
        gimp_tool_push_status (tool, display, status);
 
317
 
 
318
      if (free_status)
 
319
        g_free (status);
230
320
    }
231
321
}
232
322
 
234
324
gimp_selection_tool_cursor_update (GimpTool        *tool,
235
325
                                   GimpCoords      *coords,
236
326
                                   GdkModifierType  state,
237
 
                                   GimpDisplay     *gdisp)
 
327
                                   GimpDisplay     *display)
238
328
{
239
 
  GimpSelectionTool  *selection_tool = GIMP_SELECTION_TOOL (tool);
240
 
  GimpToolCursorType  tool_cursor;
241
 
  GimpCursorModifier  cmodifier;
 
329
  GimpSelectionTool    *selection_tool = GIMP_SELECTION_TOOL (tool);
 
330
  GimpSelectionOptions *options;
 
331
  GimpToolCursorType    tool_cursor;
 
332
  GimpCursorModifier    modifier;
 
333
 
 
334
  options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
242
335
 
243
336
  tool_cursor = gimp_tool_control_get_tool_cursor (tool->control);
244
 
  cmodifier   = GIMP_CURSOR_MODIFIER_NONE;
 
337
  modifier    = GIMP_CURSOR_MODIFIER_NONE;
245
338
 
246
 
  switch (selection_tool->op)
 
339
  switch (selection_tool->function)
247
340
    {
248
 
    case SELECTION_ADD:
249
 
      cmodifier = GIMP_CURSOR_MODIFIER_PLUS;
250
 
      break;
251
 
    case SELECTION_SUBTRACT:
252
 
      cmodifier = GIMP_CURSOR_MODIFIER_MINUS;
253
 
      break;
254
 
    case SELECTION_INTERSECT:
255
 
      cmodifier = GIMP_CURSOR_MODIFIER_INTERSECT;
256
 
      break;
257
 
    case SELECTION_REPLACE:
258
 
      break;
 
341
    case SELECTION_SELECT:
 
342
      switch (options->operation)
 
343
        {
 
344
        case GIMP_CHANNEL_OP_REPLACE:
 
345
          break;
 
346
        case GIMP_CHANNEL_OP_ADD:
 
347
          modifier = GIMP_CURSOR_MODIFIER_PLUS;
 
348
          break;
 
349
        case GIMP_CHANNEL_OP_SUBTRACT:
 
350
          modifier = GIMP_CURSOR_MODIFIER_MINUS;
 
351
          break;
 
352
        case GIMP_CHANNEL_OP_INTERSECT:
 
353
          modifier = GIMP_CURSOR_MODIFIER_INTERSECT;
 
354
          break;
 
355
        }
 
356
      break;
 
357
 
259
358
    case SELECTION_MOVE_MASK:
260
 
      cmodifier = GIMP_CURSOR_MODIFIER_MOVE;
 
359
      modifier = GIMP_CURSOR_MODIFIER_MOVE;
261
360
      break;
 
361
 
262
362
    case SELECTION_MOVE:
263
363
    case SELECTION_MOVE_COPY:
264
364
      tool_cursor = GIMP_TOOL_CURSOR_MOVE;
265
365
      break;
 
366
 
266
367
    case SELECTION_ANCHOR:
267
 
      cmodifier = GIMP_CURSOR_MODIFIER_ANCHOR;
 
368
      modifier = GIMP_CURSOR_MODIFIER_ANCHOR;
268
369
      break;
269
370
    }
270
371
 
271
 
  gimp_tool_set_cursor (tool, gdisp,
272
 
                        GIMP_CURSOR_MOUSE, tool_cursor, cmodifier);
 
372
  /*  we don't set the bad modifier ourselves, so a subclass has set
 
373
   *  it, always leave it there since it's more important than what we
 
374
   *  have to say.
 
375
   */
 
376
  if (gimp_tool_control_get_cursor_modifier (tool->control) ==
 
377
      GIMP_CURSOR_MODIFIER_BAD)
 
378
    {
 
379
      modifier = GIMP_CURSOR_MODIFIER_BAD;
 
380
    }
 
381
 
 
382
  gimp_tool_set_cursor (tool, display,
 
383
                        gimp_tool_control_get_cursor (tool->control),
 
384
                        tool_cursor,
 
385
                        modifier);
273
386
}
274
387
 
275
388
 
286
399
 
287
400
  tool = GIMP_TOOL (sel_tool);
288
401
 
289
 
  g_return_val_if_fail (GIMP_IS_DISPLAY (tool->gdisp), FALSE);
 
402
  g_return_val_if_fail (GIMP_IS_DISPLAY (tool->display), FALSE);
290
403
  g_return_val_if_fail (gimp_tool_control_is_active (tool->control), FALSE);
291
404
 
292
 
  switch (sel_tool->op)
 
405
  switch (sel_tool->function)
293
406
    {
294
407
    case SELECTION_MOVE_MASK:
295
 
      gimp_edit_selection_tool_start (tool, tool->gdisp, coords,
 
408
      gimp_edit_selection_tool_start (tool, tool->display, coords,
296
409
                                      GIMP_TRANSLATE_MODE_MASK, FALSE);
297
410
      return TRUE;
298
411
 
299
412
    case SELECTION_MOVE:
300
 
      gimp_edit_selection_tool_start (tool, tool->gdisp, coords,
 
413
      gimp_edit_selection_tool_start (tool, tool->display, coords,
301
414
                                      GIMP_TRANSLATE_MODE_MASK_TO_LAYER, FALSE);
302
415
      return TRUE;
303
416
 
304
417
    case SELECTION_MOVE_COPY:
305
 
      gimp_edit_selection_tool_start (tool, tool->gdisp, coords,
 
418
      gimp_edit_selection_tool_start (tool, tool->display, coords,
306
419
                                      GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER,
307
420
                                      FALSE);
308
421
      return TRUE;