gimpcolortool.c 27.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

#include <gtk/gtk.h>

Michael Natterer's avatar
Michael Natterer committed
23
#include "libgimpcolor/gimpcolor.h"
24 25 26 27
#include "libgimpwidgets/gimpwidgets.h"

#include "tools-types.h"

28 29
#include "config/gimpdisplayconfig.h"

30
#include "core/gimp.h"
31
#include "core/gimpdata.h"
32
#include "core/gimpimage.h"
Sven Neumann's avatar
Sven Neumann committed
33
#include "core/gimpimage-pick-color.h"
34
#include "core/gimpimage-sample-points.h"
35
#include "core/gimpitem.h"
Sven Neumann's avatar
Sven Neumann committed
36
#include "core/gimpmarshal.h"
37

38 39 40 41 42
#include "widgets/gimpcolormapeditor.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockable.h"
#include "widgets/gimppaletteeditor.h"
#include "widgets/gimpsessioninfo.h"
43

44
#include "display/gimpdisplay.h"
45 46 47
#include "display/gimpdisplayshell.h"
#include "display/gimpdisplayshell-appearance.h"
#include "display/gimpdisplayshell-draw.h"
Sven Neumann's avatar
Sven Neumann committed
48
#include "display/gimpdisplayshell-selection.h"
49
#include "display/gimpdisplayshell-transform.h"
50 51 52 53 54

#include "gimpcoloroptions.h"
#include "gimpcolortool.h"
#include "gimptoolcontrol.h"

55 56
#include "gimp-intl.h"

57

Sven Neumann's avatar
Sven Neumann committed
58 59 60 61 62 63 64
enum
{
  PICKED,
  LAST_SIGNAL
};


65 66
/*  local function prototypes  */

67
static void       gimp_color_tool_finalize       (GObject         *object);
68

69 70
static void       gimp_color_tool_control        (GimpTool        *tool,
                                                  GimpToolAction   action,
71
                                                  GimpDisplay     *display);
72
static void       gimp_color_tool_button_press   (GimpTool        *tool,
73 74 75
                                                  GimpCoords      *coords,
                                                  guint32          time,
                                                  GdkModifierType  state,
76
                                                  GimpDisplay     *display);
77
static void       gimp_color_tool_button_release (GimpTool        *tool,
78 79 80
                                                  GimpCoords      *coords,
                                                  guint32          time,
                                                  GdkModifierType  state,
81
                                                  GimpDisplay     *display);
82
static void       gimp_color_tool_motion         (GimpTool        *tool,
83 84 85
                                                  GimpCoords      *coords,
                                                  guint32          time,
                                                  GdkModifierType  state,
86
                                                  GimpDisplay     *display);
87 88 89
static void       gimp_color_tool_oper_update    (GimpTool        *tool,
                                                  GimpCoords      *coords,
                                                  GdkModifierType  state,
90
                                                  gboolean         proximity,
91
                                                  GimpDisplay     *display);
92
static void       gimp_color_tool_cursor_update  (GimpTool        *tool,
93 94
                                                  GimpCoords      *coords,
                                                  GdkModifierType  state,
95
                                                  GimpDisplay     *display);
96 97 98

static void       gimp_color_tool_draw           (GimpDrawTool    *draw_tool);

Sven Neumann's avatar
Sven Neumann committed
99 100 101 102 103 104 105
static gboolean   gimp_color_tool_real_pick      (GimpColorTool   *color_tool,
                                                  gint             x,
                                                  gint             y,
                                                  GimpImageType   *sample_type,
                                                  GimpRGB         *color,
                                                  gint            *color_index);
static void       gimp_color_tool_pick           (GimpColorTool   *tool,
106
                                                  GimpColorPickState pick_state,
Sven Neumann's avatar
Sven Neumann committed
107 108
                                                  gint             x,
                                                  gint             y);
