gimpcolorarea.c 21.3 KB
Newer Older
1
2
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3
4
 *
 * gimpcolorarea.c
5
 * Copyright (C) 2001-2002  Sven Neumann <sven@gimp.org>
6
7
8
9
10
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
11
12
13
14
 *
 * This library 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
15
16
17
18
19
20
21
22
23
24
25
26
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; 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>

27
#include "libgimpcolor/gimpcolor.h"
28
#include "libgimpbase/gimpbase.h"
29

30
#include "gimpwidgetstypes.h"
31
32
33
34
35
36
37
38
39
40
41
42
43
44

#include "gimpcolorarea.h"


#define DRAG_PREVIEW_SIZE   32
#define DRAG_ICON_OFFSET    -8


enum
{
  COLOR_CHANGED,
  LAST_SIGNAL
};

45
46
47
enum
{
  PROP_0,
48
49
50
  PROP_COLOR,
  PROP_TYPE,
  PROP_DRAG_MASK
51
52
};

53

54
55
static void     gimp_color_area_class_init     (GimpColorAreaClass *klass);
static void     gimp_color_area_init           (GimpColorArea      *area);
56

57
58
59
60
61
62
63
64
65
static void      gimp_color_area_get_property  (GObject            *object,
                                                guint               property_id,
                                                GValue             *value,
                                                GParamSpec         *pspec);
static void      gimp_color_area_set_property  (GObject            *object,
                                                guint               property_id,
                                                const GValue       *value,
                                                GParamSpec         *pspec);
static void      gimp_color_area_finalize      (GObject            *object);
66

67
68
69
70
71
static void      gimp_color_area_size_allocate (GtkWidget          *widget,
                                                GtkAllocation      *allocation);
static gboolean  gimp_color_area_expose        (GtkWidget          *widget,
                                                GdkEventExpose     *event);
static void      gimp_color_area_render        (GimpColorArea      *area);
72
73
74
75
76

static void  gimp_color_area_drag_begin         (GtkWidget        *widget,
						 GdkDragContext   *context);
static void  gimp_color_area_drag_end           (GtkWidget        *widget,
						 GdkDragContext   *context);
77
static void  gimp_color_area_drag_data_received (GtkWidget        *widget,
78
79
						 GdkDragContext   *context,
						 gint              x,
80
						 gint              y,
81
82
83
						 GtkSelectionData *selection_data,
						 guint             info,
						 guint             time);
84
static void  gimp_color_area_drag_data_get      (GtkWidget        *widget,
85
86
87
88
89
						 GdkDragContext   *context,
						 GtkSelectionData *selection_data,
						 guint             info,
						 guint             time);

90

91
static const GtkTargetEntry target = { "application/x-color", 0 };
92

93
static guint gimp_color_area_signals[LAST_SIGNAL] = { 0 };
94

95
static GtkDrawingAreaClass * parent_class = NULL;
96
97


98
GType
99
100
gimp_color_area_get_type (void)
{
Sven Neumann's avatar
Sven Neumann committed
101
  static GType area_type = 0;
102

Sven Neumann's avatar
Sven Neumann committed
103
  if (! area_type)
104
    {
Sven Neumann's avatar
Sven Neumann committed
105
      static const GTypeInfo area_info =
106
      {
107
108
109
110
111
112
113
114
115
        sizeof (GimpColorAreaClass),
        (GBaseInitFunc) NULL,
        (GBaseFinalizeFunc) NULL,
        (GClassInitFunc) gimp_color_area_class_init,
        NULL,           /* class_finalize */
        NULL,           /* class_data     */
        sizeof (GimpColorArea),
        0,              /* n_preallocs    */
        (GInstanceInitFunc) gimp_color_area_init,
116
117
      };

Sven Neumann's avatar
Sven Neumann committed
118
      area_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
119
120
                                          "GimpColorArea",
                                          &area_info, 0);
121
    }
122

Sven Neumann's avatar
Sven Neumann committed
123
  return area_type;
124
125
126
}

