gtkcolorsel.c 97.6 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
2
 * Copyright (C) 2000 Red Hat, Inc.
Elliot Lee's avatar
Elliot Lee committed
3 4 5
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
Javier Jardon's avatar
Javier Jardon committed
16
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
17
 */
18 19

/*
20
 * Modified by the GTK+ Team and others 1997-2001.  See the AUTHORS
21 22
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
23
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
24 25
 */

26
#include "config.h"
27

28 29
#define GDK_DISABLE_DEPRECATION_WARNINGS

30 31
#include "gtkcolorsel.h"

32
#include <math.h>
33
#include <string.h>
34

35
#include "gdk/gdk.h"
36
#include "gtkadjustment.h"
37
#include "gtkorientable.h"
38
#include "gtkhsv.h"
39
#include "gtkwindowgroup.h"
40
#include "gtkselection.h"
41
#include "gtkcolorutils.h"
42
#include "gtkdnd.h"
43
#include "gtkdragsource.h"
44
#include "gtkdragdest.h"
45 46
#include "gtkdrawingarea.h"
#include "gtkframe.h"
47
#include "gtkgrid.h"
48
#include "gtklabel.h"
49
#include "gtkmarshalers.h"
Manish Singh's avatar
Manish Singh committed
50
#include "gtkimage.h"
51 52
#include "gtkspinbutton.h"
#include "gtkrange.h"
Matthias Clasen's avatar
Matthias Clasen committed
53
#include "gtkscale.h"
54 55
#include "gtkentry.h"
#include "gtkbutton.h"
56 57 58
#include "gtkmenuitem.h"
#include "gtkmain.h"
#include "gtksettings.h"
59
#include "gtkstock.h"
60
#include "gtkaccessible.h"
61
#include "gtksizerequest.h"
Matthias Clasen's avatar
Matthias Clasen committed
62
#include "gtkseparator.h"
63 64
#include "gtkprivate.h"
#include "gtkintl.h"
Elliot Lee's avatar
Elliot Lee committed
65

66 67 68

/**
 * SECTION:gtkcolorsel
69
 * @Short_description: Deprecated widget used to select a color
70 71 72 73 74 75 76 77 78 79
 * @Title: GtkColorSelection
 *
 * The #GtkColorSelection is a widget that is used to select
 * a color.  It consists of a color wheel and number of sliders
 * and entry boxes for color parameters such as hue, saturation,
 * value, red, green, blue, and opacity.  It is found on the standard
 * color selection dialog box #GtkColorSelectionDialog.
 */


80 81 82
/* Keep it in sync with gtksettings.c:default_color_palette */
#define DEFAULT_COLOR_PALETTE   "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90"

83 84 85 86
/* Number of elements in the custom palatte */
#define GTK_CUSTOM_PALETTE_WIDTH 10
#define GTK_CUSTOM_PALETTE_HEIGHT 2

87 88 89 90 91 92
#define CUSTOM_PALETTE_ENTRY_WIDTH   20
#define CUSTOM_PALETTE_ENTRY_HEIGHT  20

/* The cursor for the dropper */
#define DROPPER_WIDTH 17
#define DROPPER_HEIGHT 17
93
#define DROPPER_STRIDE (DROPPER_WIDTH * 4)
94 95 96 97 98
#define DROPPER_X_HOT 2
#define DROPPER_Y_HOT 16

#define SAMPLE_WIDTH  64
#define SAMPLE_HEIGHT 28
99
#define CHECK_SIZE 16
100 101
#define BIG_STEP 20

102 103 104 105 106
/* Conversion between 0->1 double and and guint16. See
 * scale_round() below for more general conversions
 */
#define SCALE(i) (i / 65535.)
#define UNSCALE(d) ((guint16)(d * 65535 + 0.5))
107
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
108

109
enum {
Elliot Lee's avatar
Elliot Lee committed
110 111 112 113
  COLOR_CHANGED,
  LAST_SIGNAL
};

114 115 116 117 118
enum {
  PROP_0,
  PROP_HAS_PALETTE,
  PROP_HAS_OPACITY_CONTROL,
  PROP_CURRENT_COLOR,
119 120
  PROP_CURRENT_ALPHA,
  PROP_CURRENT_RGBA
121 122
};

123
enum {
124 125 126 127 128 129 130 131
  COLORSEL_RED = 0,
  COLORSEL_GREEN = 1,
  COLORSEL_BLUE = 2,
  COLORSEL_OPACITY = 3,
  COLORSEL_HUE,
  COLORSEL_SATURATION,
  COLORSEL_VALUE,
  COLORSEL_NUM_CHANNELS
Elliot Lee's avatar
Elliot Lee committed
132 133
};

134

135
struct _GtkColorSelectionPrivate
Elliot Lee's avatar
Elliot Lee committed
136
{
137 138 139 140
  guint has_opacity       : 1;
  guint has_palette       : 1;
  guint changing          : 1;
  guint default_set       : 1;
141
  guint default_alpha_set : 1;
142 143
  guint has_grab          : 1;

144 145
  gdouble color[COLORSEL_NUM_CHANNELS];
  gdouble old_color[COLORSEL_NUM_CHANNELS];
146

147 148 149 150 151 152 153 154 155 156 157 158
  GtkWidget *triangle_colorsel;
  GtkWidget *hue_spinbutton;
  GtkWidget *sat_spinbutton;
  GtkWidget *val_spinbutton;
  GtkWidget *red_spinbutton;
  GtkWidget *green_spinbutton;
  GtkWidget *blue_spinbutton;
  GtkWidget *opacity_slider;
  GtkWidget *opacity_label;
  GtkWidget *opacity_entry;
  GtkWidget *palette_frame;
  GtkWidget *hex_entry;
159

160
  /* The Palette code */
161
  GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT];
