1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpmath/gimpmath.h"
24 #include "libgimpcolor/gimpcolor.h"
25 #include "libgimpwidgets/gimpwidgets.h"
26 
27 #include "tools-types.h"
28 
29 #include "config/gimpcoreconfig.h"
30 
31 #include "core/gimp.h"
32 #include "core/gimpdrawable.h"
33 #include "core/gimpimage.h"
34 #include "core/gimptoolinfo.h"
35 
36 #include "widgets/gimpcolorframe.h"
37 #include "widgets/gimphelp-ids.h"
38 #include "widgets/gimpwidgets-utils.h"
39 
40 #include "display/gimpdisplay.h"
41 #include "display/gimptoolgui.h"
42 
43 #include "gimpcolorpickeroptions.h"
44 #include "gimpcolorpickertool.h"
45 #include "gimptoolcontrol.h"
46 
47 #include "gimp-intl.h"
48 
49 
50 /*  local function prototypes  */
51 
52 static void   gimp_color_picker_tool_constructed   (GObject             *object);
53 static void   gimp_color_picker_tool_dispose       (GObject             *object);
54 
55 static void   gimp_color_picker_tool_control       (GimpTool            *tool,
56                                                     GimpToolAction       action,
57                                                     GimpDisplay         *display);
58 static void   gimp_color_picker_tool_modifier_key  (GimpTool            *tool,
59                                                     GdkModifierType      key,
60                                                     gboolean             press,
61                                                     GdkModifierType      state,
62                                                     GimpDisplay         *display);
63 static void   gimp_color_picker_tool_oper_update   (GimpTool            *tool,
64                                                     const GimpCoords    *coords,
65                                                     GdkModifierType      state,
66                                                     gboolean             proximity,
67                                                     GimpDisplay         *display);
68 
69 static void   gimp_color_picker_tool_picked        (GimpColorTool       *color_tool,
70                                                     const GimpCoords    *coords,
71                                                     GimpDisplay         *display,
72                                                     GimpColorPickState   pick_state,
73                                                     const Babl          *sample_format,
74                                                     gpointer             pixel,
75                                                     const GimpRGB       *color);
76 
77 static void   gimp_color_picker_tool_info_create   (GimpColorPickerTool *picker_tool,
78                                                     GimpDisplay         *display);
79 static void   gimp_color_picker_tool_info_response (GimpToolGui         *gui,
80                                                     gint                 response_id,
81                                                     GimpColorPickerTool *picker_tool);
82 static void   gimp_color_picker_tool_info_update   (GimpColorPickerTool *picker_tool,
83                                                     GimpDisplay         *display,
84                                                     gboolean             sample_average,
85                                                     const Babl          *sample_format,
86                                                     gpointer             pixel,
87                                                     const GimpRGB       *color,
88                                                     gint                 x,
89                                                     gint                 y);
90 
91 
G_DEFINE_TYPE(GimpColorPickerTool,gimp_color_picker_tool,GIMP_TYPE_COLOR_TOOL)92 G_DEFINE_TYPE (GimpColorPickerTool, gimp_color_picker_tool,
93                GIMP_TYPE_COLOR_TOOL)
94 
95 #define parent_class gimp_color_picker_tool_parent_class
96 
97 
98 void
99 gimp_color_picker_tool_register (GimpToolRegisterCallback  callback,
100                                  gpointer                  data)
101 {
102   (* callback) (GIMP_TYPE_COLOR_PICKER_TOOL,
103                 GIMP_TYPE_COLOR_PICKER_OPTIONS,
104                 gimp_color_picker_options_gui,
105                 GIMP_CONTEXT_PROP_MASK_FOREGROUND |
106                 GIMP_CONTEXT_PROP_MASK_BACKGROUND,
107                 "gimp-color-picker-tool",
108                 _("Color Picker"),
109                 _("Color Picker Tool: Set colors from image pixels"),
110                 N_("C_olor Picker"), "O",
111                 NULL, GIMP_HELP_TOOL_COLOR_PICKER,
112                 GIMP_ICON_TOOL_COLOR_PICKER,
113                 data);
114 }
115 
116 static void
gimp_color_picker_tool_class_init(GimpColorPickerToolClass * klass)117 gimp_color_picker_tool_class_init (GimpColorPickerToolClass *klass)
118 {
119   GObjectClass       *object_class     = G_OBJECT_CLASS (klass);
120   GimpToolClass      *tool_class       = GIMP_TOOL_CLASS (klass);
121   GimpColorToolClass *color_tool_class = GIMP_COLOR_TOOL_CLASS (klass);
122 
123   object_class->constructed = gimp_color_picker_tool_constructed;
124   object_class->dispose     = gimp_color_picker_tool_dispose;
125 
126   tool_class->control       = gimp_color_picker_tool_control;
127   tool_class->modifier_key  = gimp_color_picker_tool_modifier_key;
128   tool_class->oper_update   = gimp_color_picker_tool_oper_update;
129 
130   color_tool_class->picked  = gimp_color_picker_tool_picked;
131 }
132 
133 static void
gimp_color_picker_tool_init(GimpColorPickerTool * picker_tool)134 gimp_color_picker_tool_init (GimpColorPickerTool *picker_tool)
135 {
136   GimpColorTool *color_tool = GIMP_COLOR_TOOL (picker_tool);
137 
138   color_tool->pick_target = GIMP_COLOR_PICK_TARGET_FOREGROUND;
139 }
140 
141 static void
gimp_color_picker_tool_constructed(GObject * object)142 gimp_color_picker_tool_constructed (GObject *object)
143 {
144   GimpTool *tool = GIMP_TOOL (object);
145 
146   G_OBJECT_CLASS (parent_class)->constructed (object);
147 
148   gimp_color_tool_enable (GIMP_COLOR_TOOL (object),
149                           GIMP_COLOR_TOOL_GET_OPTIONS (tool));
150 }
151 
152 static void
gimp_color_picker_tool_dispose(GObject * object)153 gimp_color_picker_tool_dispose (GObject *object)
154 {
155   GimpColorPickerTool *picker_tool = GIMP_COLOR_PICKER_TOOL (object);
156 
157   g_clear_object (&picker_tool->gui);
158   picker_tool->color_area   = NULL;
159   picker_tool->color_frame1 = NULL;
160   picker_tool->color_frame2 = NULL;
161 
162   G_OBJECT_CLASS (parent_class)->dispose (object);
163 }
164 
165 static void
gimp_color_picker_tool_control(GimpTool * tool,GimpToolAction action,GimpDisplay * display)166 gimp_color_picker_tool_control (GimpTool       *tool,
167                                 GimpToolAction  action,
168                                 GimpDisplay    *display)
169 {
170   GimpColorPickerTool *picker_tool = GIMP_COLOR_PICKER_TOOL (tool);
171 
172   switch (action)
173     {
174     case GIMP_TOOL_ACTION_PAUSE:
175     case GIMP_TOOL_ACTION_RESUME:
176       break;
177 
178     case GIMP_TOOL_ACTION_HALT:
179       if (picker_tool->gui)
180         gimp_tool_gui_hide (picker_tool->gui);
181       break;
182 
183     case GIMP_TOOL_ACTION_COMMIT:
184       break;
185     }
186 
187   GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
188 }
189 
190 static void
gimp_color_picker_tool_modifier_key(GimpTool * tool,GdkModifierType key,gboolean press,GdkModifierType state,GimpDisplay * display)191 gimp_color_picker_tool_modifier_key (GimpTool        *tool,
192                                      GdkModifierType  key,
193                                      gboolean         press,
194                                      GdkModifierType  state,
195                                      GimpDisplay     *display)
196 {
197   GimpColorPickerOptions *options = GIMP_COLOR_PICKER_TOOL_GET_OPTIONS (tool);
198 
199   if (key == gimp_get_extend_selection_mask ())
200     {
201       g_object_set (options, "use-info-window", ! options->use_info_window,
202                     NULL);
203     }
204   else if (key == gimp_get_toggle_behavior_mask ())
205     {
206       switch (options->pick_target)
207         {
208         case GIMP_COLOR_PICK_TARGET_FOREGROUND:
209           g_object_set (options,
210                         "pick-target", GIMP_COLOR_PICK_TARGET_BACKGROUND,
211                         NULL);
212           break;
213 
214         case GIMP_COLOR_PICK_TARGET_BACKGROUND:
215           g_object_set (options,
216                         "pick-target", GIMP_COLOR_PICK_TARGET_FOREGROUND,
217                         NULL);
218           break;
219 
220         default:
221           break;
222         }
223 
224     }
225 }
226 
227 static void
gimp_color_picker_tool_oper_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpDisplay * display)228 gimp_color_picker_tool_oper_update (GimpTool         *tool,
229                                     const GimpCoords *coords,
230                                     GdkModifierType   state,
231                                     gboolean          proximity,
232                                     GimpDisplay      *display)
233 {
234   GimpColorPickerTool    *picker_tool = GIMP_COLOR_PICKER_TOOL (tool);
235   GimpColorPickerOptions *options = GIMP_COLOR_PICKER_TOOL_GET_OPTIONS (tool);
236 
237   GIMP_COLOR_TOOL (tool)->pick_target = options->pick_target;
238 
239   gimp_tool_pop_status (tool, display);
240 
241   if (proximity)
242     {
243       gchar           *status_help = NULL;
244       GdkModifierType  extend_mask = 0;
245       GdkModifierType  toggle_mask;
246 
247       if (! picker_tool->gui)
248         extend_mask = gimp_get_extend_selection_mask ();
249 
250       toggle_mask = gimp_get_toggle_behavior_mask ();
251 
252       switch (options->pick_target)
253         {
254         case GIMP_COLOR_PICK_TARGET_NONE:
255           status_help = gimp_suggest_modifiers (_("Click in any image to view"
256                                                   " its color"),
257                                                 extend_mask & ~state,
258                                                 NULL, NULL, NULL);
259           break;
260 
261         case GIMP_COLOR_PICK_TARGET_FOREGROUND:
262           status_help = gimp_suggest_modifiers (_("Click in any image to pick"
263                                                   " the foreground color"),
264                                                 (extend_mask | toggle_mask) &
265                                                 ~state,
266                                                 NULL, NULL, NULL);
267           break;
268 
269         case GIMP_COLOR_PICK_TARGET_BACKGROUND:
270           status_help = gimp_suggest_modifiers (_("Click in any image to pick"
271                                                   " the background color"),
272                                                 (extend_mask | toggle_mask) &
273                                                 ~state,
274                                                 NULL, NULL, NULL);
275           break;
276 
277         case GIMP_COLOR_PICK_TARGET_PALETTE:
278           status_help = gimp_suggest_modifiers (_("Click in any image to add"
279                                                   " the color to the palette"),
280                                                 extend_mask & ~state,
281                                                 NULL, NULL, NULL);
282           break;
283         }
284 
285       if (status_help != NULL)
286         {
287           gimp_tool_push_status (tool, display, "%s", status_help);
288           g_free (status_help);
289         }
290     }
291 
292   GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
293                                                display);
294 }
295 
296 static void
gimp_color_picker_tool_picked(GimpColorTool * color_tool,const GimpCoords * coords,GimpDisplay * display,GimpColorPickState pick_state,const Babl * sample_format,gpointer pixel,const GimpRGB * color)297 gimp_color_picker_tool_picked (GimpColorTool      *color_tool,
298                                const GimpCoords   *coords,
299                                GimpDisplay        *display,
300                                GimpColorPickState  pick_state,
301                                const Babl         *sample_format,
302                                gpointer            pixel,
303                                const GimpRGB      *color)
304 {
305   GimpColorPickerTool    *picker_tool = GIMP_COLOR_PICKER_TOOL (color_tool);
306   GimpColorPickerOptions *options;
307 
308   options = GIMP_COLOR_PICKER_TOOL_GET_OPTIONS (color_tool);
309 
310   if (options->use_info_window && ! picker_tool->gui)
311     gimp_color_picker_tool_info_create (picker_tool, display);
312 
313   if (picker_tool->gui &&
314       (options->use_info_window ||
315        gimp_tool_gui_get_visible (picker_tool->gui)))
316     {
317       gimp_color_picker_tool_info_update (picker_tool, display,
318                                           GIMP_COLOR_OPTIONS (options)->sample_average,
319                                           sample_format, pixel, color,
320                                           (gint) floor (coords->x),
321                                           (gint) floor (coords->y));
322     }
323 
324   GIMP_COLOR_TOOL_CLASS (parent_class)->picked (color_tool,
325                                                 coords, display, pick_state,
326                                                 sample_format, pixel, color);
327 }
328 
329 static void
gimp_color_picker_tool_info_create(GimpColorPickerTool * picker_tool,GimpDisplay * display)330 gimp_color_picker_tool_info_create (GimpColorPickerTool *picker_tool,
331                                     GimpDisplay         *display)
332 {
333   GimpTool         *tool     = GIMP_TOOL (picker_tool);
334   GimpToolOptions  *options  = GIMP_TOOL_GET_OPTIONS (tool);
335   GimpContext      *context  = GIMP_CONTEXT (tool->tool_info->tool_options);
336   GimpDisplayShell *shell    = gimp_display_get_shell (display);
337   GimpImage        *image    = gimp_display_get_image (display);
338   GimpDrawable     *drawable = gimp_image_get_active_drawable (image);
339   GtkWidget        *hbox;
340   GtkWidget        *frame;
341   GimpRGB           color;
342 
343   picker_tool->gui = gimp_tool_gui_new (tool->tool_info,
344                                         NULL,
345                                         _("Color Picker Information"),
346                                         NULL, NULL,
347                                         gtk_widget_get_screen (GTK_WIDGET (shell)),
348                                         gimp_widget_get_monitor (GTK_WIDGET (shell)),
349                                         TRUE,
350 
351                                         _("_Close"), GTK_RESPONSE_CLOSE,
352 
353                                         NULL);
354 
355   gimp_tool_gui_set_auto_overlay (picker_tool->gui, TRUE);
356   gimp_tool_gui_set_focus_on_map (picker_tool->gui, FALSE);
357   gimp_tool_gui_set_viewable (picker_tool->gui, GIMP_VIEWABLE (drawable));
358 
359   g_signal_connect (picker_tool->gui, "response",
360                     G_CALLBACK (gimp_color_picker_tool_info_response),
361                     picker_tool);
362 
363   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
364   gtk_box_pack_start (GTK_BOX (gimp_tool_gui_get_vbox (picker_tool->gui)),
365                       hbox, FALSE, FALSE, 0);
366   gtk_widget_show (hbox);
367 
368   picker_tool->color_frame1 = gimp_color_frame_new ();
369   gimp_color_frame_set_color_config (GIMP_COLOR_FRAME (picker_tool->color_frame1),
370                                      context->gimp->config->color_management);
371   gimp_color_frame_set_has_coords (GIMP_COLOR_FRAME (picker_tool->color_frame1),
372                                    TRUE);
373   g_object_bind_property (options,                   "frame1-mode",
374                           picker_tool->color_frame1, "mode",
375                           G_BINDING_BIDIRECTIONAL |
376                           G_BINDING_SYNC_CREATE);
377   gtk_box_pack_start (GTK_BOX (hbox), picker_tool->color_frame1,
378                       FALSE, FALSE, 0);
379   gtk_widget_show (picker_tool->color_frame1);
380 
381   picker_tool->color_frame2 = gimp_color_frame_new ();
382   gimp_color_frame_set_color_config (GIMP_COLOR_FRAME (picker_tool->color_frame2),
383                                      context->gimp->config->color_management);
384   g_object_bind_property (options,                   "frame2-mode",
385                           picker_tool->color_frame2, "mode",
386                           G_BINDING_BIDIRECTIONAL |
387                           G_BINDING_SYNC_CREATE);
388   gtk_box_pack_start (GTK_BOX (hbox), picker_tool->color_frame2,
389                       FALSE, FALSE, 0);
390   gtk_widget_show (picker_tool->color_frame2);
391 
392   frame = gtk_frame_new (NULL);
393   gimp_widget_set_fully_opaque (frame, TRUE);
394   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
395   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
396   gtk_widget_show (frame);
397 
398   gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
399   picker_tool->color_area =
400     gimp_color_area_new (&color,
401                          gimp_drawable_has_alpha (drawable) ?
402                          GIMP_COLOR_AREA_LARGE_CHECKS :
403                          GIMP_COLOR_AREA_FLAT,
404                          GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
405   gimp_color_area_set_color_config (GIMP_COLOR_AREA (picker_tool->color_area),
406                                     context->gimp->config->color_management);
407   gtk_widget_set_size_request (picker_tool->color_area, 48, -1);
408   gtk_drag_dest_unset (picker_tool->color_area);
409   gtk_container_add (GTK_CONTAINER (frame), picker_tool->color_area);
410   gtk_widget_show (picker_tool->color_area);
411 }
412 
413 static void
gimp_color_picker_tool_info_response(GimpToolGui * gui,gint response_id,GimpColorPickerTool * picker_tool)414 gimp_color_picker_tool_info_response (GimpToolGui         *gui,
415                                       gint                 response_id,
416                                       GimpColorPickerTool *picker_tool)
417 {
418   GimpTool *tool = GIMP_TOOL (picker_tool);
419 
420   gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, NULL);
421 }
422 
423 static void
gimp_color_picker_tool_info_update(GimpColorPickerTool * picker_tool,GimpDisplay * display,gboolean sample_average,const Babl * sample_format,gpointer pixel,const GimpRGB * color,gint x,gint y)424 gimp_color_picker_tool_info_update (GimpColorPickerTool *picker_tool,
425                                     GimpDisplay         *display,
426                                     gboolean             sample_average,
427                                     const Babl          *sample_format,
428                                     gpointer             pixel,
429                                     const GimpRGB       *color,
430                                     gint                 x,
431                                     gint                 y)
432 {
433   GimpTool     *tool     = GIMP_TOOL (picker_tool);
434   GimpImage    *image    = gimp_display_get_image (display);
435   GimpDrawable *drawable = gimp_image_get_active_drawable (image);
436 
437   tool->display = display;
438 
439   gimp_tool_gui_set_shell (picker_tool->gui,
440                            gimp_display_get_shell (display));
441   gimp_tool_gui_set_viewable (picker_tool->gui,
442                               GIMP_VIEWABLE (drawable));
443 
444   gimp_color_area_set_color (GIMP_COLOR_AREA (picker_tool->color_area),
445                              color);
446 
447   gimp_color_frame_set_color (GIMP_COLOR_FRAME (picker_tool->color_frame1),
448                               sample_average, sample_format, pixel, color,
449                               x, y);
450   gimp_color_frame_set_color (GIMP_COLOR_FRAME (picker_tool->color_frame2),
451                               sample_average, sample_format, pixel, color,
452                               x, y);
453 
454   gimp_tool_gui_show (picker_tool->gui);
455 }
456