static void
127
gimp_color_area_class_init (GimpColorAreaClass *klass)
128
{
129
130
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
131
  GimpRGB         color;
132

133
  parent_class = g_type_class_peek_parent (klass);
134

135
  gimp_color_area_signals[COLOR_CHANGED] =
136
    g_signal_new ("color_changed",
137
138
139
140
141
142
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GimpColorAreaClass, color_changed),
                  NULL, NULL,
                  g_cclosure_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
143

144
145
  object_class->get_property       = gimp_color_area_get_property;
  object_class->set_property       = gimp_color_area_set_property;
146
  object_class->finalize           = gimp_color_area_finalize;
147

148
  widget_class->size_allocate      = gimp_color_area_size_allocate;
149
  widget_class->expose_event       = gimp_color_area_expose;
150

151
152
153
154
  widget_class->drag_begin         = gimp_color_area_drag_begin;
  widget_class->drag_end           = gimp_color_area_drag_end;
  widget_class->drag_data_received = gimp_color_area_drag_data_received;
  widget_class->drag_data_get      = gimp_color_area_drag_data_get;
155
156

  klass->color_changed             = NULL;
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
  gimp_rgba_set (&color, 0.0, 0.0, 0.0, 1.0);

  /**
   * GimpColorArea:color:
   *
   * The color displayed in the color area.
   *
   * Since: GIMP 2.4
   */
  g_object_class_install_property (object_class, PROP_COLOR,
                                   gimp_param_spec_rgb ("color", NULL, NULL,
                                                        &color,
                                                        G_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT));
172
173
174
175
176
177
178
179
180
181
182
183
184
  /**
   * GimpColorArea:type:
   *
   * The type of the color area.
   *
   * Since: GIMP 2.4
   */
  g_object_class_install_property (object_class, PROP_TYPE,
                                   g_param_spec_enum ("type", NULL, NULL,
                                                      GIMP_TYPE_COLOR_AREA_TYPE,
                                                      GIMP_COLOR_AREA_FLAT,
                                                      G_PARAM_READWRITE |
                                                      G_PARAM_CONSTRUCT));
185
186
187
188
189
190
191
192
193
194
195
196
197
  /**
   * GimpColorArea:drag-type:
   *
   * The event_mask that should trigger drags.
   *
   * Since: GIMP 2.4
   */
  g_object_class_install_property (object_class, PROP_DRAG_MASK,
                                   g_param_spec_flags ("drag-mask", NULL, NULL,
                                                       GDK_TYPE_MODIFIER_TYPE,
                                                       0,
                                                       G_PARAM_WRITABLE |
                                                       G_PARAM_CONSTRUCT_ONLY));
198
199
200
}

static void
Sven Neumann's avatar
Sven Neumann committed
201
gimp_color_area_init (GimpColorArea *area)
202
{
203
204
205
206
207
  area->buf         = NULL;
  area->width       = 0;
  area->height      = 0;
  area->rowstride   = 0;
  area->draw_border = FALSE;
208

209
210
211
212
213
214
  gtk_drag_dest_set (GTK_WIDGET (area),
                     GTK_DEST_DEFAULT_HIGHLIGHT |
                     GTK_DEST_DEFAULT_MOTION |
                     GTK_DEST_DEFAULT_DROP,
                     &target, 1,
                     GDK_ACTION_COPY);
215
216
217
}

static void
218
gimp_color_area_finalize (GObject *object)
219
{
220
  GimpColorArea *area = GIMP_COLOR_AREA (object);
221

Sven Neumann's avatar
Sven Neumann committed
222
  if (area->buf)
223
    {
Sven Neumann's avatar
Sven Neumann committed
224
      g_free (area->buf);
225
      area->buf = NULL;
226
227
    }

228
  G_OBJECT_CLASS (parent_class)->finalize (object);
229
230
}