162

163 164 165 166 167
  /* The color_sample stuff */
  GtkWidget *sample_area;
  GtkWidget *old_sample;
  GtkWidget *cur_sample;
  GtkWidget *colorsel;
168 169 170

  /* Window for grabbing on */
  GtkWidget *dropper_grab_widget;
171
  guint32    grab_time;
172 173
  GdkDevice *keyboard_device;
  GdkDevice *pointer_device;
174 175

  /* Connection to settings */
176
  gulong settings_connection;
Elliot Lee's avatar
Elliot Lee committed
177 178 179
};


180 181 182
static void gtk_color_selection_destroy         (GtkWidget               *widget);
static void gtk_color_selection_finalize        (GObject                 *object);
static void update_color                        (GtkColorSelection       *colorsel);
183
static void gtk_color_selection_set_property    (GObject                 *object,
184 185 186
                                                 guint                    prop_id,
                                                 const GValue            *value,
                                                 GParamSpec              *pspec);
187
static void gtk_color_selection_get_property    (GObject                 *object,
188 189 190
                                                 guint                    prop_id,
                                                 GValue                  *value,
                                                 GParamSpec              *pspec);
191

192 193
static void gtk_color_selection_realize         (GtkWidget               *widget);
static void gtk_color_selection_unrealize       (GtkWidget               *widget);
194
static void gtk_color_selection_show_all        (GtkWidget               *widget);
195
static gboolean gtk_color_selection_grab_broken (GtkWidget               *widget,
196
                                                 GdkEventGrabBroken      *event);
197

198 199 200
static void     gtk_color_selection_set_palette_color   (GtkColorSelection *colorsel,
                                                         gint               index,
                                                         GdkColor          *color);
201
static void     set_focus_line_attributes               (GtkWidget         *drawing_area,
202 203
                                                         cairo_t           *cr,
                                                         gint              *focus_width);
204
static void     default_noscreen_change_palette_func    (const GdkColor    *colors,
205 206 207 208
                                                         gint               n_colors);
static void     default_change_palette_func             (GdkScreen         *screen,
                                                         const GdkColor    *colors,
                                                         gint               n_colors);
209 210 211
static void     make_control_relations                  (AtkObject         *atk_obj,
                                                         GtkWidget         *widget);
static void     make_all_relations                      (AtkObject         *atk_obj,
212
                                                         GtkColorSelectionPrivate *priv);
213

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
static void     hsv_changed                             (GtkWidget         *hsv,
                                                         gpointer           data);
static void     get_screen_color                        (GtkWidget         *button);
static void     adjustment_changed                      (GtkAdjustment     *adjustment,
                                                         gpointer           data);
static void     opacity_entry_changed                   (GtkWidget         *opacity_entry,
                                                         gpointer           data);
static void     hex_changed                             (GtkWidget         *hex_entry,
                                                         gpointer           data);
static gboolean hex_focus_out                           (GtkWidget         *hex_entry,
                                                         GdkEventFocus     *event,
                                                         gpointer           data);
static void     color_sample_new                        (GtkColorSelection *colorsel);
static void     make_label_spinbutton                   (GtkColorSelection *colorsel,
                                                         GtkWidget        **spinbutton,
                                                         gchar             *text,
                                                         GtkWidget         *table,
                                                         gint               i,
                                                         gint               j,
                                                         gint               channel_type,
                                                         const gchar       *tooltip);
static void     make_palette_frame                      (GtkColorSelection *colorsel,
                                                         GtkWidget         *table,
                                                         gint               i,
                                                         gint               j);
static void     set_selected_palette                    (GtkColorSelection *colorsel,
                                                         int                x,
                                                         int                y);
static void     set_focus_line_attributes               (GtkWidget         *drawing_area,
                                                         cairo_t           *cr,
                                                         gint              *focus_width);
static gboolean mouse_press                             (GtkWidget         *invisible,
                                                         GdkEventButton    *event,
                                                         gpointer           data);
248
static void  palette_change_notify_instance (GObject    *object,
249 250
                                             GParamSpec *pspec,
                                             gpointer    data);
251 252 253
static void update_palette (GtkColorSelection *colorsel);
static void shutdown_eyedropper (GtkWidget *widget);

254 255
static guint color_selection_signals[LAST_SIGNAL] = { 0 };

256 257
static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func;
static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func;
258

