1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2012 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
27 #include "gtkcolorchooserprivate.h"
28 #include "gtkcoloreditor.h"
29 #include "gtkcolorplane.h"
32 #include "gtkaspectframe.h"
33 #include "gtkdrawingarea.h"
36 #include "gtkadjustment.h"
41 struct _GtkColorEditorPrivate
54 guint text_changed : 1;
65 static void gtk_color_editor_iface_init (GtkColorChooserInterface *iface);
67 G_DEFINE_TYPE_WITH_CODE (GtkColorEditor, gtk_color_editor, GTK_TYPE_BOX,
68 G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER,
69 gtk_color_editor_iface_init))
72 scale_round (gdouble value, gdouble scale)
74 value = floor (value * scale + 0.5);
75 value = MAX (value, 0);
76 value = MIN (value, scale);
81 update_entry (GtkColorEditor *editor)
85 text = g_strdup_printf ("#%02X%02X%02X",
86 scale_round (editor->priv->color.red, 255),
87 scale_round (editor->priv->color.green, 255),
88 scale_round (editor->priv->color.blue, 255));
89 gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), text);
90 editor->priv->text_changed = FALSE;
95 entry_apply (GtkWidget *entry,
96 GtkColorEditor *editor)
101 if (!editor->priv->text_changed)
104 text = gtk_editable_get_chars (GTK_EDITABLE (editor->priv->entry), 0, -1);
105 if (gdk_rgba_parse (&color, text))
107 color.alpha = editor->priv->color.alpha;
108 gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (editor), &color);
111 editor->priv->text_changed = FALSE;
117 entry_focus_out (GtkWidget *entry,
118 GdkEventFocus *event,
119 GtkColorEditor *editor)
121 entry_apply (entry, editor);
126 entry_text_changed (GtkWidget *entry,
128 GtkColorEditor *editor)
130 editor->priv->text_changed = TRUE;
134 h_changed (GtkAdjustment *adj,
135 GtkColorEditor *editor)
137 editor->priv->h = gtk_adjustment_get_value (adj);
138 gtk_hsv_to_rgb (editor->priv->h, editor->priv->s, editor->priv->v,
139 &editor->priv->color.red,
140 &editor->priv->color.green,
141 &editor->priv->color.blue);
142 gtk_color_plane_set_h (GTK_COLOR_PLANE (editor->priv->sv_plane), editor->priv->h);
143 gtk_widget_queue_draw (editor->priv->swatch);
144 update_entry (editor);
145 g_object_notify (G_OBJECT (editor), "color");
149 sv_changed (GtkColorPlane *plane,
150 GtkColorEditor *editor)
152 editor->priv->s = gtk_color_plane_get_s (plane);
153 editor->priv->v = gtk_color_plane_get_v (plane);
154 gtk_hsv_to_rgb (editor->priv->h, editor->priv->s, editor->priv->v,
155 &editor->priv->color.red,
156 &editor->priv->color.green,
157 &editor->priv->color.blue);
158 update_entry (editor);
159 gtk_widget_queue_draw (editor->priv->swatch);
163 a_changed (GtkAdjustment *adj,
164 GtkColorEditor *editor)
166 editor->priv->color.alpha = gtk_adjustment_get_value (adj);
167 gtk_widget_queue_draw (editor->priv->swatch);
168 g_object_notify (G_OBJECT (editor), "color");
171 static cairo_pattern_t *
172 get_checkered_pattern (void)
174 /* need to respect pixman's stride being a multiple of 4 */
175 static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
176 0x00, 0xFF, 0x00, 0x00 };
177 static cairo_surface_t *checkered = NULL;
178 cairo_pattern_t *pattern;
180 if (checkered == NULL)
181 checkered = cairo_image_surface_create_for_data (data,
185 pattern = cairo_pattern_create_for_surface (checkered);
186 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
187 cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
193 swatch_draw (GtkWidget *widget,
195 GtkColorEditor *editor)
197 cairo_pattern_t *checkered;
199 if (editor->priv->show_alpha)
201 cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
204 cairo_set_source_rgb (cr, 0.66, 0.66, 0.66);
205 cairo_scale (cr, 8, 8);
207 checkered = get_checkered_pattern ();
208 cairo_mask (cr, checkered);
209 cairo_pattern_destroy (checkered);
212 gdk_cairo_set_source_rgba (cr, &editor->priv->color);
219 gtk_color_editor_init (GtkColorEditor *editor)
224 editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (editor,
225 GTK_TYPE_COLOR_EDITOR,
226 GtkColorEditorPrivate);
227 editor->priv->show_alpha = TRUE;
229 gtk_widget_push_composite_child ();
231 editor->priv->grid = grid = gtk_grid_new ();
232 gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
233 gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
235 editor->priv->swatch = gtk_drawing_area_new ();
236 g_signal_connect (editor->priv->swatch, "draw", G_CALLBACK (swatch_draw), editor);
237 editor->priv->entry = gtk_entry_new ();
238 g_signal_connect (editor->priv->entry, "activate",
239 G_CALLBACK (entry_apply), editor);
240 g_signal_connect (editor->priv->entry, "notify::text",
241 G_CALLBACK (entry_text_changed), editor);
242 g_signal_connect (editor->priv->entry, "focus-out-event",
243 G_CALLBACK (entry_focus_out), editor);
245 adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
246 g_signal_connect (adj, "value-changed", G_CALLBACK (h_changed), editor);
247 editor->priv->h_slider = gtk_scale_new (GTK_ORIENTATION_VERTICAL, adj);
248 editor->priv->h_adj = adj;
250 gtk_scale_set_draw_value (GTK_SCALE (editor->priv->h_slider), FALSE);
251 editor->priv->sv_plane = gtk_color_plane_new ();
252 gtk_widget_set_size_request (editor->priv->sv_plane, 300, 300);
253 gtk_widget_set_hexpand (editor->priv->sv_plane, TRUE);
254 gtk_widget_set_vexpand (editor->priv->sv_plane, TRUE);
256 g_signal_connect (editor->priv->sv_plane, "changed", G_CALLBACK (sv_changed), editor);
258 adj = gtk_adjustment_new (1, 0, 1, 0.01, 0.1, 0);
259 editor->priv->a_slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adj);
260 g_signal_connect (adj, "value-changed", G_CALLBACK (a_changed), editor);
261 gtk_scale_set_draw_value (GTK_SCALE (editor->priv->a_slider), FALSE);
262 editor->priv->a_adj = adj;
264 gtk_grid_attach (GTK_GRID (grid), editor->priv->swatch, 1, 0, 1, 1);
265 gtk_grid_attach (GTK_GRID (grid), editor->priv->entry, 2, 0, 1, 1);
266 gtk_grid_attach (GTK_GRID (grid), editor->priv->h_slider, 0, 1, 1, 1);
267 gtk_grid_attach (GTK_GRID (grid), editor->priv->sv_plane, 1, 1, 2, 1);
268 gtk_grid_attach (GTK_GRID (grid), editor->priv->a_slider, 1, 2, 2, 1);
269 gtk_widget_show_all (grid);
271 gtk_container_add (GTK_CONTAINER (editor), grid);
272 gtk_widget_pop_composite_child ();
276 gtk_color_editor_get_property (GObject *object,
281 GtkColorEditor *ce = GTK_COLOR_EDITOR (object);
282 GtkColorChooser *cc = GTK_COLOR_CHOOSER (object);
289 gtk_color_chooser_get_color (cc, &color);
290 g_value_set_boxed (value, &color);
293 case PROP_SHOW_ALPHA:
294 g_value_set_boolean (value, gtk_widget_get_visible (ce->priv->a_slider));
297 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
303 gtk_color_editor_set_show_alpha (GtkColorEditor *editor,
306 if (editor->priv->show_alpha != show_alpha)
308 editor->priv->show_alpha = show_alpha;
311 gtk_widget_show (editor->priv->a_slider);
313 gtk_widget_hide (editor->priv->a_slider);
318 gtk_color_editor_set_property (GObject *object,
323 GtkColorEditor *ce = GTK_COLOR_EDITOR (object);
324 GtkColorChooser *cc = GTK_COLOR_CHOOSER (object);
329 gtk_color_chooser_set_color (cc, g_value_get_boxed (value));
331 case PROP_SHOW_ALPHA:
332 gtk_color_editor_set_show_alpha (ce, g_value_get_boolean (value));
335 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
341 gtk_color_editor_class_init (GtkColorEditorClass *class)
343 GObjectClass *object_class = G_OBJECT_CLASS (class);
345 object_class->get_property = gtk_color_editor_get_property;
346 object_class->set_property = gtk_color_editor_set_property;
348 g_object_class_override_property (object_class, PROP_COLOR, "color");
349 g_object_class_override_property (object_class, PROP_SHOW_ALPHA, "show-alpha");
351 g_type_class_add_private (class, sizeof (GtkColorEditorPrivate));
355 gtk_color_editor_get_color (GtkColorChooser *chooser,
358 GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
360 color->red = editor->priv->color.red;
361 color->green = editor->priv->color.green;
362 color->blue = editor->priv->color.blue;
363 color->alpha = editor->priv->color.alpha;
367 gtk_color_editor_set_color (GtkColorChooser *chooser,
368 const GdkRGBA *color)
370 GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
372 editor->priv->color.red = color->red;
373 editor->priv->color.green = color->green;
374 editor->priv->color.blue = color->blue;
375 gtk_rgb_to_hsv (editor->priv->color.red,
376 editor->priv->color.green,
377 editor->priv->color.blue,
378 &editor->priv->h, &editor->priv->s, &editor->priv->v);
379 gtk_color_plane_set_h (GTK_COLOR_PLANE (editor->priv->sv_plane), editor->priv->h);
380 gtk_color_plane_set_s (GTK_COLOR_PLANE (editor->priv->sv_plane), editor->priv->s);
381 gtk_color_plane_set_v (GTK_COLOR_PLANE (editor->priv->sv_plane), editor->priv->v);
382 gtk_adjustment_set_value (editor->priv->h_adj, editor->priv->h);
383 update_entry (editor);
385 editor->priv->color.alpha = color->alpha;
386 gtk_adjustment_set_value (editor->priv->a_adj, editor->priv->color.alpha);
388 gtk_widget_queue_draw (GTK_WIDGET (editor));
390 g_object_notify (G_OBJECT (editor), "color");
394 gtk_color_editor_iface_init (GtkColorChooserInterface *iface)
396 iface->get_color = gtk_color_editor_get_color;
397 iface->set_color = gtk_color_editor_set_color;
401 gtk_color_editor_new (void)
403 return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_EDITOR, NULL);