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
11
* the License, or (at your option) any later version.
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.
36
* <title>HildonColorButton example</title>
38
* HildonColorButton *cbutton;
41
* cbutton = hildon_color_button_new();
42
* gtk_object_get( GTK_OBJECT(cbutton), "color", color );
48
#undef HILDON_DISABLE_DEPRECATED
54
#include <gdk/gdkkeysyms.h>
56
#include "hildon-color-button.h"
57
#include "hildon-defines.h"
58
#include "hildon-color-chooser-dialog.h"
59
#include "hildon-color-button-private.h"
61
#define COLOR_FILLED_HEIGHT 22
63
#define COLOR_FILLED_WIDTH 22
65
#define COLOR_BUTTON_WIDTH 52
67
#define COLOR_BUTTON_HEIGHT 48
69
#define OUTER_BORDER_RED 0
71
#define OUTER_BORDER_BLUE 0
73
#define OUTER_BORDER_GREEN 0
75
#define OUTER_BORDER_THICKNESS 1
77
#define INNER_BORDER_RED 65535
79
#define INNER_BORDER_BLUE 65535
81
#define INNER_BORDER_GREEN 65535
83
#define INNER_BORDER_THICKNESS 2
99
hildon_color_button_class_init (HildonColorButtonClass *klass);
102
hildon_color_button_init (HildonColorButton *color_button);
105
hildon_color_button_finalize (GObject *object);
108
hildon_color_button_set_property (GObject *object,
114
hildon_color_button_get_property (GObject *object,
120
hildon_color_button_realize (GtkWidget *widget);
123
hildon_color_button_unrealize (GtkWidget *widget);
126
hildon_color_button_clicked (GtkButton *button);
129
hildon_color_button_key_pressed (GtkWidget *button,
134
hildon_color_field_expose_event (GtkWidget *widget,
135
GdkEventExpose *event,
136
HildonColorButton *cb);
139
hildon_color_button_mnemonic_activate (GtkWidget *widget,
140
gboolean group_cycling);
143
draw_grid (GdkDrawable *drawable,
150
static gpointer parent_class = NULL;
151
static guint signals [LAST_SIGNAL] = { 0, };
154
* hildon_color_button_get_type:
156
* Initializes and returns the type of a hildon color button.
158
* @Returns: GType of #HildonColorButton.
161
hildon_color_button_get_type (void)
163
static GType color_button_type = 0;
165
if (! color_button_type)
167
static const GTypeInfo color_button_info =
169
sizeof (HildonColorButtonClass),
170
NULL, /* base_init */
171
NULL, /* base_finalize */
172
(GClassInitFunc) hildon_color_button_class_init,
173
NULL, /* class_finalize */
174
NULL, /* class_data */
175
sizeof (HildonColorButton),
177
(GInstanceInitFunc) hildon_color_button_init,
180
color_button_type = g_type_register_static (GTK_TYPE_BUTTON, "HildonColorButton",
181
&color_button_info, 0);
184
return color_button_type;
188
hildon_color_button_class_init (HildonColorButtonClass *klass)
190
GObjectClass *gobject_class;
191
GtkButtonClass *button_class;
192
GtkWidgetClass *widget_class;
194
gobject_class = G_OBJECT_CLASS (klass);
195
button_class = GTK_BUTTON_CLASS (klass);
196
widget_class = GTK_WIDGET_CLASS (klass);
198
parent_class = g_type_class_peek_parent (klass);
200
gobject_class->get_property = hildon_color_button_get_property;
201
gobject_class->set_property = hildon_color_button_set_property;
202
gobject_class->finalize = hildon_color_button_finalize;
203
widget_class->realize = hildon_color_button_realize;
204
widget_class->unrealize = hildon_color_button_unrealize;
205
button_class->clicked = hildon_color_button_clicked;
206
widget_class->mnemonic_activate = hildon_color_button_mnemonic_activate;
208
signals[SETUP_DIALOG] =
209
g_signal_new ("setup-dialog",
210
G_TYPE_FROM_CLASS (klass),
214
gtk_marshal_VOID__OBJECT,
216
HILDON_TYPE_COLOR_CHOOSER_DIALOG);
219
* HildonColorButton:color:
221
* The currently selected color.
223
g_object_class_install_property (gobject_class, PROP_COLOR,
224
g_param_spec_boxed ("color",
226
"The selected color",
231
* HildonColorButton:popup-shown:
233
* If the color selection dialog is currently popped-up (visible)
235
g_object_class_install_property (gobject_class, PROP_POPUP_SHOWN,
236
g_param_spec_boolean ("popup-shown",
238
"If the color selection dialog is popped up",
242
g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate));
245
/* FIXME Draw a dotted grid over the specified area to make it look
246
* insensitive. Actually, we should generate that pixbuf once and
247
* just render it over later... */
249
draw_grid (GdkDrawable *drawable,
258
for (currenty = y; currenty <= h; currenty++)
259
for (currentx = ((currenty % 2 == 0) ? x : x + 1); currentx <= w; currentx += 2)
260
gdk_draw_point (drawable, gc, currentx, currenty);
263
/* Handle exposure events for the color picker's drawing area */
265
hildon_color_field_expose_event (GtkWidget *widget,
266
GdkEventExpose *event,
267
HildonColorButton *cb)
269
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
270
GdkColor outer_border, inner_border;
274
/* Create the outer border color */
275
outer_border.pixel = 0;
276
outer_border.red = OUTER_BORDER_RED;
277
outer_border.blue = OUTER_BORDER_BLUE;
278
outer_border.green = OUTER_BORDER_GREEN;
280
/* Create the inner border color */
281
inner_border.pixel = 0;
282
inner_border.red = INNER_BORDER_RED;
283
inner_border.blue = INNER_BORDER_BLUE;
284
inner_border.green = INNER_BORDER_GREEN;
286
/* serve the outer border color to the Graphic Context */
287
gdk_gc_set_rgb_fg_color (priv->gc, &outer_border);
288
/* draw the outer border as a filled rectangle */
289
gdk_draw_rectangle (widget->window,
290
(GTK_WIDGET_IS_SENSITIVE (widget)) ? priv->gc : widget->style->bg_gc [GTK_STATE_INSENSITIVE],
294
widget->allocation.width,
295
widget->allocation.height);
297
/* serve the inner border color to the Graphic Context */
298
gdk_gc_set_rgb_fg_color (priv->gc, &inner_border);
300
/* draw the inner border as a filled rectangle */
301
gdk_draw_rectangle (widget->window,
304
OUTER_BORDER_THICKNESS,
305
OUTER_BORDER_THICKNESS,
306
widget->allocation.width - (OUTER_BORDER_THICKNESS * 2),
307
widget->allocation.height - (OUTER_BORDER_THICKNESS * 2));
309
/* serve the actual color to the Graphic Context */
310
gdk_gc_set_rgb_fg_color(priv->gc, &priv->color);
312
/* draw the actual rectangle */
313
gdk_draw_rectangle(widget->window,
316
INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
317
INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
318
widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2),
319
widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2));
321
if (! GTK_WIDGET_IS_SENSITIVE (widget)) {
322
draw_grid (GDK_DRAWABLE (widget->window), widget->style->bg_gc [GTK_STATE_INSENSITIVE],
323
INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
324
INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS,
325
widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2,
326
widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2);
333
hildon_color_button_init (HildonColorButton *cb)
336
GtkWidget *drawing_area;
337
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
341
priv->popped = FALSE;
343
gtk_widget_push_composite_child ();
345
/* create widgets and pixbuf */
346
align = gtk_alignment_new (0.5, 0.5, 0, 0); /* composite widget */
348
drawing_area = gtk_drawing_area_new (); /* composite widget */
350
/* setting minimum sizes */
351
gtk_widget_set_size_request (GTK_WIDGET (cb), COLOR_BUTTON_WIDTH,
352
COLOR_BUTTON_HEIGHT);
354
gtk_widget_set_size_request (GTK_WIDGET(drawing_area),
355
COLOR_FILLED_WIDTH, COLOR_FILLED_HEIGHT);
357
/* Connect the callback function for exposure event */
358
g_signal_connect (drawing_area, "expose-event",
359
G_CALLBACK (hildon_color_field_expose_event), cb);
361
/* Connect to callback function for key press event */
362
g_signal_connect (G_OBJECT(cb), "key-press-event",
363
G_CALLBACK(hildon_color_button_key_pressed), cb);
366
gtk_container_add (GTK_CONTAINER (align), drawing_area);
367
gtk_container_add (GTK_CONTAINER (cb), align);
369
gtk_widget_show_all (align);
371
gtk_widget_pop_composite_child ();
374
/* Free memory used by HildonColorButton */
376
hildon_color_button_finalize (GObject *object)
378
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (object);
383
gtk_widget_destroy (priv->dialog);
387
if (G_OBJECT_CLASS (parent_class)->finalize)
388
G_OBJECT_CLASS (parent_class)->finalize (object);
392
hildon_color_button_realize (GtkWidget *widget)
394
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget);
397
GTK_WIDGET_CLASS (parent_class)->realize (widget);
399
priv->gc = gdk_gc_new (widget->window);
403
hildon_color_button_unrealize (GtkWidget *widget)
405
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget);
408
if (priv->gc != NULL) {
409
g_object_unref (priv->gc);
413
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
416
/* Make the widget sensitive with the keyboard event */
418
hildon_color_button_mnemonic_activate (GtkWidget *widget,
419
gboolean group_cycling)
421
gtk_widget_grab_focus (widget);
425
/* Popup a color selector dialog on button click */
427
hildon_color_button_clicked (GtkButton *button)
429
HildonColorButton *cb = HILDON_COLOR_BUTTON (button);
430
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button);
431
HildonColorChooserDialog *cs_dialog;
435
cs_dialog = (HildonColorChooserDialog *) priv->dialog;
437
/* Popup the color selector dialog */
440
/* The dialog hasn't been created yet, do it */
441
GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET(cb));
442
priv->dialog = hildon_color_chooser_dialog_new ();
443
cs_dialog = HILDON_COLOR_CHOOSER_DIALOG (priv->dialog);
445
gtk_window_set_transient_for (GTK_WINDOW (cs_dialog), GTK_WINDOW (parent));
447
g_signal_emit (button, signals[SETUP_DIALOG], 0, priv->dialog);
450
/* Set the initial color for the color selector dialog */
451
hildon_color_chooser_dialog_set_color (cs_dialog, &priv->color);
453
/* Update the color for color button if selection was made */
455
if (gtk_dialog_run (GTK_DIALOG (cs_dialog)) == GTK_RESPONSE_OK)
457
hildon_color_chooser_dialog_get_color (cs_dialog, &priv->color);
458
hildon_color_button_set_color (HILDON_COLOR_BUTTON (button), &priv->color);
459
// FIXME A queue-draw should be enough here (not set needed)
462
gtk_widget_hide (GTK_WIDGET(cs_dialog));
463
priv->popped = FALSE;
466
/* Popup a color selector dialog on hardkey Select press.
467
* FIXME This is a bit hacky, should work without thi. Check. */
469
hildon_color_button_key_pressed (GtkWidget *button,
473
g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE);
475
if (event->keyval == HILDON_HARDKEY_SELECT)
477
hildon_color_button_clicked (GTK_BUTTON (button));
485
hildon_color_button_set_property (GObject *object,
490
HildonColorButton *cb = HILDON_COLOR_BUTTON (object);
491
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
498
priv->color = *(GdkColor *) g_value_get_boxed (value);
499
gtk_widget_queue_draw (GTK_WIDGET (cb));
503
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
509
hildon_color_button_get_property (GObject *object,
514
HildonColorButton *cb = HILDON_COLOR_BUTTON (object);
515
HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb);
522
g_value_set_boxed (value, &priv->color);
525
case PROP_POPUP_SHOWN:
526
g_value_set_boolean (value, priv->popped);
529
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
535
* hildon_color_button_new:
537
* Creates a new color button. This returns a widget in the form of a
538
* small button containing a swatch representing the selected color.
539
* When the button is clicked, a color-selection dialog will open,
540
* allowing the user to select a color. The swatch will be updated to
541
* reflect the new color when the user finishes.
543
* Returns: a new color button
546
hildon_color_button_new (void)
548
return g_object_new (HILDON_TYPE_COLOR_BUTTON, NULL);
552
* hildon_color_button_new_with_color:
553
* @color: a #GdkColor for the initial color
555
* Creates a new color button with @color as the initial color.
557
* Returns: a new color button
560
hildon_color_button_new_with_color (const GdkColor *color)
562
return g_object_new (HILDON_TYPE_COLOR_BUTTON, "color", color, NULL);
566
* hildon_color_button_set_color:
567
* @button: a #HildonColorButton
568
* @color: a color to be set
570
* Sets the color selected by the button.
573
hildon_color_button_set_color (HildonColorButton *button,
576
g_return_if_fail (HILDON_IS_COLOR_BUTTON (button));
578
g_object_set (G_OBJECT (button), "color", color, NULL);
582
* hildon_color_button_get_popup_shown
583
* @button: a #HildonColorButton
585
* This function checks if the color button has the color
586
* selection dialog currently popped-up.
588
* Returns: TRUE if the dialog is popped-up (visible to user).
592
hildon_color_button_get_popup_shown (HildonColorButton *button)
594
HildonColorButtonPrivate *priv = NULL;
595
g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE);
597
priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button);
604
* hildon_color_button_popdown
605
* @button: a #HildonColorButton
607
* If the color selection dialog is currently popped-up (visible)
608
* it will be popped-down (hidden).
612
hildon_color_button_popdown (HildonColorButton *button)
614
HildonColorButtonPrivate *priv = NULL;
615
g_return_if_fail (HILDON_IS_COLOR_BUTTON (button));
617
priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button);
620
if (priv->popped && priv->dialog) {
621
gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_CANCEL);
626
* hildon_color_button_get_color:
627
* @button: a #HildonColorButton
628
* @color: a color #GdkColor to be fillled with the current color
632
hildon_color_button_get_color (HildonColorButton *button,
635
HildonColorButtonPrivate *priv = NULL;
636
g_return_if_fail (HILDON_IS_COLOR_BUTTON (button));
637
g_return_if_fail (color != NULL);
639
priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button);
642
color->red = priv->color.red;
643
color->green = priv->color.green;
644
color->blue = priv->color.blue;
645
color->pixel = priv->color.pixel;