Matthias Clasen's avatar
Matthias Clasen committed
259
static const guchar dropper_bits[] = {
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\377\377\377\377"
  "\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\0\0\0\377"
  "\0\0\0\377\0\0\0\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377"
  "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
  "\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0"
  "\0\377\0\0\0\377\0\0\0\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\0\0\0\377\0\0\0\377\0"
  "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377"
  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0"
  "\0\0\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\0\0\0\377\0\0"
  "\0\377\0\0\0\377\377\377\377\377\377\377\377\377\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377"
  "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\377\377"
  "\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377"
  "\0\0\0\377\377\377\377\377\0\0\0\377\377\377\377\377\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377"
  "\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\0\0\0\0\0\377\377"
  "\377\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0"
  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\377\377\377\377"
  "\377\377\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377"
  "\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\377\377\377\0\0"
  "\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
  "\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
301

302
G_DEFINE_TYPE_WITH_PRIVATE (GtkColorSelection, gtk_color_selection, GTK_TYPE_BOX)
Elliot Lee's avatar
Elliot Lee committed
303

304
static void
305
gtk_color_selection_class_init (GtkColorSelectionClass *klass)
306
{
307 308
  GObjectClass *gobject_class;
  GtkWidgetClass *widget_class;
309

310 311 312 313
  gobject_class = G_OBJECT_CLASS (klass);
  gobject_class->finalize = gtk_color_selection_finalize;
  gobject_class->set_property = gtk_color_selection_set_property;
  gobject_class->get_property = gtk_color_selection_get_property;
314

315
  widget_class = GTK_WIDGET_CLASS (klass);
316
  widget_class->destroy = gtk_color_selection_destroy;
317 318 319 320
  widget_class->realize = gtk_color_selection_realize;
  widget_class->unrealize = gtk_color_selection_unrealize;
  widget_class->show_all = gtk_color_selection_show_all;
  widget_class->grab_broken_event = gtk_color_selection_grab_broken;
321

322 323 324
  g_object_class_install_property (gobject_class,
                                   PROP_HAS_OPACITY_CONTROL,
                                   g_param_spec_boolean ("has-opacity-control",
325 326 327 328
                                                         P_("Has Opacity Control"),
                                                         P_("Whether the color selector should allow setting opacity"),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
329 330 331
  g_object_class_install_property (gobject_class,
                                   PROP_HAS_PALETTE,
                                   g_param_spec_boolean ("has-palette",
332 333 334 335
                                                         P_("Has palette"),
                                                         P_("Whether a palette should be used"),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
336 337

  /**
338
   * GtkColorSelection:current-color:
339 340 341 342 343
   *
   * The current GdkColor color.
   *
   * Deprecated: 3.4: Use #GtkColorSelection:current-rgba instead.
   */
344 345 346 347 348 349
  g_object_class_install_property (gobject_class,
                                   PROP_CURRENT_COLOR,
                                   g_param_spec_boxed ("current-color",
                                                       P_("Current Color"),
                                                       P_("The current color"),
                                                       GDK_TYPE_COLOR,
350
                                                       GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
351 352 353
  g_object_class_install_property (gobject_class,
                                   PROP_CURRENT_ALPHA,
                                   g_param_spec_uint ("current-alpha",
354 355 356 357
                                                      P_("Current Alpha"),
                                                      P_("The current opacity value (0 fully transparent, 65535 fully opaque)"),
                                                      0, 65535, 65535,
                                                      GTK_PARAM_READWRITE));
358 359

  /**
360
   * GtkColorSelection:current-rgba:
361 362 363 364 365 366 367 368 369 370 371 372 373
   *
   * The current RGBA color.
   *
   * Since: 3.0
   */
  g_object_class_install_property (gobject_class,
                                   PROP_CURRENT_RGBA,
                                   g_param_spec_boxed ("current-rgba",
                                                       P_("Current RGBA"),
                                                       P_("The current RGBA color"),
                                                       GDK_TYPE_RGBA,
                                                       GTK_PARAM_READWRITE));

374 375 376 377 378 379 380
  /**
   * GtkColorSelection::color-changed:
   * @colorselection: the object which received the signal.
   *
   * This signal is emitted when the color changes in the #GtkColorSelection
   * according to its update policy.
   */
381
  color_selection_signals[COLOR_CHANGED] =
382
    g_signal_new (I_("color-changed"),
383 384 385 386
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed),
                  NULL, NULL,
387
                  NULL,
388
                  G_TYPE_NONE, 0);
389
}
Elliot Lee's avatar
Elliot Lee committed
390

391
static void
392
gtk_color_selection_init (GtkColorSelection *colorsel)
393
{
394 395 396 397 398 399
  GtkWidget *top_hbox;
  GtkWidget *top_right_vbox;
  GtkWidget *table, *label, *hbox, *frame, *vbox, *button;
  GtkAdjustment *adjust;
  GtkWidget *picker_image;
  gint i, j;
400
  GtkColorSelectionPrivate *priv;
401 402
  AtkObject *atk_obj;
  GList *focus_chain = NULL;
403

404 405 406
  gtk_orientable_set_orientation (GTK_ORIENTABLE (colorsel),
                                  GTK_ORIENTATION_VERTICAL);

407
  gtk_widget_push_composite_child ();
408

409
  priv = colorsel->private_data = gtk_color_selection_get_instance_private (colorsel);
410 411 412
  priv->changing = FALSE;
  priv->default_set = FALSE;
  priv->default_alpha_set = FALSE;
413

414
  top_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
415
  gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0);
416

417
  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
418 419 420 421 422 423 424
  priv->triangle_colorsel = gtk_hsv_new ();
  g_signal_connect (priv->triangle_colorsel, "changed",
                    G_CALLBACK (hsv_changed), colorsel);
  gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 174, 15);
  gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0);
  gtk_widget_set_tooltip_text (priv->triangle_colorsel,
425 426 427 428
                        _("Select the color you want from the outer ring. "
                          "Select the darkness or lightness of that color "
                          "using the inner triangle."));

429
  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
430
  gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
431

432 433 434 435 436 437
  frame = gtk_frame_new (NULL);
  gtk_widget_set_size_request (frame, -1, 30);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  color_sample_new (colorsel);
  gtk_container_add (GTK_CONTAINER (frame), priv->sample_area);
  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
438

439
  button = gtk_button_new ();
Elliot Lee's avatar
Elliot Lee committed
440

441
  gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
442
  g_object_set_data (G_OBJECT (button), I_("COLORSEL"), colorsel);
443 444 445 446 447 448 449 450
  g_signal_connect (button, "clicked",
                    G_CALLBACK (get_screen_color), NULL);
  picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON);
  gtk_container_add (GTK_CONTAINER (button), picker_image);
  gtk_widget_show (GTK_WIDGET (picker_image));
  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);

  gtk_widget_set_tooltip_text (button,
451 452 453
                        _("Click the eyedropper, then click a color "
                          "anywhere on your screen to select that color."));

454
  top_right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
455
  gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, FALSE, FALSE, 0);
456
  table = gtk_grid_new ();
457
  gtk_box_pack_start (GTK_BOX (top_right_vbox), table, FALSE, FALSE, 0);
458 459
  gtk_grid_set_row_spacing (GTK_GRID (table), 6);
  gtk_grid_set_column_spacing (GTK_GRID (table), 12);
460

461 462 463
  make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("_Hue:"), table, 0, 0, COLORSEL_HUE,
                         _("Position on the color wheel."));
  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE);