109 110 111 112 113
static void       gimp_color_tool_real_picked    (GimpColorTool   *color_tool,
                                                  GimpColorPickState pick_state,
                                                  GimpImageType    sample_type,
                                                  GimpRGB         *color,
                                                  gint             color_index);
Sven Neumann's avatar
Sven Neumann committed
114

115

116
G_DEFINE_TYPE (GimpColorTool, gimp_color_tool, GIMP_TYPE_DRAW_TOOL);
117

118
#define parent_class gimp_color_tool_parent_class
119

120
static guint gimp_color_tool_signals[LAST_SIGNAL] = { 0 };
121 122 123 124 125


static void
gimp_color_tool_class_init (GimpColorToolClass *klass)
{
126 127 128
  GObjectClass      *object_class = G_OBJECT_CLASS (klass);
  GimpToolClass     *tool_class   = GIMP_TOOL_CLASS (klass);
  GimpDrawToolClass *draw_class   = GIMP_DRAW_TOOL_CLASS (klass);
129

Sven Neumann's avatar
Sven Neumann committed
130 131
  gimp_color_tool_signals[PICKED] =
    g_signal_new ("picked",
132 133 134 135 136 137
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpColorToolClass, picked),
                  NULL, NULL,
                  gimp_marshal_VOID__ENUM_ENUM_BOXED_INT,
                  G_TYPE_NONE, 4,
138
                  GIMP_TYPE_COLOR_PICK_STATE,
Sven Neumann's avatar
Sven Neumann committed
139
                  GIMP_TYPE_IMAGE_TYPE,
Michael Natterer's avatar
Michael Natterer committed
140
                  GIMP_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE,
Sven Neumann's avatar
Sven Neumann committed
141 142
                  G_TYPE_INT);

Sven Neumann's avatar
Sven Neumann committed
143 144
  object_class->finalize     = gimp_color_tool_finalize;

145
  tool_class->control        = gimp_color_tool_control;
146 147 148
  tool_class->button_press   = gimp_color_tool_button_press;
  tool_class->button_release = gimp_color_tool_button_release;
  tool_class->motion         = gimp_color_tool_motion;
149
  tool_class->oper_update    = gimp_color_tool_oper_update;
150 151
  tool_class->cursor_update  = gimp_color_tool_cursor_update;

152
  draw_class->draw           = gimp_color_tool_draw;
153

Sven Neumann's avatar
Sven Neumann committed
154
  klass->pick                = gimp_color_tool_real_pick;
155
  klass->picked              = gimp_color_tool_real_picked;
156 157
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
static void
gimp_color_tool_init (GimpColorTool *color_tool)
{
  GimpTool *tool = GIMP_TOOL (color_tool);

  gimp_tool_control_set_action_value_1 (tool->control,
                                        "tools/tools-color-average-radius-set");

  color_tool->enabled             = FALSE;
  color_tool->center_x            = 0;
  color_tool->center_y            = 0;
  color_tool->pick_mode           = GIMP_COLOR_PICK_MODE_NONE;

  color_tool->options             = NULL;

  color_tool->sample_point        = NULL;
  color_tool->moving_sample_point = FALSE;
  color_tool->sample_point_x      = -1;
  color_tool->sample_point_y      = -1;
}

