1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
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 "libgimpwidgets/gimpwidgets.h"
24 
25 #include "tools-types.h"
26 
27 #include "paint/gimpdodgeburnoptions.h"
28 
29 #include "widgets/gimphelp-ids.h"
30 #include "widgets/gimppropwidgets.h"
31 #include "widgets/gimpwidgets-utils.h"
32 
33 #include "gimpdodgeburntool.h"
34 #include "gimppaintoptions-gui.h"
35 #include "gimptoolcontrol.h"
36 
37 #include "gimp-intl.h"
38 
39 
40 static void   gimp_dodge_burn_tool_modifier_key  (GimpTool          *tool,
41                                                   GdkModifierType    key,
42                                                   gboolean           press,
43                                                   GdkModifierType    state,
44                                                   GimpDisplay       *display);
45 static void   gimp_dodge_burn_tool_cursor_update (GimpTool          *tool,
46                                                   const GimpCoords  *coords,
47                                                   GdkModifierType    state,
48                                                   GimpDisplay       *display);
49 static void   gimp_dodge_burn_tool_oper_update   (GimpTool          *tool,
50                                                   const GimpCoords  *coords,
51                                                   GdkModifierType    state,
52                                                   gboolean           proximity,
53                                                   GimpDisplay       *display);
54 static void   gimp_dodge_burn_tool_status_update (GimpTool          *tool,
55                                                   GimpDodgeBurnType  type);
56 
57 static GtkWidget * gimp_dodge_burn_options_gui   (GimpToolOptions   *tool_options);
58 
59 
G_DEFINE_TYPE(GimpDodgeBurnTool,gimp_dodge_burn_tool,GIMP_TYPE_BRUSH_TOOL)60 G_DEFINE_TYPE (GimpDodgeBurnTool, gimp_dodge_burn_tool, GIMP_TYPE_BRUSH_TOOL)
61 
62 #define parent_class gimp_dodge_burn_tool_parent_class
63 
64 
65 void
66 gimp_dodge_burn_tool_register (GimpToolRegisterCallback  callback,
67                                gpointer                  data)
68 {
69   (* callback) (GIMP_TYPE_DODGE_BURN_TOOL,
70                 GIMP_TYPE_DODGE_BURN_OPTIONS,
71                 gimp_dodge_burn_options_gui,
72                 GIMP_PAINT_OPTIONS_CONTEXT_MASK,
73                 "gimp-dodge-burn-tool",
74                 _("Dodge / Burn"),
75                 _("Dodge / Burn Tool: Selectively lighten or darken using a brush"),
76                 N_("Dod_ge / Burn"), "<shift>D",
77                 NULL, GIMP_HELP_TOOL_DODGE_BURN,
78                 GIMP_ICON_TOOL_DODGE,
79                 data);
80 }
81 
82 static void
gimp_dodge_burn_tool_class_init(GimpDodgeBurnToolClass * klass)83 gimp_dodge_burn_tool_class_init (GimpDodgeBurnToolClass *klass)
84 {
85   GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
86 
87   tool_class->modifier_key  = gimp_dodge_burn_tool_modifier_key;
88   tool_class->cursor_update = gimp_dodge_burn_tool_cursor_update;
89   tool_class->oper_update   = gimp_dodge_burn_tool_oper_update;
90 }
91 
92 static void
gimp_dodge_burn_tool_init(GimpDodgeBurnTool * dodgeburn)93 gimp_dodge_burn_tool_init (GimpDodgeBurnTool *dodgeburn)
94 {
95   GimpTool *tool = GIMP_TOOL (dodgeburn);
96 
97   gimp_tool_control_set_tool_cursor        (tool->control,
98                                             GIMP_TOOL_CURSOR_DODGE);
99   gimp_tool_control_set_toggle_tool_cursor (tool->control,
100                                             GIMP_TOOL_CURSOR_BURN);
101 
102   gimp_dodge_burn_tool_status_update (tool, GIMP_DODGE_BURN_TYPE_BURN);
103 }
104 
105 static void
gimp_dodge_burn_tool_modifier_key(GimpTool * tool,GdkModifierType key,gboolean press,GdkModifierType state,GimpDisplay * display)106 gimp_dodge_burn_tool_modifier_key (GimpTool        *tool,
107                                    GdkModifierType  key,
108                                    gboolean         press,
109                                    GdkModifierType  state,
110                                    GimpDisplay     *display)
111 {
112   GimpDodgeBurnTool    *dodgeburn   = GIMP_DODGE_BURN_TOOL (tool);
113   GimpDodgeBurnOptions *options     = GIMP_DODGE_BURN_TOOL_GET_OPTIONS (tool);
114   GdkModifierType       line_mask   = GIMP_PAINT_TOOL_LINE_MASK;
115   GdkModifierType       toggle_mask = gimp_get_toggle_behavior_mask ();
116 
117   if ((key == toggle_mask   &&
118       ! (state & line_mask) && /* leave stuff untouched in line draw mode */
119        press != dodgeburn->toggled)
120 
121       ||
122 
123       (key == line_mask   && /* toggle back after keypresses CTRL(hold)->  */
124        ! press            && /* SHIFT(hold)->CTRL(release)->SHIFT(release) */
125        dodgeburn->toggled &&
126        ! (state & toggle_mask)))
127     {
128       dodgeburn->toggled = press;
129 
130       switch (options->type)
131         {
132         case GIMP_DODGE_BURN_TYPE_DODGE:
133           g_object_set (options, "type", GIMP_DODGE_BURN_TYPE_BURN, NULL);
134           break;
135 
136         case GIMP_DODGE_BURN_TYPE_BURN:
137           g_object_set (options, "type", GIMP_DODGE_BURN_TYPE_DODGE, NULL);
138           break;
139 
140         default:
141           break;
142         }
143     }
144 
145   GIMP_TOOL_CLASS (parent_class)->modifier_key (tool, key, press, state,
146                                                 display);
147 }
148 
149 static void
gimp_dodge_burn_tool_cursor_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,GimpDisplay * display)150 gimp_dodge_burn_tool_cursor_update (GimpTool         *tool,
151                                     const GimpCoords *coords,
152                                     GdkModifierType   state,
153                                     GimpDisplay      *display)
154 {
155   GimpDodgeBurnOptions *options = GIMP_DODGE_BURN_TOOL_GET_OPTIONS (tool);
156 
157   gimp_tool_control_set_toggled (tool->control,
158                                  options->type == GIMP_DODGE_BURN_TYPE_BURN);
159 
160   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state,
161                                                  display);
162 }
163 
164 static void
gimp_dodge_burn_tool_oper_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpDisplay * display)165 gimp_dodge_burn_tool_oper_update (GimpTool         *tool,
166                                   const GimpCoords *coords,
167                                   GdkModifierType   state,
168                                   gboolean          proximity,
169                                   GimpDisplay      *display)
170 {
171   GimpDodgeBurnOptions *options = GIMP_DODGE_BURN_TOOL_GET_OPTIONS (tool);
172 
173   gimp_dodge_burn_tool_status_update (tool, options->type);
174 
175   GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
176                                                display);
177 }
178 
179 static void
gimp_dodge_burn_tool_status_update(GimpTool * tool,GimpDodgeBurnType type)180 gimp_dodge_burn_tool_status_update (GimpTool          *tool,
181                                     GimpDodgeBurnType  type)
182 {
183   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
184 
185   switch (type)
186     {
187     case GIMP_DODGE_BURN_TYPE_DODGE:
188       paint_tool->status      = _("Click to dodge");
189       paint_tool->status_line = _("Click to dodge the line");
190       paint_tool->status_ctrl = _("%s to burn");
191       break;
192 
193     case GIMP_DODGE_BURN_TYPE_BURN:
194       paint_tool->status      = _("Click to burn");
195       paint_tool->status_line = _("Click to burn the line");
196       paint_tool->status_ctrl = _("%s to dodge");
197       break;
198 
199     default:
200       break;
201     }
202 }
203 
204 
205 /*  tool options stuff  */
206 
207 static GtkWidget *
gimp_dodge_burn_options_gui(GimpToolOptions * tool_options)208 gimp_dodge_burn_options_gui (GimpToolOptions *tool_options)
209 {
210   GObject         *config = G_OBJECT (tool_options);
211   GtkWidget       *vbox   = gimp_paint_options_gui (tool_options);
212   GtkWidget       *frame;
213   GtkWidget       *scale;
214   gchar           *str;
215   GdkModifierType  toggle_mask;
216 
217   toggle_mask = gimp_get_toggle_behavior_mask ();
218 
219   /* the type (dodge or burn) */
220   str = g_strdup_printf (_("Type  (%s)"),
221                          gimp_get_mod_string (toggle_mask));
222 
223   frame = gimp_prop_enum_radio_frame_new (config, "type",
224                                           str, 0, 0);
225   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
226   gtk_widget_show (frame);
227 
228   g_free (str);
229 
230   /*  mode (highlights, midtones, or shadows)  */
231   frame = gimp_prop_enum_radio_frame_new (config, "mode", NULL,
232                                           0, 0);
233   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
234   gtk_widget_show (frame);
235 
236   /*  the exposure scale  */
237   scale = gimp_prop_spin_scale_new (config, "exposure", NULL,
238                                     1.0, 10.0, 1);
239   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
240   gtk_widget_show (scale);
241 
242   return vbox;
243 }
244