464
  make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("S_aturation:"), table, 0, 1, COLORSEL_SATURATION,
465
                         _("Intensity of the color."));
466 467 468 469 470 471 472 473
  make_label_spinbutton (colorsel, &priv->val_spinbutton, _("_Value:"), table, 0, 2, COLORSEL_VALUE,
                         _("Brightness of the color."));
  make_label_spinbutton (colorsel, &priv->red_spinbutton, _("_Red:"), table, 6, 0, COLORSEL_RED,
                         _("Amount of red light in the color."));
  make_label_spinbutton (colorsel, &priv->green_spinbutton, _("_Green:"), table, 6, 1, COLORSEL_GREEN,
                         _("Amount of green light in the color."));
  make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("_Blue:"), table, 6, 2, COLORSEL_BLUE,
                         _("Amount of blue light in the color."));
474
  gtk_grid_attach (GTK_GRID (table), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL), 0, 3, 8, 1);
475

476
  priv->opacity_label = gtk_label_new_with_mnemonic (_("Op_acity:"));
477 478
  gtk_widget_set_halign (priv->opacity_label, GTK_ALIGN_START);
  gtk_widget_set_valign (priv->opacity_label, GTK_ALIGN_CENTER);
479
  gtk_grid_attach (GTK_GRID (table), priv->opacity_label, 0, 4, 1, 1);
Javier Jardon's avatar
Javier Jardon committed
480
  adjust = gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0);
481
  g_object_set_data (G_OBJECT (adjust), I_("COLORSEL"), colorsel);
482
  priv->opacity_slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adjust);
483 484 485 486 487
  gtk_widget_set_tooltip_text (priv->opacity_slider,
                        _("Transparency of the color."));
  gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label),
                                 priv->opacity_slider);
  gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE);
488
  g_signal_connect (adjust, "value-changed",
489 490
                    G_CALLBACK (adjustment_changed),
                    GINT_TO_POINTER (COLORSEL_OPACITY));
491
  gtk_grid_attach (GTK_GRID (table), priv->opacity_slider, 1, 4, 6, 1);
492
  priv->opacity_entry = gtk_entry_new ();
493 494
  gtk_widget_set_tooltip_text (priv->opacity_entry,
                        _("Transparency of the color."));
495
  gtk_widget_set_size_request (priv->opacity_entry, 40, -1);
496

497 498
  g_signal_connect (priv->opacity_entry, "activate",
                    G_CALLBACK (opacity_entry_changed), colorsel);
499
  gtk_grid_attach (GTK_GRID (table), priv->opacity_entry, 7, 4, 1, 1);
500

501
  label = gtk_label_new_with_mnemonic (_("Color _name:"));
502
  gtk_grid_attach (GTK_GRID (table), label, 0, 5, 1, 1);
503 504
  gtk_widget_set_halign (label, GTK_ALIGN_START);
  gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
505
  priv->hex_entry = gtk_entry_new ();
506

507 508 509 510 511
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry);

  g_signal_connect (priv->hex_entry, "activate",
                    G_CALLBACK (hex_changed), colorsel);

512
  g_signal_connect (priv->hex_entry, "focus-out-event",
513 514 515
                    G_CALLBACK (hex_focus_out), colorsel);

  gtk_widget_set_tooltip_text (priv->hex_entry,
516
                        _("You can enter an HTML-style hexadecimal color "
517
                          "value, or simply a color name such as “orange” "
518 519
                          "in this entry."));

520
  gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7);
521
  gtk_grid_attach (GTK_GRID (table), priv->hex_entry, 1, 5, 4, 1);
522