179
static void
Sven Neumann's avatar
Sven Neumann committed
180
gimp_color_tool_finalize (GObject *object)
181
{
Sven Neumann's avatar
Sven Neumann committed
182 183 184 185 186 187 188 189 190 191
  GimpColorTool *color_tool = GIMP_COLOR_TOOL (object);

  if (color_tool->options)
    {
      g_object_unref (color_tool->options);
      color_tool->options = NULL;
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
192

Sven Neumann's avatar
Sven Neumann committed
193
static void
194 195
gimp_color_tool_control (GimpTool       *tool,
                         GimpToolAction  action,
196
                         GimpDisplay    *display)
Sven Neumann's avatar
Sven Neumann committed
197
{
198
  GimpColorTool    *color_tool = GIMP_COLOR_TOOL (tool);
199
  GimpDisplayShell *shell      = GIMP_DISPLAY_SHELL (display->shell);
Michael Natterer's avatar
Michael Natterer committed
200

201 202
  switch (action)
    {
203
    case GIMP_TOOL_ACTION_PAUSE:
204 205
      break;

206
    case GIMP_TOOL_ACTION_RESUME:
207 208
      if (color_tool->sample_point &&
          gimp_display_shell_get_show_sample_points (GIMP_DISPLAY_SHELL (shell)))
209
        gimp_display_shell_draw_sample_point (GIMP_DISPLAY_SHELL (shell),
210 211 212
                                              color_tool->sample_point, TRUE);
      break;

213
    case GIMP_TOOL_ACTION_HALT:
214 215 216 217 218 219
      if (color_tool->sample_point &&
          gimp_display_shell_get_show_sample_points (GIMP_DISPLAY_SHELL (shell)))
        gimp_display_shell_draw_sample_point (GIMP_DISPLAY_SHELL (shell),
                                              color_tool->sample_point, FALSE);
      break;
    }
Michael Natterer's avatar
Michael Natterer committed
220

221
  GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
222 223 224 225
}

static void
gimp_color_tool_button_press (GimpTool        *tool,
226 227 228
                              GimpCoords      *coords,
                              guint32          time,
                              GdkModifierType  state,
229
                              GimpDisplay     *display)
230
{
231
  GimpColorTool    *color_tool = GIMP_COLOR_TOOL (tool);
232
  GimpDisplayShell *shell      = GIMP_DISPLAY_SHELL (display->shell);
233

234 235 236
  /*  Make the tool active and set its display & drawable  */
  tool->display  = display;
  tool->drawable = gimp_image_active_drawable (display->image);
237 238
  gimp_tool_control_activate (tool->control);

239 240 241 242 243 244 245 246 247
  if (! color_tool->enabled)
    return;

  if (color_tool->sample_point)
    {
      color_tool->moving_sample_point = TRUE;
      color_tool->sample_point_x      = color_tool->sample_point->x;
      color_tool->sample_point_y      = color_tool->sample_point->y;

Sven Neumann's avatar
Sven Neumann committed
248
      gimp_display_shell_selection_control (shell, GIMP_SELECTION_PAUSE);
249

250
      gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
251

252
      gimp_tool_push_status_coords (tool, display,
253
                                    _("Move Sample Point: "),
254 255 256 257 258
                                    color_tool->sample_point_x,
                                    ", ",
                                    color_tool->sample_point_y);
    }
  else
259
    {
Sven Neumann's avatar
Sven Neumann committed
260 261
      gint off_x, off_y;

262 263 264
      /*  Keep the coordinates of the target  */
      gimp_item_offsets (GIMP_ITEM (tool->drawable), &off_x, &off_y);

Sven Neumann's avatar
Sven Neumann committed
265 266
      color_tool->center_x = coords->x - off_x;
      color_tool->center_y = coords->y - off_y;
267

268
      gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
Sven Neumann's avatar
Sven Neumann committed
269

270 271
      gimp_color_tool_pick (color_tool, GIMP_COLOR_PICK_STATE_NEW,
                            coords->x, coords->y);
272 273 274 275 276
    }
}

static void
gimp_color_tool_button_release (GimpTool        *tool,
277 278 279
                                GimpCoords      *coords,
                                guint32          time,
                                GdkModifierType  state,
280
                                GimpDisplay     *display)
281
{
282
  GimpColorTool    *color_tool = GIMP_COLOR_TOOL (tool);
283
  GimpDisplayShell *shell      = GIMP_DISPLAY_SHELL (display->shell);
284 285

  gimp_tool_control_halt (tool->control);
286 287 288 289 290 291 292 293

  if (! color_tool->enabled)
    return;

  if (color_tool->moving_sample_point)
    {
      gint x, y, width, height;

294
      gimp_tool_pop_status (tool, display);
295 296 297 298 299 300 301 302 303

      gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));

      if (state & GDK_BUTTON3_MASK)
        {
          color_tool->moving_sample_point = FALSE;
          color_tool->sample_point_x      = -1;
          color_tool->sample_point_y      = -1;

Sven Neumann's avatar
Sven Neumann committed
304
          gimp_display_shell_selection_control (shell, GIMP_SELECTION_RESUME);
305 306 307 308 309
          return;
        }

      gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);

310 311 312 313
      if ((color_tool->sample_point_x <  x              ||
           color_tool->sample_point_x > (x + width - 1) ||
           color_tool->sample_point_y < y               ||
           color_tool->sample_point_y > (y + height - 1)))
314 315 316
        {
          if (color_tool->sample_point)
            {
317
              gimp_image_remove_sample_point (display->image,
318 319 320
                                              color_tool->sample_point, TRUE);
              color_tool->sample_point = NULL;
            }
321
        }
322 323 324 325
      else
        {
          if (color_tool->sample_point)
            {
326
              gimp_image_move_sample_point (display->image,
327 328 329 330 331 332 333 334
                                            color_tool->sample_point,
                                            color_tool->sample_point_x,
                                            color_tool->sample_point_y,
                                            TRUE);
            }
          else
            {
              color_tool->sample_point =
335
                gimp_image_add_sample_point_at_pos (display->image,
336 337 338 339 340 341
                                                    color_tool->sample_point_x,
                                                    color_tool->sample_point_y,
                                                    TRUE);
            }
        }

Sven Neumann's avatar
Sven Neumann committed
342
      gimp_display_shell_selection_control (shell, GIMP_SELECTION_RESUME);
343
      gimp_image_flush (display->image);
344 345

      if (color_tool->sample_point)
346
        gimp_display_shell_draw_sample_point (shell, color_tool->sample_point,
347 348 349 350 351 352 353 354 355 356
                                              TRUE);

      color_tool->moving_sample_point = FALSE;
      color_tool->sample_point_x      = -1;
      color_tool->sample_point_y      = -1;
    }
  else
    {
      gimp_draw_tool_stop (GIMP_DRAW_TOOL (tool));
    }
