diff options
author | Alberto Garcia <agarcia@igalia.com> | 2009-04-30 13:10:26 +0200 |
---|---|---|
committer | Alberto Garcia <agarcia@igalia.com> | 2009-04-30 13:33:58 +0200 |
commit | 69a11338fe0cc36a868e5812b590f5437622988a (patch) | |
tree | abd1efc835e7e30f7799eac64ff45405f1624528 /hildon/hildon-color-button.c | |
parent | 8a970bcc0a22925ed90b869c8f7c1ba521e189ac (diff) |
Renamed src/ to hildon/
* src/
* Makefile.am
* configure.ac
* doc/Makefile.am
* doc/hildon.types
* po/POTFILES.in:
Renamed src/ to hildon/
* examples/*.c
* debian/changelog
* debian/rules:
Include <hildon/hildon.h> directly in all examples.
Diffstat (limited to 'hildon/hildon-color-button.c')
-rw-r--r-- | hildon/hildon-color-button.c | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/hildon/hildon-color-button.c b/hildon/hildon-color-button.c new file mode 100644 index 0000000..49c0dfe --- /dev/null +++ b/hildon/hildon-color-button.c @@ -0,0 +1,648 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo <rodrigo.novo@nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-color-button + * @short_description: A widget to open HildonColorChooserDialog. + * @see_also: #HildonColorChooserDialog, #HildonColorPopup + * + * HildonColorButton is a widget to open a HildonColorChooserDialog. + * The selected color is shown in the button. + * The selected color is a property of the button. + * The property name is "color" and its type is GtkColor. + * + * <example> + * <title>HildonColorButton example</title> + * <programlisting> + * HildonColorButton *cbutton; + * GtkColor *color; + * <!-- --> + * cbutton = hildon_color_button_new(); + * gtk_object_get( GTK_OBJECT(cbutton), "color", color ); + * </programlisting> + * </example> + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gdk/gdkkeysyms.h> + +#include "hildon-color-button.h" +#include "hildon-defines.h" +#include "hildon-color-chooser-dialog.h" +#include "hildon-color-button-private.h" + +#define COLOR_FILLED_HEIGHT 22 + +#define COLOR_FILLED_WIDTH 22 + +#define COLOR_BUTTON_WIDTH 52 + +#define COLOR_BUTTON_HEIGHT 48 + +#define OUTER_BORDER_RED 0 + +#define OUTER_BORDER_BLUE 0 + +#define OUTER_BORDER_GREEN 0 + +#define OUTER_BORDER_THICKNESS 1 + +#define INNER_BORDER_RED 65535 + +#define INNER_BORDER_BLUE 65535 + +#define INNER_BORDER_GREEN 65535 + +#define INNER_BORDER_THICKNESS 2 + +enum +{ + SETUP_DIALOG, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_COLOR, + PROP_POPUP_SHOWN +}; + +static void +hildon_color_button_class_init (HildonColorButtonClass *klass); + +static void +hildon_color_button_init (HildonColorButton *color_button); + +static void +hildon_color_button_finalize (GObject *object); + +static void +hildon_color_button_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_color_button_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +static void +hildon_color_button_realize (GtkWidget *widget); + +static void +hildon_color_button_unrealize (GtkWidget *widget); + +static void +hildon_color_button_clicked (GtkButton *button); + +static gboolean +hildon_color_button_key_pressed (GtkWidget *button, + GdkEventKey *event, + gpointer data); + +static gint +hildon_color_field_expose_event (GtkWidget *widget, + GdkEventExpose *event, + HildonColorButton *cb); + +static gboolean +hildon_color_button_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling); + +static void +draw_grid (GdkDrawable *drawable, + GdkGC *gc, + int x, + int y, + gint w, + gint h); + +static gpointer parent_class = NULL; +static guint signals [LAST_SIGNAL] = { 0, }; + +/** + * hildon_color_button_get_type: + * + * Initializes and returns the type of a hildon color button. + * + * Returns: GType of #HildonColorButton. + */ +GType G_GNUC_CONST +hildon_color_button_get_type (void) +{ + static GType color_button_type = 0; + + if (! color_button_type) + { + static const GTypeInfo color_button_info = + { + sizeof (HildonColorButtonClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_color_button_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (HildonColorButton), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_color_button_init, + }; + + color_button_type = g_type_register_static (GTK_TYPE_BUTTON, "HildonColorButton", + &color_button_info, 0); + } + + return color_button_type; +} + +static void +hildon_color_button_class_init (HildonColorButtonClass *klass) +{ + GObjectClass *gobject_class; + GtkButtonClass *button_class; + GtkWidgetClass *widget_class; + + gobject_class = G_OBJECT_CLASS (klass); + button_class = GTK_BUTTON_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->get_property = hildon_color_button_get_property; + gobject_class->set_property = hildon_color_button_set_property; + gobject_class->finalize = hildon_color_button_finalize; + widget_class->realize = hildon_color_button_realize; + widget_class->unrealize = hildon_color_button_unrealize; + button_class->clicked = hildon_color_button_clicked; + widget_class->mnemonic_activate = hildon_color_button_mnemonic_activate; + + signals[SETUP_DIALOG] = + g_signal_new ("setup-dialog", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + HILDON_TYPE_COLOR_CHOOSER_DIALOG); + + /** + * HildonColorButton:color: + * + * The currently selected color. + */ + g_object_class_install_property (gobject_class, PROP_COLOR, + g_param_spec_boxed ("color", + "Current Color", + "The selected color", + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + /** + * HildonColorButton:popup-shown: + * + * If the color selection dialog is currently popped-up (visible) + */ + g_object_class_install_property (gobject_class, PROP_POPUP_SHOWN, + g_param_spec_boolean ("popup-shown", + "IsPopped", + "If the color selection dialog is popped up", + FALSE, + G_PARAM_READABLE)); + + g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate)); +} + +/* FIXME Draw a dotted grid over the specified area to make it look + * insensitive. Actually, we should generate that pixbuf once and + * just render it over later... */ +static void +draw_grid (GdkDrawable *drawable, + GdkGC *gc, + int x, + int y, + gint w, + gint h) +{ + int currentx; + int currenty; + for (currenty = y; currenty <= h; currenty++) + for (currentx = ((currenty % 2 == 0) ? x : x + 1); currentx <= w; currentx += 2) + gdk_draw_point (drawable, gc, currentx, currenty); +} + +/* Handle exposure events for the color picker's drawing area */ +static gint +hildon_color_field_expose_event (GtkWidget *widget, + GdkEventExpose *event, + HildonColorButton *cb) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + GdkColor outer_border, inner_border; + + g_assert (priv); + + /* Create the outer border color */ + outer_border.pixel = 0; + outer_border.red = OUTER_BORDER_RED; + outer_border.blue = OUTER_BORDER_BLUE; + outer_border.green = OUTER_BORDER_GREEN; + + /* Create the inner border color */ + inner_border.pixel = 0; + inner_border.red = INNER_BORDER_RED; + inner_border.blue = INNER_BORDER_BLUE; + inner_border.green = INNER_BORDER_GREEN; + + /* serve the outer border color to the Graphic Context */ + gdk_gc_set_rgb_fg_color (priv->gc, &outer_border); + /* draw the outer border as a filled rectangle */ + gdk_draw_rectangle (widget->window, + (GTK_WIDGET_IS_SENSITIVE (widget)) ? priv->gc : widget->style->bg_gc [GTK_STATE_INSENSITIVE], + TRUE, + 0, + 0, + widget->allocation.width, + widget->allocation.height); + + /* serve the inner border color to the Graphic Context */ + gdk_gc_set_rgb_fg_color (priv->gc, &inner_border); + + /* draw the inner border as a filled rectangle */ + gdk_draw_rectangle (widget->window, + priv->gc, + TRUE, + OUTER_BORDER_THICKNESS, + OUTER_BORDER_THICKNESS, + widget->allocation.width - (OUTER_BORDER_THICKNESS * 2), + widget->allocation.height - (OUTER_BORDER_THICKNESS * 2)); + + /* serve the actual color to the Graphic Context */ + gdk_gc_set_rgb_fg_color(priv->gc, &priv->color); + + /* draw the actual rectangle */ + gdk_draw_rectangle(widget->window, + priv->gc, + TRUE, + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2), + widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2)); + + if (! GTK_WIDGET_IS_SENSITIVE (widget)) { + draw_grid (GDK_DRAWABLE (widget->window), widget->style->bg_gc [GTK_STATE_INSENSITIVE], + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2, + widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2); + } + + return FALSE; +} + +static void +hildon_color_button_init (HildonColorButton *cb) +{ + GtkWidget *align; + GtkWidget *drawing_area; + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + + priv->dialog = NULL; + priv->gc = NULL; + priv->popped = FALSE; + + gtk_widget_push_composite_child (); + + /* create widgets and pixbuf */ + align = gtk_alignment_new (0.5, 0.5, 0, 0); /* composite widget */ + + drawing_area = gtk_drawing_area_new (); /* composite widget */ + + /* setting minimum sizes */ + gtk_widget_set_size_request (GTK_WIDGET (cb), COLOR_BUTTON_WIDTH, + COLOR_BUTTON_HEIGHT); + + gtk_widget_set_size_request (GTK_WIDGET(drawing_area), + COLOR_FILLED_WIDTH, COLOR_FILLED_HEIGHT); + + /* Connect the callback function for exposure event */ + g_signal_connect (drawing_area, "expose-event", + G_CALLBACK (hildon_color_field_expose_event), cb); + + /* Connect to callback function for key press event */ + g_signal_connect (G_OBJECT(cb), "key-press-event", + G_CALLBACK(hildon_color_button_key_pressed), cb); + + /* packing */ + gtk_container_add (GTK_CONTAINER (align), drawing_area); + gtk_container_add (GTK_CONTAINER (cb), align); + + gtk_widget_show_all (align); + + gtk_widget_pop_composite_child (); +} + +/* Free memory used by HildonColorButton */ +static void +hildon_color_button_finalize (GObject *object) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (object); + g_assert (priv); + + if (priv->dialog) + { + gtk_widget_destroy (priv->dialog); + priv->dialog = NULL; + } + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +hildon_color_button_realize (GtkWidget *widget) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget); + g_assert (priv); + + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + priv->gc = gdk_gc_new (widget->window); +} + +static void +hildon_color_button_unrealize (GtkWidget *widget) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget); + g_assert (priv); + + if (priv->gc != NULL) { + g_object_unref (priv->gc); + priv->gc = NULL; + } + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +/* Make the widget sensitive with the keyboard event */ +static gboolean +hildon_color_button_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling) +{ + gtk_widget_grab_focus (widget); + return TRUE; +} + +/* Popup a color selector dialog on button click */ +static void +hildon_color_button_clicked (GtkButton *button) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON (button); + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + HildonColorChooserDialog *cs_dialog; + + g_assert (priv); + + cs_dialog = (HildonColorChooserDialog *) priv->dialog; + + /* Popup the color selector dialog */ + if (! cs_dialog) + { + /* The dialog hasn't been created yet, do it */ + GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET(cb)); + priv->dialog = hildon_color_chooser_dialog_new (); + cs_dialog = HILDON_COLOR_CHOOSER_DIALOG (priv->dialog); + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (cs_dialog), GTK_WINDOW (parent)); + + g_signal_emit (button, signals[SETUP_DIALOG], 0, priv->dialog); + } + + /* Set the initial color for the color selector dialog */ + hildon_color_chooser_dialog_set_color (cs_dialog, &priv->color); + + /* Update the color for color button if selection was made */ + priv->popped = TRUE; + if (gtk_dialog_run (GTK_DIALOG (cs_dialog)) == GTK_RESPONSE_OK) + { + hildon_color_chooser_dialog_get_color (cs_dialog, &priv->color); + hildon_color_button_set_color (HILDON_COLOR_BUTTON (button), &priv->color); + // FIXME A queue-draw should be enough here (not set needed) + } + + gtk_widget_hide (GTK_WIDGET(cs_dialog)); + priv->popped = FALSE; +} + +/* Popup a color selector dialog on hardkey Select press. + * FIXME This is a bit hacky, should work without thi. Check. */ +static gboolean +hildon_color_button_key_pressed (GtkWidget *button, + GdkEventKey *event, + gpointer data) +{ + g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE); + + if (event->keyval == HILDON_HARDKEY_SELECT) + { + hildon_color_button_clicked (GTK_BUTTON (button)); + return TRUE; + } + + return FALSE; +} + +static void +hildon_color_button_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON (object); + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + g_assert (priv); + + switch (param_id) + { + + case PROP_COLOR: + priv->color = *(GdkColor *) g_value_get_boxed (value); + gtk_widget_queue_draw (GTK_WIDGET (cb)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +hildon_color_button_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON (object); + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + g_assert (priv); + + switch (param_id) + { + + case PROP_COLOR: + g_value_set_boxed (value, &priv->color); + break; + + case PROP_POPUP_SHOWN: + g_value_set_boolean (value, priv->popped); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +/** + * hildon_color_button_new: + * + * Creates a new color button. This returns a widget in the form of a + * small button containing a swatch representing the selected color. + * When the button is clicked, a color-selection dialog will open, + * allowing the user to select a color. The swatch will be updated to + * reflect the new color when the user finishes. + * + * Returns: a new color button + */ +GtkWidget* +hildon_color_button_new (void) +{ + return g_object_new (HILDON_TYPE_COLOR_BUTTON, NULL); +} + +/** + * hildon_color_button_new_with_color: + * @color: a #GdkColor for the initial color + * + * Creates a new color button with @color as the initial color. + * + * Returns: a new color button + */ +GtkWidget* +hildon_color_button_new_with_color (const GdkColor *color) +{ + return g_object_new (HILDON_TYPE_COLOR_BUTTON, "color", color, NULL); +} + +/** + * hildon_color_button_set_color: + * @button: a #HildonColorButton + * @color: a color to be set + * + * Sets the color selected by the button. + */ +void +hildon_color_button_set_color (HildonColorButton *button, + GdkColor *color) +{ + g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); + + g_object_set (G_OBJECT (button), "color", color, NULL); +} + +/** + * hildon_color_button_get_popup_shown + * @button: a #HildonColorButton + * + * This function checks if the color button has the color + * selection dialog currently popped-up. + * + * Returns: TRUE if the dialog is popped-up (visible to user). + * + */ +gboolean +hildon_color_button_get_popup_shown (HildonColorButton *button) +{ + HildonColorButtonPrivate *priv = NULL; + g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE); + + priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + g_assert (priv); + + return priv->popped; +} + +/** + * hildon_color_button_popdown + * @button: a #HildonColorButton + * + * If the color selection dialog is currently popped-up (visible) + * it will be popped-down (hidden). + * + */ +void +hildon_color_button_popdown (HildonColorButton *button) +{ + HildonColorButtonPrivate *priv = NULL; + g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); + + priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + g_assert (priv); + + if (priv->popped && priv->dialog) { + gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_CANCEL); + } +} + +/** + * hildon_color_button_get_color: + * @button: a #HildonColorButton + * @color: a color #GdkColor to be fillled with the current color + * + */ +void +hildon_color_button_get_color (HildonColorButton *button, + GdkColor *color) +{ + HildonColorButtonPrivate *priv = NULL; + g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); + g_return_if_fail (color != NULL); + + priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + g_assert (priv); + + color->red = priv->color.red; + color->green = priv->color.green; + color->blue = priv->color.blue; + color->pixel = priv->color.pixel; +} + |