523 524 525 526 527 528 529 530 531 532 533
  focus_chain = g_list_append (focus_chain, priv->hue_spinbutton);
  focus_chain = g_list_append (focus_chain, priv->sat_spinbutton);
  focus_chain = g_list_append (focus_chain, priv->val_spinbutton);
  focus_chain = g_list_append (focus_chain, priv->red_spinbutton);
  focus_chain = g_list_append (focus_chain, priv->green_spinbutton);
  focus_chain = g_list_append (focus_chain, priv->blue_spinbutton);
  focus_chain = g_list_append (focus_chain, priv->opacity_slider);
  focus_chain = g_list_append (focus_chain, priv->opacity_entry);
  focus_chain = g_list_append (focus_chain, priv->hex_entry);
  gtk_container_set_focus_chain (GTK_CONTAINER (table), focus_chain);
  g_list_free (focus_chain);
534

535
  /* Set up the palette */
536 537 538
  table = gtk_grid_new ();
  gtk_grid_set_row_spacing (GTK_GRID (table), 1);
  gtk_grid_set_column_spacing (GTK_GRID (table), 1);
539 540 541
  for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++)
    {
      for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++)
542 543 544
        {
          make_palette_frame (colorsel, table, i, j);
        }
545
    }
546
  set_selected_palette (colorsel, 0, 0);
547
  priv->palette_frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
548
  label = gtk_label_new_with_mnemonic (_("_Palette:"));
549 550
  gtk_widget_set_halign (label, GTK_ALIGN_START);
  gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
551
  gtk_box_pack_start (GTK_BOX (priv->palette_frame), label, FALSE, FALSE, 0);
552

553 554
  gtk_label_set_mnemonic_widget (GTK_LABEL (label),
                                 priv->custom_palette[0][0]);
555

556 557
  gtk_box_pack_end (GTK_BOX (top_right_vbox), priv->palette_frame, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (priv->palette_frame), table, FALSE, FALSE, 0);
558

559 560 561
  gtk_widget_show_all (top_hbox);

  /* hide unused stuff */
562

563
  if (priv->has_opacity == FALSE)
Elliot Lee's avatar
Elliot Lee committed
564
    {
565 566 567
      gtk_widget_hide (priv->opacity_label);
      gtk_widget_hide (priv->opacity_slider);
      gtk_widget_hide (priv->opacity_entry);
Elliot Lee's avatar
Elliot Lee committed
568
    }
569

570
  if (priv->has_palette == FALSE)
Elliot Lee's avatar
Elliot Lee committed
571
    {
572
      gtk_widget_hide (priv->palette_frame);
Elliot Lee's avatar
Elliot Lee committed
573
    }
574

575 576 577 578 579 580
  atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel);
  if (GTK_IS_ACCESSIBLE (atk_obj))
    {
      atk_object_set_name (atk_obj, _("Color Wheel"));
      atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER);
      make_all_relations (atk_obj, priv);
581
    }
582

583
  gtk_widget_pop_composite_child ();
Elliot Lee's avatar
Elliot Lee committed
584 585
}

586
/* GObject methods */
587
static void
588
gtk_color_selection_finalize (GObject *object)
589
{
590
  G_OBJECT_CLASS (gtk_color_selection_parent_class)->finalize (object);
Elliot Lee's avatar
Elliot Lee committed
591 592
}

593 594
static void
gtk_color_selection_set_property (GObject         *object,
595 596 597
                                  guint            prop_id,
                                  const GValue    *value,
                                  GParamSpec      *pspec)
Elliot Lee's avatar
Elliot Lee committed
598
{
599
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
600

601 602 603
  switch (prop_id)
    {
    case PROP_HAS_OPACITY_CONTROL:
604 605
      gtk_color_selection_set_has_opacity_control (colorsel,
                                                   g_value_get_boolean (value));
606 607
      break;
    case PROP_HAS_PALETTE:
608 609
      gtk_color_selection_set_has_palette (colorsel,
                                           g_value_get_boolean (value));
610 611
      break;
    case PROP_CURRENT_COLOR:
612 613 614 615 616 617 618 619 620 621 622 623 624
      {
        GdkColor *color;
        GdkRGBA rgba;

        color = g_value_get_boxed (value);

        rgba.red = SCALE (color->red);
        rgba.green = SCALE (color->green);;
        rgba.blue = SCALE (color->blue);
        rgba.alpha = 1.0;

        gtk_color_selection_set_current_rgba (colorsel, &rgba);
      }
625 626 627 628
      break;
    case PROP_CURRENT_ALPHA:
      gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value));
      break;
629 630 631
    case PROP_CURRENT_RGBA:
      gtk_color_selection_set_current_rgba (colorsel, g_value_get_boxed (value));
      break;
632 633 634 635
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
636

637
}
638

639
static void
640
gtk_color_selection_get_property (GObject     *object,
641 642 643
                                  guint        prop_id,
                                  GValue      *value,
                                  GParamSpec  *pspec)
644
{
645
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object);
646

647
  switch (prop_id)
648
    {
649 650 651 652 653 654 655
    case PROP_HAS_OPACITY_CONTROL:
      g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel));
      break;
    case PROP_HAS_PALETTE:
      g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel));
      break;
    case PROP_CURRENT_COLOR:
656 657 658 659 660 661 662 663 664 665 666 667
      {
        GdkColor color;
        GdkRGBA rgba;

        gtk_color_selection_get_current_rgba (colorsel, &rgba);

        color.red = UNSCALE (rgba.red);
        color.green = UNSCALE (rgba.green);
        color.blue = UNSCALE (rgba.blue);

        g_value_set_boxed (value, &color);
      }