357 358 359 360
}

static void
gimp_color_tool_motion (GimpTool        *tool,
Sven Neumann's avatar
Sven Neumann committed
361 362 363
                        GimpCoords      *coords,
                        guint32          time,
                        GdkModifierType  state,
364
                        GimpDisplay     *display)
365
{
366
  GimpColorTool    *color_tool = GIMP_COLOR_TOOL (tool);
367
  GimpDisplayShell *shell      = GIMP_DISPLAY_SHELL (display->shell);
368

Sven Neumann's avatar
Sven Neumann committed
369 370
  if (! color_tool->enabled)
    return;
371

372 373 374 375
  if (color_tool->moving_sample_point)
    {
      gint      tx, ty;
      gboolean  delete_point = FALSE;
376

377
      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
378

379 380 381 382
      gimp_display_shell_transform_xy (shell,
                                       coords->x, coords->y,
                                       &tx, &ty,
                                       FALSE);
383

384 385
      if (tx < 0 || tx > shell->disp_width ||
          ty < 0 || ty > shell->disp_height)
386 387
        {
          color_tool->sample_point_x = -1;
388
          color_tool->sample_point_y = -1;
Sven Neumann's avatar
Sven Neumann committed
389

390
          delete_point = TRUE;
391
        }
392 393 394 395
      else
        {
          gint x, y, width, height;

396 397
          color_tool->sample_point_x = floor (coords->x);
          color_tool->sample_point_y = floor (coords->y);
398 399 400 401

          gimp_display_shell_untransform_viewport (shell, &x, &y,
                                                   &width, &height);

402 403 404 405
          if ((color_tool->sample_point_x <  x              ||
               color_tool->sample_point_x > (x + width - 1) ||
               color_tool->sample_point_y < y               ||
               color_tool->sample_point_y > (y + height - 1)))
406 407 408 409 410 411 412
            {
              delete_point = TRUE;
            }
        }

      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));

