2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-color-button
27 * @short_description: A widget to open HildonColorChooserDialog
28 * @see_also: #HildonColorChooserDialog, #HildonColorPopup
30 * HildonColorButton is a widget to open a HildonColorChooserDialog.
31 * The selected color is shown in the button.
32 * The selected color is a property of the button.
33 * The property name is "color" and its type is GtkColor.
40 #include "hildon-color-button.h"
41 #include <gtk/gtkbutton.h>
42 #include <gtk/gtkalignment.h>
43 #include <gtk/gtkdrawingarea.h>
44 #include <gtk/gtksignal.h>
45 #include <gdk/gdkkeysyms.h>
46 #include "hildon-defines.h"
47 #include "hildon-color-chooser-dialog.h"
48 #include "hildon-color-button-private.h"
50 #define COLOR_FILLED_HEIGHT 22
52 #define COLOR_FILLED_WIDTH 22
54 #define COLOR_BUTTON_WIDTH 52
56 #define COLOR_BUTTON_HEIGHT 48
58 #define OUTER_BORDER_RED 0
60 #define OUTER_BORDER_BLUE 0
62 #define OUTER_BORDER_GREEN 0
64 #define OUTER_BORDER_THICKNESS 1
66 #define INNER_BORDER_RED 65535
68 #define INNER_BORDER_BLUE 65535
70 #define INNER_BORDER_GREEN 65535
72 #define INNER_BORDER_THICKNESS 2
81 hildon_color_button_class_init (HildonColorButtonClass *klass);
84 hildon_color_button_init (HildonColorButton *color_button);
87 hildon_color_button_finalize (GObject *object);
90 hildon_color_button_set_property (GObject *object,
96 hildon_color_button_get_property (GObject *object,
102 hildon_color_button_realize (GtkWidget *widget);
105 hildon_color_button_unrealize (GtkWidget *widget);
108 hildon_color_button_clicked (GtkButton *button);
111 hildon_color_button_key_pressed (GtkWidget *button,
116 hildon_color_field_expose_event (GtkWidget *widget,
117 GdkEventExpose *event,
118 HildonColorButton *cb);
121 hildon_color_button_mnemonic_activate (GtkWidget *widget,
122 gboolean group_cycling);
125 draw_grid (GdkDrawable *drawable,
132 static gpointer parent_class = NULL;
135 hildon_color_button_get_type (void)
137 static GType color_button_type = 0;
139 if (! color_button_type)
141 static const GTypeInfo color_button_info =
143 sizeof (HildonColorButtonClass),
144 NULL, /* base_init */
145 NULL, /* base_finalize */
146 (GClassInitFunc) hildon_color_button_class_init,
147 NULL, /* class_finalize */
148 NULL, /* class_data */
149 sizeof (HildonColorButton),
151 (GInstanceInitFunc) hildon_color_button_init,
154 color_button_type = g_type_register_static (GTK_TYPE_BUTTON, "HildonColorButton",
155 &color_button_info, 0);
158 return color_button_type;
162 hildon_color_button_class_init (HildonColorButtonClass *klass)
164 GObjectClass *gobject_class;
165 GtkButtonClass *button_class;
166 GtkWidgetClass *widget_class;
168 gobject_class = G_OBJECT_CLASS (klass);
169 button_class = GTK_BUTTON_CLASS (klass);
170 widget_class = GTK_WIDGET_CLASS (klass);
172 parent_class = g_type_class_peek_parent (klass);
174 gobject_class->get_property = hildon_color_button_get_property;
175 gobject_class->set_property = hildon_color_button_set_property;
176 gobject_class->finalize = hildon_color_button_finalize;
177 widget_class->realize = hildon_color_button_realize;
178 widget_class->unrealize = hildon_color_button_unrealize;
179 button_class->clicked = hildon_color_button_clicked;
180 widget_class->mnemonic_activate = hildon_color_button_mnemonic_activate;
183 * HildonColorButton:color:
185 * The currently selected color.
187 g_object_class_install_property (gobject_class, PROP_COLOR,
188 g_param_spec_boxed ("color",
190 "The selected color",
194 g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate));
197 /* FIXME Draw a dotted grid over the specified area to make it look
198 * insensitive. Actually, we should generate that pixbuf once and
199 * just render it over later... */
201 draw_grid (GdkDrawable *drawable,
210 for (currenty = y; currenty <= h; currenty++)
211 for (currentx = ((currenty % 2 == 0) ? x : x + 1); currentx <= w; currentx += 2)
212 gdk_draw_point (drawable, gc, currentx, currenty);
215 /* Handle exposure events for the color picker's drawing area */
217 hildon_color_field_expose_event (GtkWidget *widget,
218 GdkEventExpose *event,
219 HildonColorButton *cb)
221 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
222 GdkColor outer_border, inner_border;
226 /* Create the outer border color */
227 outer_border.pixel = 0;
228 outer_border.red = OUTER_BORDER_RED;
229 outer_border.blue = OUTER_BORDER_BLUE;
230 outer_border.green = OUTER_BORDER_GREEN;
232 /* Create the inner border color */
233 inner_border.pixel = 0;
234 inner_border.red = INNER_BORDER_RED;
235 inner_border.blue = INNER_BORDER_BLUE;
236 inner_border.green = INNER_BORDER_GREEN;
238 /* serve the outer border color to the Graphic Context */
239 gdk_gc_set_rgb_fg_color (priv->gc, &outer_border);
240 /* draw the outer border as a filled rectangle */
241 gdk_draw_rectangle (widget->window,
242 (GTK_WIDGET_IS_SENSITIVE (widget)) ? priv->gc : widget->style->bg_gc [GTK_STATE_INSENSITIVE],
246 widget->allocation.width,
247 widget->allocation.height);
249 /* serve the inner border color to the Graphic Context */
250 gdk_gc_set_rgb_fg_color (priv->gc, &inner_border);
252 /* draw the inner border as a filled rectangle */
253 gdk_draw_rectangle (widget->window,
256 OUTER_BORDER_THICKNESS,
257 OUTER_BORDER_THICKNESS,
258 widget->allocation.width - (OUTER_BORDER_THICKNESS * 2),
259 widget->allocation.height - (OUTER_BORDER_THICKNESS * 2));
261 /* serve the actual color to the Graphic Context */
262 gdk_gc_set_rgb_fg_color(priv->gc, &priv->color);
264 /* draw the actual rectangle */
265 gdk_draw_rectangle(widget->window,
268 INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
269 INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
270 widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2),
271 widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2));
273 if (! GTK_WIDGET_IS_SENSITIVE (widget)) {
274 draw_grid (GDK_DRAWABLE (widget->window), widget->style->bg_gc [GTK_STATE_INSENSITIVE],
275 INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
276 INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
277 widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2,
278 widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2);
285 hildon_color_button_init (HildonColorButton *cb)
288 GtkWidget *drawing_area;
289 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
294 gtk_widget_push_composite_child ();
296 /* create widgets and pixbuf */
297 align = gtk_alignment_new (0.5, 0.5, 0, 0); /* composite widget */
299 drawing_area = gtk_drawing_area_new (); /* composite widget */
301 /* setting minimum sizes */
302 gtk_widget_set_size_request (GTK_WIDGET (cb), COLOR_BUTTON_WIDTH,
303 COLOR_BUTTON_HEIGHT);
305 gtk_widget_set_size_request (GTK_WIDGET(drawing_area),
306 COLOR_FILLED_WIDTH, COLOR_FILLED_HEIGHT);
308 /* Connect the callback function for exposure event */
309 g_signal_connect (drawing_area, "expose-event",
310 G_CALLBACK (hildon_color_field_expose_event), cb);
312 /* Connect to callback function for key press event */
313 g_signal_connect (G_OBJECT(cb), "key-press-event",
314 G_CALLBACK(hildon_color_button_key_pressed), cb);
317 gtk_container_add (GTK_CONTAINER (align), drawing_area);
318 gtk_container_add (GTK_CONTAINER (cb), align);
320 gtk_widget_show_all (align);
322 gtk_widget_pop_composite_child ();
325 /* Free memory used by HildonColorButton */
327 hildon_color_button_finalize (GObject *object)
329 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (object);
334 gtk_widget_destroy(priv->dialog);
338 if (G_OBJECT_CLASS (parent_class)->finalize)
339 G_OBJECT_CLASS (parent_class)->finalize (object);
343 hildon_color_button_realize (GtkWidget *widget)
345 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget);
348 GTK_WIDGET_CLASS (parent_class)->realize (widget);
350 priv->gc = gdk_gc_new (widget->window);
354 hildon_color_button_unrealize (GtkWidget *widget)
356 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget);
359 if (priv->gc != NULL) {
360 g_object_unref (priv->gc);
364 GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
367 /* Make the widget sensitive with the keyboard event */
369 hildon_color_button_mnemonic_activate (GtkWidget *widget,
370 gboolean group_cycling)
372 gtk_widget_grab_focus (widget);
376 /* Popup a color selector dialog on button click */
378 hildon_color_button_clicked (GtkButton *button)
380 HildonColorButton *cb = HILDON_COLOR_BUTTON (button);
381 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button);
382 HildonColorChooserDialog *cs_dialog;
386 cs_dialog = (HildonColorChooserDialog *) priv->dialog;
388 /* Popup the color selector dialog */
391 /* The dialog hasn't been created yet, do it */
392 GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET(cb));
393 priv->dialog = hildon_color_chooser_dialog_new ();
394 cs_dialog = HILDON_COLOR_CHOOSER_DIALOG (priv->dialog);
396 gtk_window_set_transient_for (GTK_WINDOW (cs_dialog), GTK_WINDOW (parent));
399 /* Set the initial color for the color selector dialog */
400 hildon_color_chooser_dialog_set_color (cs_dialog, &priv->color);
402 /* Update the color for color button if selection was made */
403 if (gtk_dialog_run (GTK_DIALOG (cs_dialog)) == GTK_RESPONSE_OK)
405 hildon_color_chooser_dialog_get_color (cs_dialog, &priv->color);
406 hildon_color_button_set_color (HILDON_COLOR_BUTTON (button), &priv->color);
407 // FIXME A queue-draw should be enough here (not set needed)
410 gtk_widget_hide (GTK_WIDGET(cs_dialog));
413 /* Popup a color selector dialog on hardkey Select press.
414 * FIXME This is a bit hacky, should work without thi. Check. */
416 hildon_color_button_key_pressed (GtkWidget *button,
420 g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE);
422 if (event->keyval == HILDON_HARDKEY_SELECT)
424 hildon_color_button_clicked (GTK_BUTTON (button));
432 hildon_color_button_set_property (GObject *object,
437 HildonColorButton *cb = HILDON_COLOR_BUTTON (object);
438 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
445 priv->color = *(GdkColor *) g_value_get_boxed (value);
446 gtk_widget_queue_draw (GTK_WIDGET (cb));
450 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
456 hildon_color_button_get_property (GObject *object,
461 HildonColorButton *cb = HILDON_COLOR_BUTTON (object);
462 HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
469 g_value_set_boxed (value, &priv->color);
473 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
479 * hildon_color_button_new:
481 * Creates a new color button. This returns a widget in the form of a
482 * small button containing a swatch representing the selected color.
483 * When the button is clicked, a color-selection dialog will open,
484 * allowing the user to select a color. The swatch will be updated to
485 * reflect the new color when the user finishes.
487 * Returns: a new color button
490 hildon_color_button_new (void)
492 return g_object_new (HILDON_TYPE_COLOR_BUTTON, NULL);
496 * hildon_color_button_new_with_color:
497 * @color: a #GdkColor for the initial color
499 * Creates a new color button with @color as the initial color.
501 * Returns: a new color button
504 hildon_color_button_new_with_color (const GdkColor *color)
506 return g_object_new (HILDON_TYPE_COLOR_BUTTON, "color", color, NULL);
510 * hildon_color_button_set_color:
511 * @button: a #HildonColorButton
512 * @color: a color to be set
514 * Sets the color selected by the button.
517 hildon_color_button_set_color (HildonColorButton *button,
520 g_return_if_fail (HILDON_IS_COLOR_BUTTON (button));
522 g_object_set (G_OBJECT (button), "color", color, NULL);
526 * hildon_color_button_get_color:
527 * @button: a #HildonColorButton
528 * @color: a color #GdkColor to be fillled with the current color
532 hildon_color_button_get_color (HildonColorButton *button,
535 HildonColorButtonPrivate *priv = NULL;
536 g_return_if_fail (HILDON_IS_COLOR_BUTTON (button));
537 g_return_if_fail (color != NULL);
539 priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button);
542 color->red = priv->color.red;
543 color->green = priv->color.green;
544 color->blue = priv->color.blue;
545 color->pixel = priv->color.pixel;