668 669 670 671
      break;
    case PROP_CURRENT_ALPHA:
      g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel));
      break;
672 673 674 675 676 677 678 679
    case PROP_CURRENT_RGBA:
      {
        GdkRGBA rgba;

        gtk_color_selection_get_current_rgba (colorsel, &rgba);
        g_value_set_boxed (value, &rgba);
      }
      break;
680 681 682
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
683
    }
Elliot Lee's avatar
Elliot Lee committed
684 685
}

686
/* GtkWidget methods */
687

688
static void
689
gtk_color_selection_destroy (GtkWidget *widget)
690
{
691
  GtkColorSelection *cselection = GTK_COLOR_SELECTION (widget);
692
  GtkColorSelectionPrivate *priv = cselection->private_data;
693

694 695 696 697 698
  if (priv->dropper_grab_widget)
    {
      gtk_widget_destroy (priv->dropper_grab_widget);
      priv->dropper_grab_widget = NULL;
    }
699

700
  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->destroy (widget);
701
}
702

703 704 705 706
static void
gtk_color_selection_realize (GtkWidget *widget)
{
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
707
  GtkColorSelectionPrivate *priv = colorsel->private_data;
708 709 710
  GtkSettings *settings = gtk_widget_get_settings (widget);

  priv->settings_connection =  g_signal_connect (settings,
711 712 713
                                                 "notify::gtk-color-palette",
                                                 G_CALLBACK (palette_change_notify_instance),
                                                 widget);
714 715 716 717 718 719 720 721 722
  update_palette (colorsel);

  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->realize (widget);
}

static void
gtk_color_selection_unrealize (GtkWidget *widget)
{
  GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget);
723
  GtkColorSelectionPrivate *priv = colorsel->private_data;
724 725 726 727 728 729 730 731
  GtkSettings *settings = gtk_widget_get_settings (widget);

  g_signal_handler_disconnect (settings, priv->settings_connection);

  GTK_WIDGET_CLASS (gtk_color_selection_parent_class)->unrealize (widget);
}

/* We override show-all since we have internal widgets that
732
 * shouldn’t be shown when you call show_all(), like the
733 734 735 736 737 738
 * palette and opacity sliders.
 */
static void
gtk_color_selection_show_all (GtkWidget *widget)
{
  gtk_widget_show (widget);
Elliot Lee's avatar
Elliot Lee committed
739 740
}

741
static gboolean
742
gtk_color_selection_grab_broken (GtkWidget          *widget,
743
                                 GdkEventGrabBroken *event)
744 745 746 747 748
{
  shutdown_eyedropper (widget);

  return TRUE;
}
749 750 751

/*
 *
752
 * The Sample Color
753 754
 *
 */
755

756 757 758
static void color_sample_draw_sample (GtkColorSelection *colorsel,
                                      int                which,
                                      cairo_t *          cr);
759
static void color_sample_update_samples (GtkColorSelection *colorsel);
760

Elliot Lee's avatar
Elliot Lee committed
761
static void
762
set_color_internal (GtkColorSelection *colorsel,
763
                    gdouble           *color)
Elliot Lee's avatar
Elliot Lee committed
764
{
765
  GtkColorSelectionPrivate *priv;
766
  gint i;
767

768 769 770 771 772 773 774
  priv = colorsel->private_data;
  priv->changing = TRUE;
  priv->color[COLORSEL_RED] = color[0];
  priv->color[COLORSEL_GREEN] = color[1];
  priv->color[COLORSEL_BLUE] = color[2];
  priv->color[COLORSEL_OPACITY] = color[3];
  gtk_rgb_to_hsv (priv->color[COLORSEL_RED],
775 776 777 778 779
                  priv->color[COLORSEL_GREEN],
                  priv->color[COLORSEL_BLUE],
                  &priv->color[COLORSEL_HUE],
                  &priv->color[COLORSEL_SATURATION],
                  &priv->color[COLORSEL_VALUE]);
780
  if (priv->default_set == FALSE)
Elliot Lee's avatar
Elliot Lee committed
781
    {
782
      for (i = 0; i < COLORSEL_NUM_CHANNELS; i++)
783
        priv->old_color[i] = priv->color[i];
Elliot Lee's avatar
Elliot Lee committed
784
    }
785 786 787
  priv->default_set = TRUE;
  priv->default_alpha_set = TRUE;
  update_color (colorsel);
Elliot Lee's avatar
Elliot Lee committed
788 789 790
}

static void
791
set_color_icon (GdkDragContext *context,
792
                gdouble        *colors)
Elliot Lee's avatar
Elliot Lee committed
793
{
794 795
  GdkPixbuf *pixbuf;
  guint32 pixel;
796

797
  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE,
798
                           8, 48, 32);
799

800
  pixel = (((UNSCALE (colors[COLORSEL_RED])   & 0xff00) << 16) |
801 802
           ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) |
           ((UNSCALE (colors[COLORSEL_BLUE])  & 0xff00)));
803

804
  gdk_pixbuf_fill (pixbuf, pixel);
805

806 807
  gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
  g_object_unref (pixbuf);
Elliot Lee's avatar
Elliot Lee committed
808 809
}

810
static void
811
color_sample_drag_begin (GtkWidget      *widget,
812 813
                         GdkDragContext *context,
                         gpointer        data)