413
      gimp_tool_pop_status (tool, display);
414 415 416

      if (delete_point)
        {
417
          gimp_tool_push_status (tool, display,
418 419 420 421 422 423
                                 color_tool->sample_point ?
                                 _("Remove Sample Point") :
                                 _("Cancel Sample Point"));
        }
      else
        {
424
          gimp_tool_push_status_coords (tool, display,
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
                                        color_tool->sample_point ?
                                        _("Move Sample Point: ") :
                                        _("Add Sample Point: "),
                                        color_tool->sample_point_x,
                                        ", ",
                                        color_tool->sample_point_y);
        }
    }
  else
    {
      gint off_x, off_y;

      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));

      gimp_item_offsets (GIMP_ITEM (tool->drawable), &off_x, &off_y);

      color_tool->center_x = coords->x - off_x;
      color_tool->center_y = coords->y - off_y;

      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));

      gimp_color_tool_pick (color_tool, GIMP_COLOR_PICK_STATE_UPDATE,
                            coords->x, coords->y);
    }
}

static void
gimp_color_tool_oper_update (GimpTool        *tool,
                             GimpCoords      *coords,
                             GdkModifierType  state,
455
                             gboolean         proximity,
456
                             GimpDisplay     *display)
457 458
{
  GimpColorTool    *color_tool   = GIMP_COLOR_TOOL (tool);
459
  GimpDisplayShell *shell        = GIMP_DISPLAY_SHELL (display->shell);
460 461 462
  GimpSamplePoint  *sample_point = NULL;

  if (color_tool->enabled &&
463
      gimp_display_shell_get_show_sample_points (shell) && proximity)
464 465 466 467
    {
      gint snap_distance;

      snap_distance =
468
        GIMP_DISPLAY_CONFIG (display->image->gimp->config)->snap_distance;
469 470

      sample_point =
471
        gimp_image_find_sample_point (display->image,
472 473 474 475 476 477
                                      coords->x, coords->y,
                                      FUNSCALEX (shell, snap_distance),
                                      FUNSCALEY (shell, snap_distance));
    }

  if (color_tool->sample_point && color_tool->sample_point != sample_point)
478
    gimp_image_update_sample_point (shell->display->image,
479 480 481 482 483 484 485
                                    color_tool->sample_point);

  color_tool->sample_point = sample_point;

  if (color_tool->sample_point)
    gimp_display_shell_draw_sample_point (shell, color_tool->sample_point,
                                          TRUE);
486 487 488 489
}

static void
gimp_color_tool_cursor_update (GimpTool        *tool,
490 491
                               GimpCoords      *coords,
                               GdkModifierType  state,
492
                               GimpDisplay     *display)
493
{
494 495 496
  GimpColorTool *color_tool = GIMP_COLOR_TOOL (tool);

  if (color_tool->enabled)
497
    {
498
      if (color_tool->sample_point)
Sven Neumann's avatar
Sven Neumann committed
499
        {
500
          gimp_tool_set_cursor (tool, display,
501
                                GIMP_CURSOR_MOUSE,
502 503
                                GIMP_TOOL_CURSOR_COLOR_PICKER,
                                GIMP_CURSOR_MODIFIER_MOVE);
Sven Neumann's avatar
Sven Neumann committed
504
        }
505
      else
506
        {
507
          GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_BAD;
508

509 510 511
          if (gimp_image_coords_in_active_pickable (display->image, coords,
                                                    color_tool->options->sample_merged,
                                                    FALSE))
512
            {
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
              switch (color_tool->pick_mode)
                {
                case GIMP_COLOR_PICK_MODE_NONE:
                  modifier = GIMP_CURSOR_MODIFIER_NONE;
                  break;
                case GIMP_COLOR_PICK_MODE_FOREGROUND:
                  modifier = GIMP_CURSOR_MODIFIER_FOREGROUND;
                  break;
                case GIMP_COLOR_PICK_MODE_BACKGROUND:
                  modifier = GIMP_CURSOR_MODIFIER_BACKGROUND;
                  break;
                case GIMP_COLOR_PICK_MODE_PALETTE:
                  modifier = GIMP_CURSOR_MODIFIER_PLUS;
                  break;
                }
528 529
            }

530
          gimp_tool_set_cursor (tool, display,
531 532
                                GIMP_CURSOR_COLOR_PICKER,
                                GIMP_TOOL_CURSOR_COLOR_PICKER,
533
                                modifier);
534 535
        }

Sven Neumann's avatar
Sven Neumann committed
536
      return;  /*  don't chain up  */
537 538
    }

539
  GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
540 541 542 543 544
}