231
232
233
234
235
236
237
238
239
240
static void
gimp_color_area_get_property (GObject    *object,
                              guint       property_id,
                              GValue     *value,
                              GParamSpec *pspec)
{
  GimpColorArea *area = GIMP_COLOR_AREA (object);

  switch (property_id)
    {
241
242
243
244
    case PROP_COLOR:
      g_value_set_boxed (value, &area->color);
      break;

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
    case PROP_TYPE:
      g_value_set_enum (value, area->type);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_color_area_set_property (GObject      *object,
                              guint         property_id,
                              const GValue *value,
                              GParamSpec   *pspec)
{
261
262
  GimpColorArea   *area = GIMP_COLOR_AREA (object);
  GdkModifierType  drag_mask;
263
264
265

  switch (property_id)
    {
266
267
268
269
    case PROP_COLOR:
      gimp_color_area_set_color (area, g_value_get_boxed (value));
      break;

270
271
272
273
    case PROP_TYPE:
      gimp_color_area_set_type (area, g_value_get_enum (value));
      break;

274
275
276
277
278
279
280
281
282
283
284
    case PROP_DRAG_MASK:
      drag_mask = g_value_get_flags (value) & (GDK_BUTTON1_MASK |
                                               GDK_BUTTON2_MASK |
                                               GDK_BUTTON3_MASK);
      if (drag_mask)
        gtk_drag_source_set (GTK_WIDGET (area),
                             drag_mask,
                             &target, 1,
                             GDK_ACTION_COPY | GDK_ACTION_MOVE);
      break;

285
286
287
288
289
290
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

291
292
293
294
static void
gimp_color_area_size_allocate (GtkWidget     *widget,
			       GtkAllocation *allocation)
{
295
  GimpColorArea *area = GIMP_COLOR_AREA (widget);
296

297
298
299
  if (GTK_WIDGET_CLASS (parent_class)->size_allocate)
    GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);

Sven Neumann's avatar
Sven Neumann committed
300
301
  if (widget->allocation.width  != area->width ||
      widget->allocation.height != area->height)
302
    {
Sven Neumann's avatar
Sven Neumann committed
303
304
      area->width  = widget->allocation.width;
      area->height = widget->allocation.height;
305

Sven Neumann's avatar
Sven Neumann committed
306
      area->rowstride = (area->width * 3 + 3) & ~0x3;
307

Sven Neumann's avatar
Sven Neumann committed
308
309
      g_free (area->buf);
      area->buf = g_new (guchar, area->rowstride * area->height);
310

311
      area->needs_render = TRUE;
312
    }
313
314
315
316
317
318
}

static gboolean
gimp_color_area_expose (GtkWidget      *widget,
                        GdkEventExpose *event)
{
319
  GimpColorArea *area = GIMP_COLOR_AREA (widget);
320
  guchar        *buf;
321

322
  if (! area->buf || !GTK_WIDGET_DRAWABLE (widget))
323
324
    return FALSE;

325
326
327
  if (area->needs_render)
    gimp_color_area_render (area);

Sven Neumann's avatar
Sven Neumann committed
328
  buf = area->buf + event->area.y * area->rowstride + event->area.x * 3;
329

330
331
  gdk_draw_rgb_image_dithalign (widget->window,
                                widget->style->black_gc,
332
333
334
335
                                event->area.x,
                                event->area.y,
                                event->area.width,
                                event->area.height,
336
                                GDK_RGB_DITHER_MAX,
337
                                buf,
Sven Neumann's avatar
Sven Neumann committed
338
                                area->rowstride,
339
340
                                event->area.x,
                                event->area.y);
341

342
343
344
345
346
347
348
  if (area->draw_border)
    gdk_draw_rectangle (widget->window,
                        widget->style->fg_gc[widget->state],
                        FALSE,
                        0, 0,
                        area->width - 1, area->height - 1);

349
  return FALSE;
350
351
}

352
353
/**
 * gimp_color_area_new:
354
355
 * @color:     A pointer to a #GimpRGB struct.
 * @type:      The type of color area to create.
356
 * @drag_mask: The event_mask that should trigger drags.
357
 *
358
359
360
361
 * Creates a new #GimpColorArea widget.
 *
 * This returns a preview area showing the color. It handles color
 * DND. If the color changes, the "color_changed" signal is emitted.
362
 *
363
364
365
 * Returns: Pointer to the new #GimpColorArea widget.
 **/
GtkWidget *
366
367
368
gimp_color_area_new (const GimpRGB     *color,
		     GimpColorAreaType  type,
		     GdkModifierType    drag_mask)
369
{
370
371
372
373
  return g_object_new (GIMP_TYPE_COLOR_AREA,
                       "color",     color,
                       "type",      type,
                       "drag-mask", drag_mask,
374
                       NULL);
375
376
377
378
}

/**
 * gimp_color_area_set_color:
Sven Neumann's avatar
Sven Neumann committed
379
 * @area: Pointer to a #GimpColorArea.
380
 * @color: Pointer to a #GimpRGB struct that defines the new color.
381
 *
382
 * Sets @area to a different @color.
383
 **/
384
void
Sven Neumann's avatar
Sven Neumann committed
385
gimp_color_area_set_color (GimpColorArea *area,
386
                           const GimpRGB *color)
387
{
Sven Neumann's avatar
Sven Neumann committed
388
  g_return_if_fail (GIMP_IS_COLOR_AREA (area));
389
  g_return_if_fail (color != NULL);
390

391
  if (area->type == GIMP_COLOR_AREA_FLAT)
392
    {
393
394
395
396
397
398
399
400
      if (gimp_rgb_distance (&area->color, color) < 0.000001)
        return;
    }
  else
    {
      if (gimp_rgba_distance (&area->color, color) < 0.000001)
        return;
    }
401

402
  area->color = *color;
403

404
405
406
  area->needs_render = TRUE;
  gtk_widget_queue_draw (GTK_WIDGET (area));

407
408
  g_object_notify (G_OBJECT (area), "color");

409
  g_signal_emit (area, gimp_color_area_signals[COLOR_CHANGED], 0);
410
411
}

412
413
414
415
416
417
418
/**
 * gimp_color_area_get_color:
 * @area: Pointer to a #GimpColorArea.
 * @color: Pointer to a #GimpRGB struct that is used to return the color.
 *
 * Retrieves the current color of the @area.
 **/
419
void
Sven Neumann's avatar
Sven Neumann committed
420
gimp_color_area_get_color (GimpColorArea *area,
421
                           GimpRGB       *color)
422
{
Sven Neumann's avatar
Sven Neumann committed
423
  g_return_if_fail (GIMP_IS_COLOR_AREA (area));
424
  g_return_if_fail (color != NULL);
425

Sven Neumann's avatar
Sven Neumann committed
426
  *color = area->color;
427
428
}

429
430
431
432
433
434
435
436
437
/**
 * gimp_color_area_has_alpha:
 * @area: Pointer to a #GimpColorArea.
 *
 * Checks whether the @area shows transparency information. This is determined
 * via the @area's #GimpColorAreaType.
 *
 * Returns: %TRUE if @area shows transparency information, %FALSE otherwise.
 **/
438
gboolean
Sven Neumann's avatar
Sven Neumann committed
439
gimp_color_area_has_alpha (GimpColorArea *area)
440
{
Sven Neumann's avatar
Sven Neumann committed
441
  g_return_val_if_fail (GIMP_IS_COLOR_AREA (area), FALSE);
442

Sven Neumann's avatar
Sven Neumann committed
443
  return area->type != GIMP_COLOR_AREA_FLAT;
444
445
}

446
447
448
/**
 * gimp_color_area_set_type:
 * @area: Pointer to a #GimpColorArea.
449
 * @type: A #GimpColorAreaType.
450
451
452
453
454
 *
 * Allows to change the type of @area. The #GimpColorAreaType determines
 * whether the widget shows transparency information and chooses the size of
 * the checkerboard used to do that.
 **/
455
void
Sven Neumann's avatar
Sven Neumann committed
456
gimp_color_area_set_type (GimpColorArea     *area,
457
                          GimpColorAreaType  type)
458
{
Sven Neumann's avatar
Sven Neumann committed
459
  g_return_if_fail (GIMP_IS_COLOR_AREA (area));
460

Sven Neumann's avatar
Sven Neumann committed
461
  area->type = type;
462
463
464

  area->needs_render = TRUE;
  gtk_widget_queue_draw (GTK_WIDGET (area));
465
466

  g_object_notify (G_OBJECT (area), "type");
467
468
}

469
470
471
472
473
474
475
476
477
478
479
480
481
/**
 * gimp_color_area_set_draw_border:
 * @area: Pointer to a #GimpColorArea.
 * @draw_border: whether to draw a border or not
 *
 * The @area can draw a thin border in the foreground color around
 * itself.  This function allows to toggle this behaviour on and
 * off. The default is not draw a border.
 **/
void
gimp_color_area_set_draw_border (GimpColorArea *area,
                                 gboolean       draw_border)
{
482
  g_return_if_fail (GIMP_IS_COLOR_AREA (area));
483
484
485
486
487
488

  area->draw_border = draw_border ? TRUE : FALSE;

  gtk_widget_queue_draw (GTK_WIDGET (area));
}

489
490
491
492
493
494
495
void
_gimp_color_area_render_buf (GimpColorAreaType  type,
                             guchar            *buf,
                             guint              width,
                             guint              height,
                             guint              rowstride,
                             GimpRGB           *color)
496
{
497
498
499
500
501
502
503
  guint    x, y;
  guint    check_size = 0;
  guchar   light[3];
  guchar   dark[3];
  guchar   opaque[3];
  guchar  *p;
  gdouble  frac;
504

505
  switch (type)
506
507
508
509
510
511
512
513
514
515
516
517
518
    {
    case GIMP_COLOR_AREA_FLAT:
      check_size = 0;
      break;

    case GIMP_COLOR_AREA_SMALL_CHECKS:
      check_size = GIMP_CHECK_SIZE_SM;
      break;

    case GIMP_COLOR_AREA_LARGE_CHECKS:
      check_size = GIMP_CHECK_SIZE;
      break;
    }
519

520
  gimp_rgb_get_uchar (color, opaque, opaque + 1, opaque + 2);
521

522
  if (color->a == 1.0 || !check_size)
523
524
    {
      for (y = 0; y < height; y++)
525
        {
526
          p = buf + y * rowstride;
527
528
529
530
531
532
533
534

          for (x = 0; x < width; x++)
            {
              *p++ = opaque[0];
              *p++ = opaque[1];
              *p++ = opaque[2];
            }
        }
535

536
      return;
537
538
    }

539
  light[0] = (GIMP_CHECK_LIGHT +
540
              (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.999;
541
  dark[0]  = (GIMP_CHECK_DARK +
542
              (color->r - GIMP_CHECK_DARK)  * color->a) * 255.999;
543
  light[1] = (GIMP_CHECK_LIGHT +
544
              (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.999;
545
  dark[1]  = (GIMP_CHECK_DARK +
546
              (color->g - GIMP_CHECK_DARK)  * color->a) * 255.999;
547
  light[2] = (GIMP_CHECK_LIGHT +
548
              (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.999;
549
  dark[2]  = (GIMP_CHECK_DARK +
550
              (color->b - GIMP_CHECK_DARK)  * color->a) * 255.999;
551

552
553
  for (y = 0; y < height; y++)
    {
554
      p = buf + y * rowstride;
555

556
557
558
559
560
561
562
      for (x = 0; x < width; x++)
        {
          if ((width - x) * height > y * width)
            {
              *p++ = opaque[0];
              *p++ = opaque[1];
              *p++ = opaque[2];
563

564
565
              continue;
            }
566

567
          frac = y - (gdouble) ((width - x) * height) / (gdouble) width;
568
569

          if (((x / check_size) ^ (y / check_size)) & 1)
570
571
572
573
574
575
576
577
578
            {
              if ((gint) frac)
                {
                  *p++ = light[0];
                  *p++ = light[1];
                  *p++ = light[2];
                }
              else
                {
579
                  *p++ = ((gdouble) light[0]  * frac +
580
                          (gdouble) opaque[0] * (1.0 - frac));
581
                  *p++ = ((gdouble) light[1]  * frac +
582
                          (gdouble) opaque[1] * (1.0 - frac));
583
                  *p++ = ((gdouble) light[2]  * frac +
584
585
586
587
588
589
590
591
592
593
594
595
596
                          (gdouble) opaque[2] * (1.0 - frac));
                }
            }
          else
            {
              if ((gint) frac)
                {
                  *p++ = dark[0];
                  *p++ = dark[1];
                  *p++ = dark[2];
                }
              else
                {
597
                  *p++ = ((gdouble) dark[0] * frac +
598
                          (gdouble) opaque[0] * (1.0 - frac));
599
                  *p++ = ((gdouble) dark[1] * frac +
600
                          (gdouble) opaque[1] * (1.0 - frac));
601
                  *p++ = ((gdouble) dark[2] * frac +
602
603
604
605
606
                          (gdouble) opaque[2] * (1.0 - frac));
                }
            }
        }
    }
607
}
608
609
610
611
612
613
614
615
616
617
618
619
620
static void
gimp_color_area_render (GimpColorArea *area)
{
  area->needs_render = FALSE;

  if (! area->buf)
    return;

  _gimp_color_area_render_buf (area->type,
                               area->buf,
                               area->width, area->height, area->rowstride,
                               &area->color);
}
621
622
623
624
625

static void
gimp_color_area_drag_begin (GtkWidget      *widget,
			    GdkDragContext *context)
{
626
627
628
629
  GimpRGB    color;
  GtkWidget *window;
  GtkWidget *frame;
  GtkWidget *color_area;
630
631
632

  window = gtk_window_new (GTK_WINDOW_POPUP);
  gtk_widget_realize (window);
633
634
635
636
637
638
639

  frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
  gtk_container_add (GTK_CONTAINER (window), frame);

  gimp_color_area_get_color (GIMP_COLOR_AREA (widget), &color);

640
641
642
  color_area = gimp_color_area_new (&color,
                                    GIMP_COLOR_AREA (widget)->type,
                                    0);
643

644
  gtk_widget_set_size_request (color_area,
645
                               DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);
646
647
648
649
  gtk_container_add (GTK_CONTAINER (frame), color_area);
  gtk_widget_show (color_area);
  gtk_widget_show (frame);

650
651
652
653
  g_object_set_data_full (G_OBJECT (widget),
                          "gimp-color-area-drag-window",
                          window,
                          (GDestroyNotify) gtk_widget_destroy);
654

655
  gtk_drag_set_icon_widget (context, window,
656
                            DRAG_ICON_OFFSET, DRAG_ICON_OFFSET);
657
658
659
660
}

static void
gimp_color_area_drag_end (GtkWidget      *widget,
661
                          GdkDragContext *context)
662
{
663
664
  g_object_set_data (G_OBJECT (widget),
                     "gimp-color-area-drag-window", NULL);
665
666
667
}

static void
668
gimp_color_area_drag_data_received (GtkWidget        *widget,
669
670
671
672
673
674
                                    GdkDragContext   *context,
                                    gint              x,
                                    gint              y,
                                    GtkSelectionData *selection_data,
                                    guint             info,
                                    guint             time)
675
{
676
  GimpColorArea *area = GIMP_COLOR_AREA (widget);
677
678
679
680
681
682
  GimpRGB        color;
  guint16       *vals;

  if (selection_data->length < 0)
    return;

683
  if ((selection_data->format != 16) ||
684
685
      (selection_data->length != 8))
    {
686
      g_warning ("Received invalid color data");
687
688
689
690
691
      return;
    }

  vals = (guint16 *)selection_data->data;

692
  gimp_rgba_set (&color,
693
694
695
696
                 (gdouble) vals[0] / 0xffff,
                 (gdouble) vals[1] / 0xffff,
                 (gdouble) vals[2] / 0xffff,
                 (gdouble) vals[3] / 0xffff);
697

Sven Neumann's avatar
Sven Neumann committed
698
  gimp_color_area_set_color (area, &color);
699
700
701
}

static void
702
gimp_color_area_drag_data_get (GtkWidget        *widget,
703
704
705
706
                               GdkDragContext   *context,
                               GtkSelectionData *selection_data,
                               guint             info,
                               guint             time)
707
{
708
  GimpColorArea *area = GIMP_COLOR_AREA (widget);
709
710
  guint16        vals[4];

Sven Neumann's avatar
Sven Neumann committed
711
712
713
  vals[0] = area->color.r * 0xffff;
  vals[1] = area->color.g * 0xffff;
  vals[2] = area->color.b * 0xffff;
714

Sven Neumann's avatar
Sven Neumann committed
715
  if (area->type == GIMP_COLOR_AREA_FLAT)
716
    vals[3] = 0xffff;
717
  else
Sven Neumann's avatar
Sven Neumann committed
718
    vals[3] = area->color.a * 0xffff;
719
720

  gtk_selection_data_set (selection_data,
721
722
                          gdk_atom_intern ("application/x-color", FALSE),
                          16, (guchar *) vals, 8);
723
}