814
{
815
  GtkColorSelection *colorsel = data;
816
  GtkColorSelectionPrivate *priv;
817
  gdouble *colsrc;
818

819
  priv = colorsel->private_data;
820

821 822
  if (widget == priv->old_sample)
    colsrc = priv->old_color;
823
  else
824
    colsrc = priv->color;
825

826 827
  set_color_icon (context, colsrc);
}
828

829 830
static void
color_sample_drag_end (GtkWidget      *widget,
831 832
                       GdkDragContext *context,
                       gpointer        data)
833 834 835
{
  g_object_set_data (G_OBJECT (widget), I_("gtk-color-selection-drag-window"), NULL);
}
Elliot Lee's avatar
Elliot Lee committed
836 837

static void
838
color_sample_drop_handle (GtkWidget        *widget,
839 840 841 842 843 844 845
                          GdkDragContext   *context,
                          gint              x,
                          gint              y,
                          GtkSelectionData *selection_data,
                          guint             info,
                          guint             time,
                          gpointer          data)
846
{
847
  GtkColorSelection *colorsel = data;
848
  GtkColorSelectionPrivate *priv;
849
  gint length;
850 851 852
  guint16 *vals;
  gdouble color[4];
  priv = colorsel->private_data;
853

854 855 856 857 858 859
  /* This is currently a guint16 array of the format:
   * R
   * G
   * B
   * opacity
   */
860 861 862 863

  length = gtk_selection_data_get_length (selection_data);

  if (length < 0)
864
    return;
865

866 867 868
  /* We accept drops with the wrong format, since the KDE color
   * chooser incorrectly drops application/x-color with format 8.
   */
869
  if (length != 8)
870
    {
871
      g_warning ("Received invalid color data");
872 873
      return;
    }
874 875 876

  vals = (guint16 *) gtk_selection_data_get_data (selection_data);

877 878 879 880 881 882
  if (widget == priv->cur_sample)
    {
      color[0] = (gdouble)vals[0] / 0xffff;
      color[1] = (gdouble)vals[1] / 0xffff;
      color[2] = (gdouble)vals[2] / 0xffff;
      color[3] = (gdouble)vals[3] / 0xffff;
883

884 885
      set_color_internal (colorsel, color);
    }
886 887
}

888
static void
889
color_sample_drag_handle (GtkWidget        *widget,
890 891 892 893 894
                          GdkDragContext   *context,
                          GtkSelectionData *selection_data,
                          guint             info,
                          guint             time,
                          gpointer          data)
895
{
896
  GtkColorSelection *colorsel = data;
897
  GtkColorSelectionPrivate *priv;
898
  guint16 vals[4];
899
  gdouble *colsrc;
900

901
  priv = colorsel->private_data;
902

903 904 905 906
  if (widget == priv->old_sample)
    colsrc = priv->old_color;
  else
    colsrc = priv->color;
907

908 909 910
  vals[0] = colsrc[COLORSEL_RED] * 0xffff;
  vals[1] = colsrc[COLORSEL_GREEN] * 0xffff;
  vals[2] = colsrc[COLORSEL_BLUE] * 0xffff;
911
  vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff;
912

913
  gtk_selection_data_set (selection_data,
914 915
                          gdk_atom_intern_static_string ("application/x-color"),
                          16, (guchar *)vals, 8);
916 917
}

918
/* which = 0 means draw old sample, which = 1 means draw new */
919
static void
920 921 922
color_sample_draw_sample (GtkColorSelection *colorsel,
                          int                which,
                          cairo_t           *cr)
923
{
924
  GtkWidget *da;
925
  gint x, y, goff;
926
  GtkColorSelectionPrivate *priv;
927
  int width, height;
928

929 930
  g_return_if_fail (colorsel != NULL);
  priv = colorsel->private_data;
931

932
  g_return_if_fail (priv->sample_area != NULL);
933
  if (!gtk_widget_is_drawable (priv->sample_area))
934 935 936
    return;

  if (which == 0)
937
    {
938 939
      da = priv->old_sample;
      goff = 0;
940 941 942
    }
  else
    {
943 944
      GtkAllocation old_sample_allocation;

945
      da = priv->cur_sample;
946 947
      gtk_widget_get_allocation (priv->old_sample, &old_sample_allocation);
      goff =  old_sample_allocation.width % 32;
948 949
    }

950
  /* Below needs tweaking for non-power-of-two */
951 952
  width = gtk_widget_get_allocated_width (da);
  height = gtk_widget_get_allocated_height (da);
953

954
  if (priv->has_opacity)
955
    {
956
      /* Draw checks in background */
957

958
      cairo_set_source_rgb (cr, 0.5, 0.5, 0.5);
959
      cairo_rectangle (cr, 0, 0, width, height);
960
      cairo_fill (cr);
961

962
      cairo_set_source_rgb (cr, 0.75, 0.75, 0.75);
963
      for (x = goff & -CHECK_SIZE; x < goff + width; x += CHECK_SIZE)
964 965 966
        for (y = 0; y < height; y += CHECK_SIZE)
          if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0)
            cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE);
967 968
      cairo_fill (cr);
    }
969

970
  if (which == 0)
971
    {
972
      cairo_set_source_rgba (cr,
973 974 975 976 977
                             priv->old_color[COLORSEL_RED],
                             priv->old_color[COLORSEL_GREEN],
                             priv->old_color[COLORSEL_BLUE],
                             priv->has_opacity ?
                                priv->old_color[COLORSEL_OPACITY] : 1.0);
978 979
    }
  else