static void
gimp_color_tool_draw (GimpDrawTool *draw_tool)
{
545
  GimpColorTool *color_tool = GIMP_COLOR_TOOL (draw_tool);
546

547
  if (! color_tool->enabled)
548 549
    return;

550
  if (color_tool->moving_sample_point)
Sven Neumann's avatar
Sven Neumann committed
551
    {
552 553 554 555
      if (color_tool->sample_point_x != -1 &&
          color_tool->sample_point_y != -1)
        {
          gimp_draw_tool_draw_line (draw_tool,
556
                                    0, color_tool->sample_point_y + 0.5,
557
                                    draw_tool->display->image->width,
558
                                    color_tool->sample_point_y + 0.5,
559 560
                                    FALSE);
          gimp_draw_tool_draw_line (draw_tool,
561 562
                                    color_tool->sample_point_x + 0.5, 0,
                                    color_tool->sample_point_x + 0.5,
563
                                    draw_tool->display->image->height,
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
                                    FALSE);
        }
    }
  else
    {
      if (color_tool->options->sample_average)
        {
          gdouble radius = color_tool->options->average_radius;

          gimp_draw_tool_draw_rectangle (draw_tool,
                                         FALSE,
                                         color_tool->center_x - radius,
                                         color_tool->center_y - radius,
                                         2 * radius + 1,
                                         2 * radius + 1,
                                         TRUE);
        }
Sven Neumann's avatar
Sven Neumann committed
581
    }
582 583
}

Sven Neumann's avatar
Sven Neumann committed
584 585 586 587 588 589 590
static gboolean
gimp_color_tool_real_pick (GimpColorTool *color_tool,
                           gint           x,
                           gint           y,
                           GimpImageType *sample_type,
                           GimpRGB       *color,
                           gint          *color_index)
591
{
Sven Neumann's avatar
Sven Neumann committed
592
  GimpTool *tool = GIMP_TOOL (color_tool);
Sven Neumann's avatar
Sven Neumann committed
593

594
  g_return_val_if_fail (tool->display != NULL, FALSE);
Sven Neumann's avatar
Sven Neumann committed
595 596
  g_return_val_if_fail (tool->drawable != NULL, FALSE);

597
  return gimp_image_pick_color (tool->display->image, tool->drawable, x, y,
Sven Neumann's avatar
Sven Neumann committed
598 599 600
                                color_tool->options->sample_merged,
                                color_tool->options->sample_average,
                                color_tool->options->average_radius,
Sven Neumann's avatar
Sven Neumann committed
601 602 603 604 605
                                sample_type,
                                color,
                                color_index);
}

