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 "libgimpcolor/gimpcolor.h"
24 #include "libgimpwidgets/gimpwidgets.h"
25
26 #include "widgets-types.h"
27
28 #include "config/gimpcoreconfig.h"
29
30 #include "core/gimp.h"
31 #include "core/gimpcontext.h"
32 #include "core/gimpmarshal.h"
33
34 #include "gimpaction.h"
35 #include "gimpactiongroup.h"
36 #include "gimpactionimpl.h"
37 #include "gimpcolordialog.h"
38 #include "gimpcolorpanel.h"
39
40
41 #define RGBA_EPSILON 1e-6
42
43 enum
44 {
45 RESPONSE,
46 LAST_SIGNAL
47 };
48
49
50 /* local function prototypes */
51
52 static void gimp_color_panel_dispose (GObject *object);
53
54 static gboolean gimp_color_panel_button_press (GtkWidget *widget,
55 GdkEventButton *bevent);
56
57 static void gimp_color_panel_clicked (GtkButton *button);
58
59 static void gimp_color_panel_color_changed (GimpColorButton *button);
60 static GType gimp_color_panel_get_action_type (GimpColorButton *button);
61
62 static void gimp_color_panel_dialog_update (GimpColorDialog *dialog,
63 const GimpRGB *color,
64 GimpColorDialogState state,
65 GimpColorPanel *panel);
66
67
68 G_DEFINE_TYPE (GimpColorPanel, gimp_color_panel, GIMP_TYPE_COLOR_BUTTON)
69
70 #define parent_class gimp_color_panel_parent_class
71
72 static guint color_panel_signals[LAST_SIGNAL] = { 0, };
73
74
75 static void
gimp_color_panel_class_init(GimpColorPanelClass * klass)76 gimp_color_panel_class_init (GimpColorPanelClass *klass)
77 {
78 GObjectClass *object_class = G_OBJECT_CLASS (klass);
79 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
80 GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
81 GimpColorButtonClass *color_button_class = GIMP_COLOR_BUTTON_CLASS (klass);
82
83 object_class->dispose = gimp_color_panel_dispose;
84
85 widget_class->button_press_event = gimp_color_panel_button_press;
86
87 button_class->clicked = gimp_color_panel_clicked;
88
89 color_button_class->color_changed = gimp_color_panel_color_changed;
90 color_button_class->get_action_type = gimp_color_panel_get_action_type;
91
92 color_panel_signals[RESPONSE] =
93 g_signal_new ("response",
94 G_TYPE_FROM_CLASS (klass),
95 G_SIGNAL_RUN_LAST,
96 G_STRUCT_OFFSET (GimpColorPanelClass, response),
97 NULL, NULL,
98 gimp_marshal_VOID__ENUM,
99 G_TYPE_NONE, 1,
100 GIMP_TYPE_COLOR_DIALOG_STATE);
101 }
102
103 static void
gimp_color_panel_init(GimpColorPanel * panel)104 gimp_color_panel_init (GimpColorPanel *panel)
105 {
106 panel->context = NULL;
107 panel->color_dialog = NULL;
108 }
109
110 static void
gimp_color_panel_dispose(GObject * object)111 gimp_color_panel_dispose (GObject *object)
112 {
113 GimpColorPanel *panel = GIMP_COLOR_PANEL (object);
114
115 if (panel->color_dialog)
116 {
117 gtk_widget_destroy (panel->color_dialog);
118 panel->color_dialog = NULL;
119 }
120
121 G_OBJECT_CLASS (parent_class)->dispose (object);
122 }
123
124 static gboolean
gimp_color_panel_button_press(GtkWidget * widget,GdkEventButton * bevent)125 gimp_color_panel_button_press (GtkWidget *widget,
126 GdkEventButton *bevent)
127 {
128 if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
129 {
130 GimpColorButton *color_button;
131 GimpColorPanel *color_panel;
132 GtkUIManager *ui_manager;
133 GimpActionGroup *group;
134 GimpAction *action;
135 GimpRGB color;
136
137 color_button = GIMP_COLOR_BUTTON (widget);
138 color_panel = GIMP_COLOR_PANEL (widget);
139 ui_manager = gimp_color_button_get_ui_manager (color_button);
140
141 group = gtk_ui_manager_get_action_groups (ui_manager)->data;
142
143 action = gimp_action_group_get_action (group,
144 "color-button-use-foreground");
145 gimp_action_set_visible (action, color_panel->context != NULL);
146
147 action = gimp_action_group_get_action (group,
148 "color-button-use-background");
149 gimp_action_set_visible (action, color_panel->context != NULL);
150
151 if (color_panel->context)
152 {
153 action = gimp_action_group_get_action (group,
154 "color-button-use-foreground");
155 gimp_context_get_foreground (color_panel->context, &color);
156 g_object_set (action, "color", &color, NULL);
157
158 action = gimp_action_group_get_action (group,
159 "color-button-use-background");
160 gimp_context_get_background (color_panel->context, &color);
161 g_object_set (action, "color", &color, NULL);
162 }
163
164 action = gimp_action_group_get_action (group, "color-button-use-black");
165 gimp_rgba_set (&color, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
166 g_object_set (action, "color", &color, NULL);
167
168 action = gimp_action_group_get_action (group, "color-button-use-white");
169 gimp_rgba_set (&color, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
170 g_object_set (action, "color", &color, NULL);
171 }
172
173 if (GTK_WIDGET_CLASS (parent_class)->button_press_event)
174 return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, bevent);
175
176 return FALSE;
177 }
178
179 static void
gimp_color_panel_clicked(GtkButton * button)180 gimp_color_panel_clicked (GtkButton *button)
181 {
182 GimpColorPanel *panel = GIMP_COLOR_PANEL (button);
183 GimpRGB color;
184
185 gimp_color_button_get_color (GIMP_COLOR_BUTTON (button), &color);
186
187 if (! panel->color_dialog)
188 {
189 GimpColorButton *color_button = GIMP_COLOR_BUTTON (button);
190
191 panel->color_dialog =
192 gimp_color_dialog_new (NULL, panel->context,
193 gimp_color_button_get_title (color_button),
194 NULL, NULL,
195 GTK_WIDGET (button),
196 NULL, NULL,
197 &color,
198 gimp_color_button_get_update (color_button),
199 gimp_color_button_has_alpha (color_button));
200
201 g_signal_connect (panel->color_dialog, "destroy",
202 G_CALLBACK (gtk_widget_destroyed),
203 &panel->color_dialog);
204
205 g_signal_connect (panel->color_dialog, "update",
206 G_CALLBACK (gimp_color_panel_dialog_update),
207 panel);
208 }
209 else
210 {
211 gimp_color_dialog_set_color (GIMP_COLOR_DIALOG (panel->color_dialog),
212 &color);
213 }
214
215 gtk_window_present (GTK_WINDOW (panel->color_dialog));
216 }
217
218 static GType
gimp_color_panel_get_action_type(GimpColorButton * button)219 gimp_color_panel_get_action_type (GimpColorButton *button)
220 {
221 return GIMP_TYPE_ACTION_IMPL;
222 }
223
224
225 /* public functions */
226
227 GtkWidget *
gimp_color_panel_new(const gchar * title,const GimpRGB * color,GimpColorAreaType type,gint width,gint height)228 gimp_color_panel_new (const gchar *title,
229 const GimpRGB *color,
230 GimpColorAreaType type,
231 gint width,
232 gint height)
233 {
234 g_return_val_if_fail (title != NULL, NULL);
235 g_return_val_if_fail (color != NULL, NULL);
236 g_return_val_if_fail (width > 0, NULL);
237 g_return_val_if_fail (height > 0, NULL);
238
239 return g_object_new (GIMP_TYPE_COLOR_PANEL,
240 "title", title,
241 "type", type,
242 "color", color,
243 "area-width", width,
244 "area-height", height,
245 NULL);
246 }
247
248 static void
gimp_color_panel_color_changed(GimpColorButton * button)249 gimp_color_panel_color_changed (GimpColorButton *button)
250 {
251 GimpColorPanel *panel = GIMP_COLOR_PANEL (button);
252 GimpRGB color;
253
254 if (panel->color_dialog)
255 {
256 GimpRGB dialog_color;
257
258 gimp_color_button_get_color (GIMP_COLOR_BUTTON (button), &color);
259 gimp_color_dialog_get_color (GIMP_COLOR_DIALOG (panel->color_dialog),
260 &dialog_color);
261
262 if (gimp_rgba_distance (&color, &dialog_color) > RGBA_EPSILON ||
263 color.a != dialog_color.a)
264 {
265 gimp_color_dialog_set_color (GIMP_COLOR_DIALOG (panel->color_dialog),
266 &color);
267 }
268 }
269 }
270
271 void
gimp_color_panel_set_context(GimpColorPanel * panel,GimpContext * context)272 gimp_color_panel_set_context (GimpColorPanel *panel,
273 GimpContext *context)
274 {
275 g_return_if_fail (GIMP_IS_COLOR_PANEL (panel));
276 g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
277
278 panel->context = context;
279
280 if (context)
281 gimp_color_button_set_color_config (GIMP_COLOR_BUTTON (panel),
282 context->gimp->config->color_management);
283 }
284
285 void
gimp_color_panel_dialog_response(GimpColorPanel * panel,GimpColorDialogState state)286 gimp_color_panel_dialog_response (GimpColorPanel *panel,
287 GimpColorDialogState state)
288 {
289 g_return_if_fail (GIMP_IS_COLOR_PANEL (panel));
290 g_return_if_fail (state == GIMP_COLOR_DIALOG_OK ||
291 state == GIMP_COLOR_DIALOG_CANCEL);
292
293 if (panel->color_dialog && gtk_widget_get_visible (panel->color_dialog))
294 gimp_color_panel_dialog_update (NULL, NULL, state, panel);
295 }
296
297
298 /* private functions */
299
300 static void
gimp_color_panel_dialog_update(GimpColorDialog * dialog,const GimpRGB * color,GimpColorDialogState state,GimpColorPanel * panel)301 gimp_color_panel_dialog_update (GimpColorDialog *dialog,
302 const GimpRGB *color,
303 GimpColorDialogState state,
304 GimpColorPanel *panel)
305 {
306 switch (state)
307 {
308 case GIMP_COLOR_DIALOG_UPDATE:
309 if (gimp_color_button_get_update (GIMP_COLOR_BUTTON (panel)))
310 gimp_color_button_set_color (GIMP_COLOR_BUTTON (panel), color);
311 break;
312
313 case GIMP_COLOR_DIALOG_OK:
314 if (! gimp_color_button_get_update (GIMP_COLOR_BUTTON (panel)))
315 gimp_color_button_set_color (GIMP_COLOR_BUTTON (panel), color);
316 gtk_widget_hide (panel->color_dialog);
317
318 g_signal_emit (panel, color_panel_signals[RESPONSE], 0,
319 state);
320 break;
321
322 case GIMP_COLOR_DIALOG_CANCEL:
323 if (gimp_color_button_get_update (GIMP_COLOR_BUTTON (panel)))
324 gimp_color_button_set_color (GIMP_COLOR_BUTTON (panel), color);
325 gtk_widget_hide (panel->color_dialog);
326
327 g_signal_emit (panel, color_panel_signals[RESPONSE], 0,
328 state);
329 break;
330 }
331 }
332