diff --git a/gtk/Makefile.am b/gtk/Makefile.am index dd8db33a6e..fddc1204a2 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -217,6 +217,9 @@ gtk_public_h_sources = \ gtkcolorbutton.h \ gtkcolorsel.h \ gtkcolorseldialog.h \ + gtkcolorchooser.h \ + gtkcolorchooserwidget.h \ + gtkcolorchooserdialog.h \ gtkcombobox.h \ gtkcomboboxtext.h \ gtkcontainer.h \ @@ -410,6 +413,9 @@ gtk_private_h_sources = \ gtkbuilderprivate.h \ gtkbuttonprivate.h \ gtkcellareaboxcontextprivate.h \ + gtkcolorswatch.h \ + gtkcoloreditor.h \ + gtkcolorchooserprivate.h \ gtkcontainerprivate.h \ gtkcsscomputedvaluesprivate.h \ gtkcsscustompropertyprivate.h \ @@ -592,6 +598,11 @@ gtk_base_c_sources = \ gtkcolorbutton.c \ gtkcolorsel.c \ gtkcolorseldialog.c \ + gtkcoloreditor.c \ + gtkcolorswatch.c \ + gtkcolorchooser.c \ + gtkcolorchooserwidget.c \ + gtkcolorchooserdialog.c \ gtkcombobox.c \ gtkcomboboxtext.c \ gtkcontainer.c \ @@ -1562,10 +1573,12 @@ EXTRA_DIST += \ gtktypebuiltins.h.template \ gtkprivatetypebuiltins.c.template \ gtkprivatetypebuiltins.h.template \ - org.gtk.Settings.FileChooser.gschema.xml + org.gtk.Settings.FileChooser.gschema.xml \ + org.gtk.Settings.ColorChooser.gschema.xml gsettings_SCHEMAS = \ - org.gtk.Settings.FileChooser.gschema.xml + org.gtk.Settings.FileChooser.gschema.xml \ + org.gtk.Settings.ColorChooser.gschema.xml @GSETTINGS_RULES@ diff --git a/gtk/gtkcolorchooser.c b/gtk/gtkcolorchooser.c new file mode 100644 index 0000000000..a63566f84b --- /dev/null +++ b/gtk/gtkcolorchooser.c @@ -0,0 +1,110 @@ +/* GTK - The GIMP Toolkit + * + * Copyright (C) 2012, Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkcolorchooser.h" +#include "gtkcolorchooserprivate.h" +#include "gtkintl.h" +#include "gtktypebuiltins.h" +#include "gtkprivate.h" + +enum +{ + COLOR_ACTIVATED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_INTERFACE (GtkColorChooser, gtk_color_chooser, G_TYPE_OBJECT); + +static void +gtk_color_chooser_default_init (GtkColorChooserInterface *iface) +{ + g_object_interface_install_property (iface, + g_param_spec_boxed ("color", + P_("Color"), + P_("Current color, as a GdkRGBA"), + GDK_TYPE_RGBA, + GTK_PARAM_READWRITE)); + + /** + * GtkColorChooser::color-activated: + * @self: the object which received the signal + * @color: the color + * + * Emitted when a color is activated from the color chooser. + * This usually happens when the user clicks a color swatch, + * or a color is selected and the user presses one of the keys + * Space, Shift+Space, Return or Enter. + */ + signals[COLOR_ACTIVATED] = + g_signal_new ("color-activated", + GTK_TYPE_COLOR_CHOOSER, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkColorChooserInterface, color_activated), + NULL, NULL, + NULL, + G_TYPE_NONE, + 1, G_TYPE_STRING); +} + +/** + * gtk_color_chooser_get_color: + * @chooser: a #GtkColorChooser + * @color: return location for the color + * + * Gets the currently-selected color. + */ +void +gtk_color_chooser_get_color (GtkColorChooser *chooser, + GdkRGBA *color) +{ + g_return_if_fail (GTK_IS_COLOR_CHOOSER (chooser)); + + GTK_COLOR_CHOOSER_GET_IFACE (chooser)->get_color (chooser, color); +} + +/** + * gtk_color_chooser_set_color: + * @chooser: a #GtkColorChooser + * @color: the new color + * + * Sets the currently-selected color. + */ +void +gtk_color_chooser_set_color (GtkColorChooser *chooser, + const GdkRGBA *color) +{ + g_return_if_fail (GTK_IS_COLOR_CHOOSER (chooser)); + g_return_if_fail (color != NULL); + + GTK_COLOR_CHOOSER_GET_IFACE (chooser)->set_color (chooser, color); +} + +void +_gtk_color_chooser_color_activated (GtkColorChooser *chooser, + const GdkRGBA *color) +{ + g_return_if_fail (GTK_IS_COLOR_CHOOSER (chooser)); + + g_signal_emit (chooser, signals[COLOR_ACTIVATED], 0, color); +} diff --git a/gtk/gtkcolorchooser.h b/gtk/gtkcolorchooser.h new file mode 100644 index 0000000000..bd5b70e5a3 --- /dev/null +++ b/gtk/gtkcolorchooser.h @@ -0,0 +1,67 @@ +/* GTK - The GIMP Toolkit + * + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_COLOR_CHOOSER_H__ +#define __GTK_COLOR_CHOOSER_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_COLOR_CHOOSER (gtk_color_chooser_get_type ()) +#define GTK_COLOR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_CHOOSER, GtkColorChooser)) +#define GTK_IS_COLOR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_CHOOSER)) +#define GTK_COLOR_CHOOSER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_COLOR_CHOOSER, GtkColorChooserInterface)) + +typedef struct _GtkColorChooser GtkColorChooser; +typedef struct _GtkColorChooserInterface GtkColorChooserInterface; + +struct _GtkColorChooserInterface +{ + GTypeInterface base_interface; + + /* Methods */ + void (* get_color) (GtkColorChooser *chooser, + GdkRGBA *color); + void (* set_color) (GtkColorChooser *chooser, + const GdkRGBA *color); + + /* Signals */ + void (* color_activated) (GtkColorChooser *chooser, + const GdkRGBA *color); + + /* Padding */ + gpointer padding[12]; +}; + +GType gtk_color_chooser_get_type (void) G_GNUC_CONST; + +void gtk_color_chooser_get_color (GtkColorChooser *chooser, + GdkRGBA *color); +void gtk_color_chooser_set_color (GtkColorChooser *chooser, + const GdkRGBA *color); + +G_END_DECLS + +#endif /* __GTK_COLOR_CHOOSER_H__ */ diff --git a/gtk/gtkcolorchooserdialog.c b/gtk/gtkcolorchooserdialog.c new file mode 100644 index 0000000000..76355409e7 --- /dev/null +++ b/gtk/gtkcolorchooserdialog.c @@ -0,0 +1,217 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkdialog.h" +#include "gtkstock.h" +#include "gtkbox.h" +#include "gtkintl.h" + +#include "gtkcolorchooserprivate.h" +#include "gtkcolorchooserdialog.h" +#include "gtkcolorchooserwidget.h" + + +struct _GtkColorChooserDialogPrivate +{ + GtkWidget *color_chooser; + + GtkWidget *select_button; + GtkWidget *cancel_button; +}; + +enum +{ + PROP_ZERO, + PROP_COLOR +}; + +static void gtk_color_chooser_dialog_iface_init (GtkColorChooserInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GtkColorChooserDialog, gtk_color_chooser_dialog, GTK_TYPE_DIALOG, + G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER, + gtk_color_chooser_dialog_iface_init)) + +static void +propagate_notify (GObject *o, + GParamSpec *pspec, + GtkColorChooserDialog *cc) +{ + g_object_notify (G_OBJECT (cc), "color"); +} + +static void +color_activated_cb (GtkColorChooser *chooser, + GdkRGBA *color, + GtkDialog *dialog) +{ + gtk_dialog_response (dialog, GTK_RESPONSE_OK); +} + +static void +gtk_color_chooser_dialog_init (GtkColorChooserDialog *cc) +{ + GtkColorChooserDialogPrivate *priv; + GtkDialog *dialog = GTK_DIALOG (cc); + GtkWidget *action_area, *content_area; + + cc->priv = G_TYPE_INSTANCE_GET_PRIVATE (cc, + GTK_TYPE_COLOR_CHOOSER_DIALOG, + GtkColorChooserDialogPrivate); + priv = cc->priv; + + content_area = gtk_dialog_get_content_area (dialog); + action_area = gtk_dialog_get_action_area (dialog); + + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */ + gtk_container_set_border_width (GTK_CONTAINER (action_area), 5); + gtk_box_set_spacing (GTK_BOX (action_area), 6); + + gtk_widget_push_composite_child (); + + gtk_window_set_resizable (GTK_WINDOW (cc), FALSE); + + /* Create the content area */ + priv->color_chooser = gtk_color_chooser_widget_new (); + gtk_container_set_border_width (GTK_CONTAINER (priv->color_chooser), 5); + gtk_widget_show (priv->color_chooser); + gtk_box_pack_start (GTK_BOX (content_area), + priv->color_chooser, TRUE, TRUE, 0); + + g_signal_connect (priv->color_chooser, "notify::color", + G_CALLBACK (propagate_notify), cc); + + g_signal_connect (priv->color_chooser, "color-activated", + G_CALLBACK (color_activated_cb), cc); + + /* Create the action area */ + priv->cancel_button = gtk_dialog_add_button (dialog, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + priv->select_button = gtk_dialog_add_button (dialog, + _("_Select"), + GTK_RESPONSE_OK); + gtk_widget_grab_default (priv->select_button); + + gtk_dialog_set_alternative_button_order (dialog, + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gtk_window_set_title (GTK_WINDOW (cc), _("Select a Color")); + + gtk_widget_pop_composite_child (); +} + +static void +gtk_color_chooser_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkColorChooser *cc = GTK_COLOR_CHOOSER (object); + + switch (prop_id) + { + case PROP_COLOR: + { + GdkRGBA color; + + gtk_color_chooser_get_color (cc, &color); + g_value_set_boxed (value, &color); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_color_chooser_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkColorChooser *cc = GTK_COLOR_CHOOSER (object); + + switch (prop_id) + { + case PROP_COLOR: + gtk_color_chooser_set_color (cc, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_color_chooser_dialog_class_init (GtkColorChooserDialogClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->get_property = gtk_color_chooser_dialog_get_property; + object_class->set_property = gtk_color_chooser_dialog_set_property; + + g_object_class_override_property (object_class, PROP_COLOR, "color"); + + g_type_class_add_private (class, sizeof (GtkColorChooserDialogPrivate)); +} + +static void +gtk_color_chooser_dialog_get_color (GtkColorChooser *chooser, + GdkRGBA *color) +{ + GtkColorChooserDialog *cc = GTK_COLOR_CHOOSER_DIALOG (chooser); + + gtk_color_chooser_get_color (GTK_COLOR_CHOOSER (cc->priv->color_chooser), color); +} + +static void +gtk_color_chooser_dialog_set_color (GtkColorChooser *chooser, + const GdkRGBA *color) +{ + GtkColorChooserDialog *cc = GTK_COLOR_CHOOSER_DIALOG (chooser); + + gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (cc->priv->color_chooser), color); +} + +static void +gtk_color_chooser_dialog_iface_init (GtkColorChooserInterface *iface) +{ + iface->get_color = gtk_color_chooser_dialog_get_color; + iface->set_color = gtk_color_chooser_dialog_set_color; +} + +GtkWidget * +gtk_color_chooser_dialog_new (const gchar *title, + GtkWindow *parent) +{ + GtkColorChooserDialog *dialog; + + dialog = g_object_new (GTK_TYPE_COLOR_CHOOSER_DIALOG, + "title", title, + "transient-for", parent, + NULL); + + return GTK_WIDGET (dialog); +} diff --git a/gtk/gtkcolorchooserdialog.h b/gtk/gtkcolorchooserdialog.h new file mode 100644 index 0000000000..c67be0e360 --- /dev/null +++ b/gtk/gtkcolorchooserdialog.h @@ -0,0 +1,68 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_COLOR_CHOOSER_DIALOG_H__ +#define __GTK_COLOR_CHOOSER_DIALOG_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_COLOR_CHOOSER_DIALOG (gtk_color_chooser_dialog_get_type ()) +#define GTK_COLOR_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_CHOOSER_DIALOG, GtkColorChooserDialog)) +#define GTK_COLOR_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_CHOOSER_DIALOG, GtkColorChooserDialogClass)) +#define GTK_IS_COLOR_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_CHOOSER_DIALOG)) +#define GTK_IS_COLOR_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_CHOOSER_DIALOG)) +#define GTK_COLOR_CHOOSER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_COLOR_CHOOSER_DIALOG, GtkColorChooserDialogClass)) + +typedef struct _GtkColorChooserDialog GtkColorChooserDialog; +typedef struct _GtkColorChooserDialogPrivate GtkColorChooserDialogPrivate; +typedef struct _GtkColorChooserDialogClass GtkColorChooserDialogClass; + +struct _GtkColorChooserDialog +{ + GtkDialog parent_instance; + + /*< private >*/ + GtkColorChooserDialogPrivate *priv; +}; + +struct _GtkColorChooserDialogClass +{ + GtkDialogClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + +GType gtk_color_chooser_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget * gtk_color_chooser_dialog_new (const gchar *title, + GtkWindow *parent); + +G_END_DECLS + +#endif /* __GTK_COLOR_CHOOSER_DIALOG_H__ */ diff --git a/gtk/gtkcolorchooserprivate.h b/gtk/gtkcolorchooserprivate.h new file mode 100644 index 0000000000..0a9f4f5e6b --- /dev/null +++ b/gtk/gtkcolorchooserprivate.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GTK_COLOR_CHOOSER_PRIVATE_H__ +#define __GTK_COLOR_CHOOSER_PRIVATE_H__ + +#include "gtkcolorchooser.h" + +G_BEGIN_DECLS + +void _gtk_color_chooser_color_activated (GtkColorChooser *chooser, + const GdkRGBA *color); + +G_END_DECLS + +#endif /* ! __GTK_COLOR_CHOOSER_PRIVATE_H__ */ diff --git a/gtk/gtkcolorchooserwidget.c b/gtk/gtkcolorchooserwidget.c new file mode 100644 index 0000000000..06fd27e20b --- /dev/null +++ b/gtk/gtkcolorchooserwidget.c @@ -0,0 +1,482 @@ +/* GTK - The GIMP Toolkit + * + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkcolorchooserprivate.h" +#include "gtkcolorchooserwidget.h" +#include "gtkcoloreditor.h" +#include "gtkcolorswatch.h" +#include "gtkbox.h" +#include "gtkgrid.h" +#include "gtkhsv.h" +#include "gtklabel.h" +#include "gtkorientable.h" +#include "gtkintl.h" + +struct _GtkColorChooserWidgetPrivate +{ + GtkWidget *palette; + GtkWidget *editor; + + GtkWidget *colors; + GtkWidget *grays; + GtkWidget *custom; + + GtkColorSwatch *current; + + GSettings *settings; +}; + +enum +{ + PROP_ZERO, + PROP_COLOR +}; + +static void gtk_color_chooser_widget_iface_init (GtkColorChooserInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GtkColorChooserWidget, gtk_color_chooser_widget, GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER, + gtk_color_chooser_widget_iface_init)) + +static void +select_swatch (GtkColorChooserWidget *cc, + GtkColorSwatch *swatch) +{ + if (cc->priv->current == swatch) + return; + if (cc->priv->current != NULL) + gtk_color_swatch_set_selected (cc->priv->current, FALSE); + gtk_color_swatch_set_selected (swatch, TRUE); + cc->priv->current = swatch; + g_object_notify (G_OBJECT (cc), "color"); +} + +static void add_custom (GtkColorChooserWidget *cc, GtkColorSwatch *swatch); +static void save_custom (GtkColorChooserWidget *cc); + +static void +button_activate (GtkColorSwatch *swatch, + GtkColorChooserWidget *cc) +{ + add_custom (cc, swatch); +} + +static void +swatch_activate (GtkColorSwatch *swatch, + GtkColorChooserWidget *cc) +{ + GdkRGBA color; + + gtk_color_swatch_get_color (swatch, &color); + _gtk_color_chooser_color_activated (GTK_COLOR_CHOOSER (cc), &color); +} + +static void +swatch_customize (GtkColorSwatch *swatch, + GtkColorChooserWidget *cc) +{ + GdkRGBA color; + + gtk_color_swatch_get_color (swatch, &color); + gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (cc->priv->editor), &color); + + gtk_widget_hide (cc->priv->palette); + gtk_widget_show (cc->priv->editor); + g_print ("TODO: customize color\n"); +} + +static void +swatch_selected (GtkColorSwatch *swatch, + GParamSpec *pspec, + GtkColorChooserWidget *cc) +{ + select_swatch (cc, swatch); +} + +static void +connect_swatch_signals (GtkWidget *p, gpointer data) +{ + g_signal_connect (p, "activate", G_CALLBACK (swatch_activate), data); + g_signal_connect (p, "customize", G_CALLBACK (swatch_customize), data); + g_signal_connect (p, "notify::selected", G_CALLBACK (swatch_selected), data); +} + +static void +connect_button_signals (GtkWidget *p, gpointer data) +{ + g_signal_connect (p, "activate", G_CALLBACK (button_activate), data); +} + +static void +connect_custom_signals (GtkWidget *p, gpointer data) +{ + connect_swatch_signals (p, data); + g_signal_connect_swapped (p, "notify::color", G_CALLBACK (save_custom), data); +} + +static void +save_custom (GtkColorChooserWidget *cc) +{ + GVariantBuilder builder; + GVariant *variant; + GdkRGBA color; + GList *children, *l; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(dddd)")); + + children = gtk_container_get_children (GTK_CONTAINER (cc->priv->custom)); + for (l = children; l; l = l->next) + { + if (gtk_color_swatch_get_color (GTK_COLOR_SWATCH (l->data), &color)) + { + g_variant_builder_add (&builder, "(dddd)", + color.red, color.green, color.blue, color.alpha); + } + } + + g_list_free (children); + + variant = g_variant_builder_end (&builder); + g_settings_set_value (cc->priv->settings, "custom-colors", variant); +} + +static void +add_custom (GtkColorChooserWidget *cc, GtkColorSwatch *swatch) +{ + GList *children; + gint n_children; + GdkRGBA color; + GtkWidget *p; + + children = gtk_container_get_children (GTK_CONTAINER (cc->priv->custom)); + n_children = g_list_length (children); + g_list_free (children); + if (n_children >= 9) + { + gtk_widget_error_bell (GTK_WIDGET (cc)); + return; + } + + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (swatch), 10, 1, 1, 10); + + color.red = g_random_double_range (0, 1); + color.green = g_random_double_range (0, 1); + color.blue = g_random_double_range (0, 1); + color.alpha = 1.0; + + p = gtk_color_swatch_new (); + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (p), &color); + gtk_color_swatch_set_can_drop (GTK_COLOR_SWATCH (p), TRUE); + connect_custom_signals (p, cc); + + if (n_children == 1) + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 10, 10, 1); + else + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 1, 1, 1); + + gtk_grid_insert_next_to (GTK_GRID (cc->priv->custom), GTK_WIDGET (swatch), GTK_POS_RIGHT); + gtk_grid_attach (GTK_GRID (cc->priv->custom), p, 1, 0, 1, 1); + + gtk_widget_show (p); + + save_custom (cc); +} + +static void +gtk_color_chooser_widget_init (GtkColorChooserWidget *cc) +{ + GtkWidget *grid; + GtkWidget *p; + GtkWidget *label; + gint i; + GdkRGBA color, color1, color2; + gdouble h, s, v; + GVariant *variant; + GVariantIter iter; + gboolean selected; + const gchar *default_palette[9] = { + "red", + "orange", + "yellow", + "green", + "blue", + "purple", + "brown", + "darkgray", + "gray" + }; + + cc->priv = G_TYPE_INSTANCE_GET_PRIVATE (cc, GTK_TYPE_COLOR_CHOOSER_WIDGET, GtkColorChooserWidgetPrivate); + + gtk_orientable_set_orientation (GTK_ORIENTABLE (cc), GTK_ORIENTATION_VERTICAL); + cc->priv->palette = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_container_add (GTK_CONTAINER (cc), cc->priv->palette); + + cc->priv->colors = grid = gtk_grid_new (); + g_object_set (grid, "margin", 12, NULL); + gtk_widget_set_margin_bottom (grid, 12); + gtk_grid_set_row_spacing (GTK_GRID (grid), 2); + gtk_grid_set_column_spacing (GTK_GRID (grid), 4); + gtk_container_add (GTK_CONTAINER (cc->priv->palette), grid); + + for (i = 0; i < 9; i++) + { + gdk_rgba_parse (&color, default_palette[i]); + gtk_rgb_to_hsv (color.red, color.green, color.blue, &h, &s, &v); + gtk_hsv_to_rgb (h, s / 2, (v + 1) / 2, &color1.red, &color1.green, &color1.blue); + color1.alpha = color.alpha; + + gtk_hsv_to_rgb (h, s, v * 3 / 4, &color2.red, &color2.green, &color2.blue); + color2.alpha = color.alpha; + + p = gtk_color_swatch_new (); + connect_swatch_signals (p, cc); + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 10, 10, 1, 1); + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (p), &color1); + + gtk_grid_attach (GTK_GRID (grid), p, i, 0, 1, 1); + + p = gtk_color_swatch_new (); + connect_swatch_signals (p, cc); + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 1, 1, 1); + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (p), &color); + gtk_grid_attach (GTK_GRID (grid), p, i, 1, 1, 1); + + p = gtk_color_swatch_new (); + connect_swatch_signals (p, cc); + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 1, 10, 10); + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (p), &color2); + gtk_grid_attach (GTK_GRID (grid), p, i, 2, 1, 1); + } + + cc->priv->grays = grid = gtk_grid_new (); + g_object_set (grid, "margin", 12, "margin-top", 0, NULL); + gtk_grid_set_column_spacing (GTK_GRID (grid), 4); + gtk_container_add (GTK_CONTAINER (cc->priv->palette), grid); + + for (i = 0; i < 9; i++) + { + color.red = color.green = color.blue = i / 8.0; + color.alpha = 1.0; + + p = gtk_color_swatch_new (); + connect_swatch_signals (p, cc); + if (i == 0) + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 10, 1, 1, 10); + else if (i == 8) + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 10, 10, 1); + else + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 1, 1, 1); + + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (p), &color); + gtk_grid_attach (GTK_GRID (grid), p, i, 0, 1, 1); + } + + label = gtk_label_new (_("Custom color")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_container_add (GTK_CONTAINER (cc->priv->palette), label); + g_object_set (grid, "margin", 12, "margin-top", 0, NULL); + + cc->priv->custom = grid = gtk_grid_new (); + g_object_set (grid, "margin", 12, "margin-top", 0, NULL); + gtk_grid_set_column_spacing (GTK_GRID (grid), 4); + gtk_container_add (GTK_CONTAINER (cc->priv->palette), grid); + + p = gtk_color_swatch_new (); + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 10, 10, 10, 10); + connect_button_signals (p, cc); + gtk_color_swatch_set_icon (GTK_COLOR_SWATCH (p), "list-add-symbolic"); + gtk_grid_attach (GTK_GRID (grid), p, 0, 0, 1, 1); + + cc->priv->settings = g_settings_new_with_path ("org.gtk.Settings.ColorChooser", + "/org/gtk/settings/color-chooser/"); + variant = g_settings_get_value (cc->priv->settings, "custom-colors"); + g_variant_iter_init (&iter, variant); + i = 0; + while (g_variant_iter_loop (&iter, "(dddd)", &color.red, &color.green, &color.blue, &color.alpha)) + { + i++; + p = gtk_color_swatch_new (); + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 1, 1, 1); + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (p), &color); + gtk_color_swatch_set_can_drop (GTK_COLOR_SWATCH (p), TRUE); + connect_custom_signals (p, cc); + gtk_grid_attach (GTK_GRID (grid), p, i, 0, 1, 1); + + if (i == 8) + break; + } + if (i > 0) + gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 10, 10, 1); + g_variant_unref (variant); + + cc->priv->editor = gtk_color_editor_new (); + gtk_container_add (GTK_CONTAINER (cc), cc->priv->editor); + + g_settings_get (cc->priv->settings, "selected-color", "(bdddd)", + &selected, + &color.red, &color.green, &color.blue, &color.alpha); + if (selected) + gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (cc), &color); + + gtk_widget_show_all (GTK_WIDGET (cc)); + gtk_widget_hide (GTK_WIDGET (cc->priv->editor)); + gtk_widget_hide (GTK_WIDGET (cc)); + + gtk_widget_set_no_show_all (cc->priv->palette, TRUE); + gtk_widget_set_no_show_all (cc->priv->editor, TRUE); +} + +static void +gtk_color_chooser_widget_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkColorChooser *cc = GTK_COLOR_CHOOSER (object); + + switch (prop_id) + { + case PROP_COLOR: + { + GdkRGBA color; + + gtk_color_chooser_get_color (cc, &color); + g_value_set_boxed (value, &color); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_color_chooser_widget_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (object); + + switch (prop_id) + { + case PROP_COLOR: + gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (cc), + g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_color_chooser_widget_finalize (GObject *object) +{ + GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (object); + + g_object_unref (cc->priv->settings); + + G_OBJECT_CLASS (gtk_color_chooser_widget_parent_class)->finalize (object); +} + +static void +gtk_color_chooser_widget_class_init (GtkColorChooserWidgetClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->get_property = gtk_color_chooser_widget_get_property; + object_class->set_property = gtk_color_chooser_widget_set_property; + object_class->finalize = gtk_color_chooser_widget_finalize; + + g_object_class_override_property (object_class, PROP_COLOR, "color"); + + g_type_class_add_private (object_class, sizeof (GtkColorChooserWidgetPrivate)); +} + +static void +gtk_color_chooser_widget_get_color (GtkColorChooser *chooser, + GdkRGBA *color) +{ + GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (chooser); + + if (gtk_widget_get_visible (cc->priv->editor)) + gtk_color_chooser_get_color (GTK_COLOR_CHOOSER (cc->priv->editor), color); + else if (cc->priv->current) + gtk_color_swatch_get_color (cc->priv->current, color); + else + { + color->red = 1.0; + color->green = 1.0; + color->blue = 1.0; + color->alpha = 1.0; + } +} + +static void +gtk_color_chooser_widget_set_color (GtkColorChooser *chooser, + const GdkRGBA *color) +{ + GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (chooser); + GList *children, *l; + GtkColorSwatch *swatch; + GdkRGBA c; + GtkWidget *grids[3]; + gint i; + + grids[0] = cc->priv->colors; + grids[1] = cc->priv->grays; + grids[2] = cc->priv->custom; + + for (i = 0; i < 3; i++) + { + children = gtk_container_get_children (GTK_CONTAINER (grids[i])); + for (l = children; l; l = l->next) + { + swatch = l->data; + gtk_color_swatch_get_color (swatch, &c); + if (gdk_rgba_equal (color, &c)) + { + select_swatch (cc, swatch); + g_list_free (children); + return; + } + } + g_list_free (children); + } + + /* FIXME: add new custom color */ +} + +static void +gtk_color_chooser_widget_iface_init (GtkColorChooserInterface *iface) +{ + iface->get_color = gtk_color_chooser_widget_get_color; + iface->set_color = gtk_color_chooser_widget_set_color; +} + +GtkWidget * +gtk_color_chooser_widget_new (void) +{ + return g_object_new (GTK_TYPE_COLOR_CHOOSER_WIDGET, NULL); +} diff --git a/gtk/gtkcolorchooserwidget.h b/gtk/gtkcolorchooserwidget.h new file mode 100644 index 0000000000..177a719120 --- /dev/null +++ b/gtk/gtkcolorchooserwidget.h @@ -0,0 +1,71 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_COLOR_CHOOSER_WIDGET_H__ +#define __GTK_COLOR_CHOOSER_WIDGET_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_COLOR_CHOOSER_WIDGET (gtk_color_chooser_widget_get_type ()) +#define GTK_COLOR_CHOOSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_CHOOSER_WIDGET, GtkColorChooserWidget)) +#define GTK_COLOR_CHOOSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_CHOOSER_WIDGET, GtkColorChooserWidgetClass)) +#define GTK_IS_COLOR_CHOOSER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_CHOOSER_WIDGET)) +#define GTK_IS_COLOR_CHOOSER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_CHOOSER_WIDGET)) +#define GTK_COLOR_CHOOSER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_COLOR_CHOOSER_WIDGET, GtkColorChooserWidgetClass)) + +typedef struct _GtkColorChooserWidget GtkColorChooserWidget; +typedef struct _GtkColorChooserWidgetPrivate GtkColorChooserWidgetPrivate; +typedef struct _GtkColorChooserWidgetClass GtkColorChooserWidgetClass; + +struct _GtkColorChooserWidget +{ + GtkBox parent_instance; + + /*< private >*/ + GtkColorChooserWidgetPrivate *priv; +}; + +struct _GtkColorChooserWidgetClass +{ + GtkBoxClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); + void (*_gtk_reserved5) (void); + void (*_gtk_reserved6) (void); + void (*_gtk_reserved7) (void); + void (*_gtk_reserved8) (void); +}; + +GType gtk_color_chooser_widget_get_type (void) G_GNUC_CONST; + +GtkWidget * gtk_color_chooser_widget_new (void); + +G_END_DECLS + +#endif /* __GTK_COLOR_CHOOSER_WIDGET_H__ */ diff --git a/gtk/gtkcoloreditor.c b/gtk/gtkcoloreditor.c new file mode 100644 index 0000000000..f1346986cc --- /dev/null +++ b/gtk/gtkcoloreditor.c @@ -0,0 +1,172 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkintl.h" +#include "gtkcolorchooserprivate.h" +#include "gtkcoloreditor.h" +#include "gtkhsv.h" + + +struct _GtkColorEditorPrivate +{ + GtkWidget *hsv; + GdkRGBA color; +}; + +enum +{ + PROP_ZERO, + PROP_COLOR +}; + +static void gtk_color_editor_iface_init (GtkColorChooserInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GtkColorEditor, gtk_color_editor, GTK_TYPE_BOX, + G_IMPLEMENT_INTERFACE (GTK_TYPE_COLOR_CHOOSER, + gtk_color_editor_iface_init)) + +static void +hsv_changed (GtkHSV *hsv, + GtkColorEditor *editor) +{ + gdouble h, s, v; + + gtk_hsv_get_color (hsv, &h, &s, &v); + gtk_hsv_to_rgb (h, s, v, + &editor->priv->color.red, + &editor->priv->color.green, + &editor->priv->color.blue); + editor->priv->color.alpha = 1; +} + +static void +gtk_color_editor_init (GtkColorEditor *editor) +{ + GtkWidget *hsv; + + editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (editor, + GTK_TYPE_COLOR_EDITOR, + GtkColorEditorPrivate); + gtk_widget_push_composite_child (); + + editor->priv->hsv = hsv = gtk_hsv_new (); + gtk_hsv_set_metrics (GTK_HSV (hsv), 300, 20); + g_signal_connect (hsv, "changed", G_CALLBACK (hsv_changed), editor); + gtk_widget_show (hsv); + gtk_container_add (GTK_CONTAINER (editor), hsv); + gtk_widget_pop_composite_child (); +} + +static void +gtk_color_editor_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkColorChooser *cc = GTK_COLOR_CHOOSER (object); + + switch (prop_id) + { + case PROP_COLOR: + { + GdkRGBA color; + gtk_color_chooser_get_color (cc, &color); + g_value_set_boxed (value, &color); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_color_editor_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkColorChooser *cc = GTK_COLOR_CHOOSER (object); + + switch (prop_id) + { + case PROP_COLOR: + gtk_color_chooser_set_color (cc, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_color_editor_class_init (GtkColorEditorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->get_property = gtk_color_editor_get_property; + object_class->set_property = gtk_color_editor_set_property; + + g_object_class_override_property (object_class, PROP_COLOR, "color"); + + g_type_class_add_private (class, sizeof (GtkColorEditorPrivate)); +} + +static void +gtk_color_editor_get_color (GtkColorChooser *chooser, + GdkRGBA *color) +{ + GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser); + + color->red = editor->priv->color.red; + color->green = editor->priv->color.green; + color->blue = editor->priv->color.blue; + color->alpha = editor->priv->color.alpha; +} + +static void +gtk_color_editor_set_color (GtkColorChooser *chooser, + const GdkRGBA *color) +{ + GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser); + gdouble h, s, v; + + editor->priv->color.red = color->red; + editor->priv->color.green = color->green; + editor->priv->color.blue = color->blue; + editor->priv->color.alpha = color->alpha; + gtk_rgb_to_hsv (color->red, color->green, color->blue, &h, &s, &v); + gtk_hsv_set_color (GTK_HSV (editor->priv->hsv), h, s, v); + g_object_notify (G_OBJECT (editor), "color"); +} + +static void +gtk_color_editor_iface_init (GtkColorChooserInterface *iface) +{ + iface->get_color = gtk_color_editor_get_color; + iface->set_color = gtk_color_editor_set_color; +} + +GtkWidget * +gtk_color_editor_new (void) +{ + return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_EDITOR, NULL); +} diff --git a/gtk/gtkcoloreditor.h b/gtk/gtkcoloreditor.h new file mode 100644 index 0000000000..25dfe73763 --- /dev/null +++ b/gtk/gtkcoloreditor.h @@ -0,0 +1,68 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_COLOR_EDITOR_H__ +#define __GTK_COLOR_EDITOR_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_COLOR_EDITOR (gtk_color_editor_get_type ()) +#define GTK_COLOR_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_EDITOR, GtkColorEditor)) +#define GTK_COLOR_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_EDITOR, GtkColorEditorClass)) +#define GTK_IS_COLOR_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_EDITOR)) +#define GTK_IS_COLOR_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_EDITOR)) +#define GTK_COLOR_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_COLOR_EDITOR, GtkColorEditorClass)) + + +typedef struct _GtkColorEditor GtkColorEditor; +typedef struct _GtkColorEditorClass GtkColorEditorClass; +typedef struct _GtkColorEditorPrivate GtkColorEditorPrivate; + +struct _GtkColorEditor +{ + GtkBox parent_instance; + + GtkColorEditorPrivate *priv; +}; + +struct _GtkColorEditorClass +{ + GtkBoxClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType gtk_color_editor_get_type (void) G_GNUC_CONST; + +GtkWidget * gtk_color_editor_new (void); + +G_END_DECLS + +#endif /* __GTK_COLOR_EDITOR_H__ */ diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c new file mode 100644 index 0000000000..25dbcb0c18 --- /dev/null +++ b/gtk/gtkcolorswatch.c @@ -0,0 +1,572 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkcolorswatch.h" +#include "gtkroundedboxprivate.h" +#include "gtkdnd.h" +#include "gtkicontheme.h" +#include "gtkprivate.h" +#include "gtkintl.h" + + +struct _GtkColorSwatchPrivate +{ + GdkRGBA color; + gdouble radius[4]; + gchar *icon; + guint selected : 1; + guint has_color : 1; + guint can_drop : 1; + guint contains_pointer : 1; +}; + +enum +{ + PROP_ZERO, + PROP_COLOR, + PROP_SELECTED +}; + +enum +{ + ACTIVATE, + CUSTOMIZE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_DRAWING_AREA) + +static void +gtk_color_swatch_init (GtkColorSwatch *swatch) +{ + swatch->priv = G_TYPE_INSTANCE_GET_PRIVATE (swatch, + GTK_TYPE_COLOR_SWATCH, + GtkColorSwatchPrivate); + + gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE); + gtk_widget_set_events (GTK_WIDGET (swatch), GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_EXPOSURE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK); +} + +static void +swatch_finalize (GObject *object) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object); + + g_free (swatch->priv->icon); + + G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object); +} + +#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) + +static gboolean +swatch_draw (GtkWidget *widget, + cairo_t *cr) +{ + GtkColorSwatch *swatch = (GtkColorSwatch*)widget; + GtkRoundedBox box; + gint i; + gdouble width, height; + GtkStyleContext *context; + GtkStateFlags state; + GdkRGBA bg; + + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + + gtk_style_context_save (context); + cairo_save (cr); + + gtk_style_context_set_state (context, state); + + _gtk_rounded_box_init_rect (&box, 0, 0, width, height); + for (i = 0; i < 4; i++) + box.corner[i].horizontal = box.corner[i].vertical = swatch->priv->radius[i]; + + _gtk_rounded_box_path (&box, cr); + + if (swatch->priv->has_color) + { + gdk_cairo_set_source_rgba (cr, &swatch->priv->color); + cairo_fill_preserve (cr); + } + + cairo_set_source_rgb (cr, 0.4, 0.4, 0.4); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + + if (gtk_widget_has_visible_focus (widget)) + { + cairo_set_line_width (cr, 2); + if (swatch->priv->has_color && INTENSITY (swatch->priv->color.red, swatch->priv->color.green, swatch->priv->color.blue) < 0.5) + cairo_set_source_rgba (cr, 1., 1., 1., 0.4); + else + cairo_set_source_rgba (cr, 0., 0., 0., 0.4); + _gtk_rounded_box_shrink (&box, 3, 3, 3, 3); + _gtk_rounded_box_path (&box, cr); + cairo_stroke (cr); + } + + if (swatch->priv->icon) + { + GdkPixbuf *pixbuf; + GtkIconTheme *theme; + theme = gtk_icon_theme_get_default (); + pixbuf = gtk_icon_theme_load_icon (theme, "list-add-symbolic", 16, + GTK_ICON_LOOKUP_GENERIC_FALLBACK + | GTK_ICON_LOOKUP_USE_BUILTIN, + NULL); + + gtk_render_icon (context, cr, pixbuf, + (width - gdk_pixbuf_get_width (pixbuf)) / 2, + (height - gdk_pixbuf_get_height (pixbuf)) / 2); + g_object_unref (pixbuf); + } + else if (swatch->priv->selected) + { + gtk_style_context_get_background_color (context, state, &bg); + cairo_new_sub_path (cr); + cairo_arc (cr, width / 2, height / 2, 10, 0, 2 * G_PI); + cairo_close_path (cr); + gdk_cairo_set_source_rgba (cr, &bg); + cairo_fill_preserve (cr); + if (INTENSITY (swatch->priv->color.red, swatch->priv->color.green, swatch->priv->color.blue) > 0.5) + cairo_set_source_rgba (cr, 0., 0., 0., 0.4); + else + cairo_set_source_rgba (cr, 1., 1., 1., 0.4); + cairo_set_line_width (cr, 2); + cairo_stroke (cr); + gtk_style_context_set_state (context, state | GTK_STATE_FLAG_ACTIVE); + gtk_render_check (context, cr, width / 2 - 5, height / 2 - 5, 10, 10); + } + + cairo_restore (cr); + gtk_style_context_restore (context); + + return FALSE; +} + +static void +drag_set_color_icon (GdkDragContext *context, + const GdkRGBA *color) +{ + cairo_surface_t *surface; + cairo_t *cr; + + surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 48, 32); + cr = cairo_create (surface); + gdk_cairo_set_source_rgba (cr, color); + cairo_paint (cr); + + cairo_surface_set_device_offset (surface, -2, -2); + gtk_drag_set_icon_surface (context, surface); + + cairo_destroy (cr); + cairo_surface_destroy (surface); +} + +static void +swatch_drag_begin (GtkWidget *widget, + GdkDragContext *context) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + GdkRGBA color; + + gtk_color_swatch_get_color (swatch, &color); + drag_set_color_icon (context, &color); +} + +static void +swatch_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + guint16 vals[4]; + GdkRGBA color; + + gtk_color_swatch_get_color (swatch, &color); + + vals[0] = color.red * 0xffff; + vals[1] = color.green * 0xffff; + vals[2] = color.blue * 0xffff; + vals[3] = color.alpha * 0xffff; + + gtk_selection_data_set (selection_data, + gdk_atom_intern_static_string ("application/x-color"), + 16, (guchar *)vals, 8); +} + +static void +swatch_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + gint length; + guint16 *vals; + GdkRGBA color; + + length = gtk_selection_data_get_length (selection_data); + + if (length < 0) + return; + + /* We accept drops with the wrong format, since the KDE color + * chooser incorrectly drops application/x-color with format 8. + */ + if (length != 8) + { + g_warning ("Received invalid color data\n"); + return; + } + + vals = (guint16 *) gtk_selection_data_get_data (selection_data); + + color.red = (gdouble)vals[0] / 0xffff; + color.green = (gdouble)vals[1] / 0xffff; + color.blue = (gdouble)vals[2] / 0xffff; + color.alpha = (gdouble)vals[3] / 0xffff; + + gtk_color_swatch_set_color (GTK_COLOR_SWATCH (widget), &color); +} + +static void +swatch_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object); + GdkRGBA color; + + switch (prop_id) + { + case PROP_COLOR: + gtk_color_swatch_get_color (swatch, &color); + g_value_set_boxed (value, &color); + break; + case PROP_SELECTED: + g_value_set_boolean (value, swatch->priv->selected); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +swatch_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object); + + switch (prop_id) + { + case PROP_COLOR: + gtk_color_swatch_set_color (swatch, g_value_get_boxed (value)); + break; + case PROP_SELECTED: + gtk_color_swatch_set_selected (swatch, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +swatch_get_preferred_width (GtkWidget *widget, + gint *min, + gint *nat) +{ + *min = *nat = 48; +} + +static void +swatch_get_preferred_height (GtkWidget *widget, + gint *min, + gint *nat) +{ + *min = *nat = 32; +} + +static gboolean +swatch_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + + if (event->keyval == GDK_KEY_space || + event->keyval == GDK_KEY_Return || + event->keyval == GDK_KEY_ISO_Enter|| + event->keyval == GDK_KEY_KP_Enter || + event->keyval == GDK_KEY_KP_Space) + { + if (swatch->priv->has_color && !swatch->priv->selected) + gtk_color_swatch_set_selected (swatch, TRUE); + else + g_signal_emit (swatch, signals[ACTIVATE], 0); + return TRUE; + } + + return FALSE; +} + +static gboolean +swatch_enter (GtkWidget *widget, + GdkEventCrossing *event) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + swatch->priv->contains_pointer = TRUE; + return FALSE; +} + +static gboolean +swatch_leave (GtkWidget *widget, + GdkEventCrossing *event) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + swatch->priv->contains_pointer = FALSE; + return FALSE; +} + +static gboolean +swatch_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + + gtk_widget_grab_focus (GTK_WIDGET (swatch)); + + if (gdk_event_triggers_context_menu ((GdkEvent *) event)) + { + g_signal_emit (swatch, signals[CUSTOMIZE], 0); + return TRUE; + } + else if (event->button == GDK_BUTTON_PRIMARY && + swatch->priv->selected) + { + g_signal_emit (swatch, signals[ACTIVATE], 0); + return TRUE; + } + + return FALSE; +} + +static gboolean +swatch_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget); + + gtk_widget_grab_focus (GTK_WIDGET (swatch)); + + if (event->button == GDK_BUTTON_PRIMARY && + swatch->priv->contains_pointer) + { + if (!swatch->priv->has_color) + { + g_signal_emit (swatch, signals[ACTIVATE], 0); + return TRUE; + } + else if (!swatch->priv->selected) + { + gtk_color_swatch_set_selected (swatch, TRUE); + return TRUE; + } + } + + return FALSE; +} + +static void +gtk_color_swatch_class_init (GtkColorSwatchClass *class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass *)class; + GObjectClass *object_class = (GObjectClass *)class; + + object_class->get_property = swatch_get_property; + object_class->set_property = swatch_set_property; + object_class->finalize = swatch_finalize; + + widget_class->get_preferred_width = swatch_get_preferred_width; + widget_class->get_preferred_height = swatch_get_preferred_height; + widget_class->draw = swatch_draw; + widget_class->drag_begin = swatch_drag_begin; + widget_class->drag_data_get = swatch_drag_data_get; + widget_class->drag_data_received = swatch_drag_data_received; + widget_class->key_press_event = swatch_key_press; + widget_class->button_press_event = swatch_button_press; + widget_class->button_release_event = swatch_button_release; + widget_class->enter_notify_event = swatch_enter; + widget_class->leave_notify_event = swatch_leave; + + signals[ACTIVATE] = + g_signal_new ("activate", + GTK_TYPE_COLOR_SWATCH, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkColorSwatchClass, activate), + NULL, NULL, NULL, G_TYPE_NONE, 0); + + signals[CUSTOMIZE] = + g_signal_new ("customize", + GTK_TYPE_COLOR_SWATCH, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkColorSwatchClass, customize), + NULL, NULL, NULL, G_TYPE_NONE, 0); + + g_object_class_install_property (object_class, PROP_COLOR, + g_param_spec_boxed ("color", P_("Color"), P_("Color"), + GDK_TYPE_RGBA, GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SELECTED, + g_param_spec_boolean ("selected", P_("Selected"), P_("Selected"), + FALSE, GTK_PARAM_READWRITE)); + + g_type_class_add_private (object_class, sizeof (GtkColorSwatchPrivate)); +} + + +/* Public API {{{1 */ + +GtkWidget * +gtk_color_swatch_new (void) +{ + return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_SWATCH, NULL); +} + +void +gtk_color_swatch_set_color (GtkColorSwatch *swatch, + const GdkRGBA *color) +{ + static const GtkTargetEntry targets[] = { + { "application/x-color", 0 } + }; + + if (!swatch->priv->has_color) + gtk_drag_source_set (GTK_WIDGET (swatch), + GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, + targets, 1, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + + swatch->priv->has_color = TRUE; + swatch->priv->color.red = color->red; + swatch->priv->color.green = color->green; + swatch->priv->color.blue = color->blue; + swatch->priv->color.alpha = color->alpha; + + gtk_widget_queue_draw (GTK_WIDGET (swatch)); + g_object_notify (G_OBJECT (swatch), "color"); +} + +gboolean +gtk_color_swatch_get_color (GtkColorSwatch *swatch, + GdkRGBA *color) +{ + if (swatch->priv->has_color) + { + color->red = swatch->priv->color.red; + color->green = swatch->priv->color.green; + color->blue = swatch->priv->color.blue; + color->alpha = swatch->priv->color.alpha; + return TRUE; + } + else + { + color->red = 1.0; + color->green = 1.0; + color->blue = 1.0; + color->alpha = 1.0; + return FALSE; + } +} + +void +gtk_color_swatch_set_corner_radii (GtkColorSwatch *swatch, + gdouble top_left, + gdouble top_right, + gdouble bottom_right, + gdouble bottom_left) +{ + swatch->priv->radius[0] = top_left; + swatch->priv->radius[1] = top_right; + swatch->priv->radius[2] = bottom_right; + swatch->priv->radius[3] = bottom_left; + + gtk_widget_queue_draw (GTK_WIDGET (swatch)); +} + +void +gtk_color_swatch_set_selected (GtkColorSwatch *swatch, + gboolean selected) +{ + if (swatch->priv->selected != selected) + { + swatch->priv->selected = selected; + gtk_widget_queue_draw (GTK_WIDGET (swatch)); + g_object_notify (G_OBJECT (swatch), "selected"); + } +} + +void +gtk_color_swatch_set_icon (GtkColorSwatch *swatch, + const gchar *icon) +{ + swatch->priv->icon = g_strdup (icon); + gtk_widget_queue_draw (GTK_WIDGET (swatch)); +} + +void +gtk_color_swatch_set_can_drop (GtkColorSwatch *swatch, + gboolean can_drop) +{ + static const GtkTargetEntry targets[] = { + { "application/x-color", 0 } + }; + + if (!swatch->priv->can_drop) + gtk_drag_dest_set (GTK_WIDGET (swatch), + GTK_DEST_DEFAULT_HIGHLIGHT | + GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_DROP, + targets, 1, + GDK_ACTION_COPY); + + swatch->priv->can_drop = can_drop; +} + +/* vim:set foldmethod=marker: */ diff --git a/gtk/gtkcolorswatch.h b/gtk/gtkcolorswatch.h new file mode 100644 index 0000000000..5c98e04482 --- /dev/null +++ b/gtk/gtkcolorswatch.h @@ -0,0 +1,88 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2012 Red Hat, Inc. + * + * 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; either + * version 2 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GTK_COLOR_SWATCH_H__ +#define __GTK_COLOR_SWATCH_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_COLOR_SWATCH (gtk_color_swatch_get_type ()) +#define GTK_COLOR_SWATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_SWATCH, GtkColorSwatch)) +#define GTK_COLOR_SWATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_SWATCH, GtkColorSwatchClass)) +#define GTK_IS_COLOR_SWATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_SWATCH)) +#define GTK_IS_COLOR_SWATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_SWATCH)) +#define GTK_COLOR_SWATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_COLOR_SWATCH, GtkColorSwatchClass)) + + +typedef struct _GtkColorSwatch GtkColorSwatch; +typedef struct _GtkColorSwatchClass GtkColorSwatchClass; +typedef struct _GtkColorSwatchPrivate GtkColorSwatchPrivate; + +struct _GtkColorSwatch +{ + GtkDrawingArea parent; + + /*< private >*/ + GtkColorSwatchPrivate *priv; +}; + +struct _GtkColorSwatchClass +{ + GtkDrawingAreaClass parent_class; + + void ( * activate) (GtkColorSwatch *swatch); + void ( * customize) (GtkColorSwatch *swatch); + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType gtk_color_swatch_get_type (void) G_GNUC_CONST; + +GtkWidget * gtk_color_swatch_new (void); +void gtk_color_swatch_set_corner_radii (GtkColorSwatch *swatch, + gdouble top_left, + gdouble top_right, + gdouble bottom_right, + gdouble bottom_left); +void gtk_color_swatch_set_color (GtkColorSwatch *swatch, + const GdkRGBA *color); +gboolean gtk_color_swatch_get_color (GtkColorSwatch *swatch, + GdkRGBA *color); +void gtk_color_swatch_set_selected (GtkColorSwatch *swatch, + gboolean selected); +void gtk_color_swatch_set_can_drop (GtkColorSwatch *swatch, + gboolean can_drop); +void gtk_color_swatch_set_icon (GtkColorSwatch *swatch, + const gchar *icon); + + +G_END_DECLS + +#endif /* __GTK_COLOR_SWATCH_H__ */ diff --git a/gtk/org.gtk.Settings.ColorChooser.gschema.xml b/gtk/org.gtk.Settings.ColorChooser.gschema.xml new file mode 100644 index 0000000000..f707e469f0 --- /dev/null +++ b/gtk/org.gtk.Settings.ColorChooser.gschema.xml @@ -0,0 +1,13 @@ + + + + + + [] + + + (false,1.0,1.0,1.0,1.0) + + + +