606 607 608 609 610 611 612
static void
gimp_color_tool_real_picked (GimpColorTool      *color_tool,
                             GimpColorPickState  pick_state,
                             GimpImageType       sample_type,
                             GimpRGB            *color,
                             gint                color_index)
{
613
  GimpTool          *tool = GIMP_TOOL (color_tool);
614
  GimpContext       *context;
615
  GimpDialogFactory *dialog_factory;
616

617 618 619
  /*  use this tool's own options here (NOT color_tool->options)  */
  context = GIMP_CONTEXT (gimp_tool_get_options (tool));

620
  dialog_factory = gimp_dialog_factory_from_name ("dock");
621

622 623
  if (color_tool->pick_mode == GIMP_COLOR_PICK_MODE_FOREGROUND ||
      color_tool->pick_mode == GIMP_COLOR_PICK_MODE_BACKGROUND)
624
    {
625
      GimpSessionInfo *info;
626

627 628 629 630 631 632 633 634 635
      if (GIMP_IMAGE_TYPE_IS_INDEXED (sample_type))
        {
          info = gimp_dialog_factory_find_session_info (dialog_factory,
                                                        "gimp-indexed-palette");
          if (info && info->widget)
            {
              GimpColormapEditor *editor;

              editor = GIMP_COLORMAP_EDITOR (gtk_bin_get_child (GTK_BIN (info->widget)));
636

637 638 639 640 641
              gimp_colormap_editor_set_index (editor, color_index, NULL);
            }
        }

      if (TRUE)
642
        {
643 644 645 646 647 648
          info = gimp_dialog_factory_find_session_info (dialog_factory,
                                                        "gimp-palette-editor");
          if (info && info->widget)
            {
              GimpPaletteEditor *editor;
              gint               index;
649

650
              editor = GIMP_PALETTE_EDITOR (gtk_bin_get_child (GTK_BIN (info->widget)));
651

652 653 654 655
              index = gimp_palette_editor_get_index (editor, color);
              if (index != -1)
                gimp_palette_editor_set_index (editor, index, NULL);
            }
656 657 658 659 660 661 662 663 664
        }
    }

  switch (color_tool->pick_mode)
    {
    case GIMP_COLOR_PICK_MODE_NONE:
      break;

    case GIMP_COLOR_PICK_MODE_FOREGROUND:
665
      gimp_context_set_foreground (context, color);
666 667 668
      break;

    case GIMP_COLOR_PICK_MODE_BACKGROUND:
669
      gimp_context_set_background (context, color);
670 671 672 673
      break;

    case GIMP_COLOR_PICK_MODE_PALETTE:
      {
674 675
        GdkScreen *screen;
        GtkWidget *dockable;
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695

        screen = gtk_widget_get_screen (tool->display->shell);
        dockable = gimp_dialog_factory_dialog_raise (dialog_factory, screen,
                                                     "gimp-palette-editor",
                                                     -1);
        if (dockable)
          {
            GtkWidget *palette_editor;
            GimpData  *data;

            /* don't blink like mad when updating */
            if (pick_state == GIMP_COLOR_PICK_STATE_UPDATE)
              gimp_dockable_blink_cancel (GIMP_DOCKABLE (dockable));

            palette_editor = gtk_bin_get_child (GTK_BIN (dockable));

            data = gimp_data_editor_get_data (GIMP_DATA_EDITOR (palette_editor));

            if (! data)
              {
696
                data = GIMP_DATA (gimp_context_get_palette (context));
697 698 699 700 701 702 703 704 705 706 707 708 709

                gimp_data_editor_set_data (GIMP_DATA_EDITOR (palette_editor),
                                           data);
              }

            gimp_palette_editor_pick_color (GIMP_PALETTE_EDITOR (palette_editor),
                                            color, pick_state);
          }
      }
      break;
    }
}

Sven Neumann's avatar
Sven Neumann committed
710
static void
711 712
gimp_color_tool_pick (GimpColorTool      *tool,
                      GimpColorPickState  pick_state,
713 714
                      gint                x,
                      gint                y)