980 981
    {
      cairo_set_source_rgba (cr,
982 983 984 985 986
                             priv->color[COLORSEL_RED],
                             priv->color[COLORSEL_GREEN],
                             priv->color[COLORSEL_BLUE],
                             priv->has_opacity ?
                               priv->color[COLORSEL_OPACITY] : 1.0);
987
    }
988

989
  cairo_rectangle (cr, 0, 0, width, height);
990
  cairo_fill (cr);
991 992
}

993

994
static void
995
color_sample_update_samples (GtkColorSelection *colorsel)
996
{
997
  GtkColorSelectionPrivate *priv = colorsel->private_data;
998 999 1000
  gtk_widget_queue_draw (priv->old_sample);
  gtk_widget_queue_draw (priv->cur_sample);
}
1001

1002
static gboolean
1003 1004 1005
color_old_sample_draw (GtkWidget         *da,
                       cairo_t           *cr,
                       GtkColorSelection *colorsel)
1006
{
1007
  color_sample_draw_sample (colorsel, 0, cr);
1008
  return FALSE;
1009 1010
}

1011

1012
static gboolean
1013 1014 1015
color_cur_sample_draw (GtkWidget         *da,
                       cairo_t           *cr,
                       GtkColorSelection *colorsel)
1016
{
1017
  color_sample_draw_sample (colorsel, 1, cr);
1018
  return FALSE;
1019 1020 1021
}

static void
1022
color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample)
1023
{
1024 1025 1026
  static const GtkTargetEntry targets[] = {
    { "application/x-color", 0 }
  };
1027
  GtkColorSelectionPrivate *priv;
1028
  priv = colorsel->private_data;
1029

1030
  gtk_drag_source_set (sample,
1031 1032 1033 1034
                       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
                       targets, 1,
                       GDK_ACTION_COPY | GDK_ACTION_MOVE);

1035
  g_signal_connect (sample, "drag-begin",
1036 1037
                    G_CALLBACK (color_sample_drag_begin),
                    colorsel);
1038 1039
  if (sample == priv->cur_sample)
    {
1040

1041
      gtk_drag_dest_set (sample,
1042 1043 1044 1045 1046 1047
                         GTK_DEST_DEFAULT_HIGHLIGHT |
                         GTK_DEST_DEFAULT_MOTION |
                         GTK_DEST_DEFAULT_DROP,
                         targets, 1,
                         GDK_ACTION_COPY);

1048
      g_signal_connect (sample, "drag-end",
1049 1050
                        G_CALLBACK (color_sample_drag_end),
                        colorsel);
1051
    }
1052

1053
  g_signal_connect (sample, "drag-data-get",
1054 1055
                    G_CALLBACK (color_sample_drag_handle),
                    colorsel);
1056
  g_signal_connect (sample, "drag-data-received",
1057 1058 1059
                    G_CALLBACK (color_sample_drop_handle),
                    colorsel);

1060 1061
}

1062 1063 1064
static void
update_tooltips (GtkColorSelection *colorsel)
{
1065
  GtkColorSelectionPrivate *priv;
1066 1067 1068 1069 1070 1071

  priv = colorsel->private_data;

  if (priv->has_palette == TRUE)
    {
      gtk_widget_set_tooltip_text (priv->old_sample,
1072
        _("The previously-selected color, for comparison to the color "
1073
          "you’re selecting now. You can drag this color to a palette "
1074 1075
          "entry, or select this color as current by dragging it to the "
          "other color swatch alongside."));
1076 1077

      gtk_widget_set_tooltip_text (priv->cur_sample,
1078
        _("The color you’ve chosen. You can drag this color to a palette "
1079
          "entry to save it for use in the future."));
1080 1081 1082 1083
    }
  else
    {
      gtk_widget_set_tooltip_text (priv->old_sample,
1084
        _("The previously-selected color, for comparison to the color "
1085
          "you’re selecting now."));
1086 1087

      gtk_widget_set_tooltip_text (priv->cur_sample,
1088
        _("The color you’ve chosen."));
1089 1090
    }
}
1091

1092
static void
1093
color_sample_new (GtkColorSelection *colorsel)
1094
{
1095
  GtkColorSelectionPrivate *priv;
1096

1097
  priv = colorsel->private_data;
1098

1099
  priv->sample_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1100 1101
  priv->old_sample = gtk_drawing_area_new ();
  priv->cur_sample = gtk_drawing_area_new ();
1102

1103
  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample,
1104
                      TRUE, TRUE, 0);
1105
  gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample,
1106 1107
                      TRUE, TRUE, 0);

1108
  g_signal_connect (priv->old_sample, "draw",
1109 1110
                    G_CALLBACK (color_old_sample_draw),
                    colorsel);
1111
  g_signal_connect (priv->cur_sample, "draw",
1112 1113 1114
                    G_CALLBACK (color_cur_sample_draw),
                    colorsel);

1115 1116
  color_sample_setup_dnd (colorsel, priv->old_sample);
  color_sample_setup_dnd (colorsel, priv->cur_sample);
1117

1118
  update_tooltips (colorsel);
1119

1120
  gtk_widget_show_all (priv->sample_area);
1121 1122 1123
}


1124
/* The palette area code */
1125

1126 1127
static void
palette_get_color (GtkWidget *drawing_area, gdouble *color)