Sven Neumann's avatar
Sven Neumann committed
715 716 717 718 719
{
  GimpColorToolClass *klass;
  GimpImageType       sample_type;
  GimpRGB             color;
  gint                color_index;
720 721 722

  klass = GIMP_COLOR_TOOL_GET_CLASS (tool);

Sven Neumann's avatar
Sven Neumann committed
723 724 725
  if (klass->pick &&
      klass->pick (tool, x, y, &sample_type, &color, &color_index))
    {
726 727
      g_signal_emit (tool, gimp_color_tool_signals[PICKED], 0,
                     pick_state, sample_type, &color, color_index);
Sven Neumann's avatar
Sven Neumann committed
728 729 730 731 732
    }
}


void
Sven Neumann's avatar
Sven Neumann committed
733 734
gimp_color_tool_enable (GimpColorTool    *color_tool,
                        GimpColorOptions *options)
Sven Neumann's avatar
Sven Neumann committed
735 736 737 738
{
  GimpTool *tool;

  g_return_if_fail (GIMP_IS_COLOR_TOOL (color_tool));
Sven Neumann's avatar
Sven Neumann committed
739
  g_return_if_fail (GIMP_IS_COLOR_OPTIONS (options));
Sven Neumann's avatar
Sven Neumann committed
740 741

  tool = GIMP_TOOL (color_tool);
742

Sven Neumann's avatar
Sven Neumann committed
743 744
  if (gimp_tool_control_is_active (tool->control))
    {
Sven Neumann's avatar
Sven Neumann committed
745
      g_warning ("Trying to enable GimpColorTool while it is active.");
Sven Neumann's avatar
Sven Neumann committed
746 747
      return;
    }
748

Sven Neumann's avatar
Sven Neumann committed
749
  if (color_tool->options)
750 751
    g_object_unref (color_tool->options);

Sven Neumann's avatar
Sven Neumann committed
752 753 754 755 756 757 758 759 760 761 762 763 764
  color_tool->options = g_object_ref (options);

  color_tool->enabled = TRUE;
}

void
gimp_color_tool_disable (GimpColorTool *color_tool)
{
  GimpTool *tool;

  g_return_if_fail (GIMP_IS_COLOR_TOOL (color_tool));

  tool = GIMP_TOOL (color_tool);
765

Sven Neumann's avatar
Sven Neumann committed
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
  if (gimp_tool_control_is_active (tool->control))
    {
      g_warning ("Trying to disable GimpColorTool while it is active.");
      return;
    }

  if (color_tool->options)
    {
      g_object_unref (color_tool->options);
      color_tool->options = NULL;
    }

  color_tool->enabled = FALSE;
}

gboolean
gimp_color_tool_is_enabled (GimpColorTool *color_tool)
{
  return color_tool->enabled;
785
}
786 787 788

void
gimp_color_tool_start_sample_point (GimpTool    *tool,
789
                                    GimpDisplay *display)
790 791 792 793
{
  GimpColorTool *color_tool;

  g_return_if_fail (GIMP_IS_COLOR_TOOL (tool));
794
  g_return_if_fail (GIMP_IS_DISPLAY (display));
795 796 797

  color_tool = GIMP_COLOR_TOOL (tool);

Sven Neumann's avatar
Sven Neumann committed
798 799
  gimp_display_shell_selection_control (GIMP_DISPLAY_SHELL (display->shell),
                                        GIMP_SELECTION_PAUSE);
800

801
  tool->display = display;
802 803 804
  gimp_tool_control_activate (tool->control);

  if (color_tool->sample_point)
805
    gimp_display_shell_draw_sample_point (GIMP_DISPLAY_SHELL (display->shell),
806 807 808 809 810 811 812
                                          color_tool->sample_point, FALSE);

  color_tool->sample_point        = NULL;
  color_tool->moving_sample_point = TRUE;
  color_tool->sample_point_x      = -1;
  color_tool->sample_point_y      = -1;

813
  gimp_tool_set_cursor (tool, display,
814
                        GIMP_CURSOR_MOUSE,
815 816 817
                        GIMP_TOOL_CURSOR_COLOR_PICKER,
                        GIMP_CURSOR_MODIFIER_MOVE);

818
  gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
819
}