aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-color-chooser-widget.c
diff options
context:
space:
mode:
authorTomas Popela <tpopela@redhat.com>2014-06-09 22:32:25 +0800
committerTomas Popela <tpopela@redhat.com>2014-06-09 22:32:25 +0800
commit8650fb139a9143f04615de74ff569bce3e0c4ce3 (patch)
tree89a41d08f179a5359b8eaee0c9344b8a5bf07cb3 /e-util/e-color-chooser-widget.c
parent04b7c97275ae420dca43f3e65c2ef54d02f01bdd (diff)
downloadgsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.tar
gsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.tar.gz
gsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.tar.bz2
gsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.tar.lz
gsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.tar.xz
gsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.tar.zst
gsoc2013-evolution-8650fb139a9143f04615de74ff569bce3e0c4ce3.zip
Bug 540362: [webkit-composer] Use webkit for composer
Merge wip/webkit-composer branch into master.
Diffstat (limited to 'e-util/e-color-chooser-widget.c')
-rw-r--r--e-util/e-color-chooser-widget.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/e-util/e-color-chooser-widget.c b/e-util/e-color-chooser-widget.c
new file mode 100644
index 0000000000..5761ebf2ff
--- /dev/null
+++ b/e-util/e-color-chooser-widget.c
@@ -0,0 +1,253 @@
+
+/* e-color-chooser-widget.c
+ *
+ * Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-color-chooser-widget.h"
+
+#include <glib/gi18n-lib.h>
+
+#define E_COLOR_CHOOSER_WIDGET_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_COLOR_CHOOSER_WIDGET, EColorChooserWidgetPrivate))
+
+/**
+ * EColorChooserWidget:
+ *
+ * This widget wrapps around #GtkColorChooserWidget and allows the widget to be
+ * used as a delegate for #GtkComboBox for instance.
+ */
+
+struct _EColorChooserWidgetPrivate {
+ gboolean showing_editor;
+};
+
+enum {
+ SIGNAL_EDITOR_ACTIVATED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (
+ EColorChooserWidget,
+ e_color_chooser_widget,
+ GTK_TYPE_COLOR_CHOOSER_WIDGET);
+
+/* UGLY UGLY UGLY!
+ * GtkColorChooserWidget sends "color-activated" signal
+ * only when user double-clicks the color. This is totally stupid
+ * and since we want to use it in a combobox-like widget, we need
+ * to be notified upon single click (which by default only selects the color).
+ *
+ * Unfortunatelly the GtkColorSwatch widget, which handles the button-press
+ * event is a non-public widget embedded within the GtkColorChooserWidget,
+ * so we can't just subclass it and fix the behavior.
+ *
+ * Here we override button_press_event of the GtkColorSwatch and manually
+ * emit the 'activate' signal on single click. This is stupid, ugly and I
+ * want to punch someone for such a stupid design...
+ */
+static gboolean
+color_chooser_widget_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ if ((event->type == GDK_BUTTON_PRESS) &&
+ (event->button == GDK_BUTTON_PRIMARY)) {
+
+ g_signal_emit_by_name (widget, "activate");
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+color_chooser_widget_color_activated (GtkColorChooser *chooser,
+ GdkRGBA *color,
+ gpointer user_data)
+{
+ /* Because we are simulating the double-click by accepting only
+ * single click, the color in the swatch is actually not selected,
+ * so we must do it manually */
+ gtk_color_chooser_set_rgba (chooser, color);
+}
+
+static gboolean
+run_color_chooser_dialog (gpointer user_data)
+{
+ EColorChooserWidgetPrivate *priv;
+ GtkWidget *parent_window;
+ GtkWidget *parent_chooser;
+ GtkWidget *dialog;
+ GtkWidget *chooser;
+
+ parent_chooser = user_data;
+
+ g_object_set (
+ G_OBJECT (parent_chooser), "show-editor", FALSE, NULL);
+
+ parent_window = g_object_get_data (G_OBJECT (parent_chooser), "window");
+ if (!parent_window)
+ parent_window = gtk_widget_get_toplevel (parent_chooser);
+ dialog = gtk_dialog_new_with_buttons (
+ N_("Choose custom color"),
+ GTK_WINDOW (parent_window),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);
+
+ chooser = gtk_color_chooser_widget_new ();
+ g_object_set (G_OBJECT (chooser), "show-editor", TRUE, NULL);
+ gtk_box_pack_start (
+ GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ chooser, TRUE, TRUE, 5);
+
+ gtk_widget_show_all (chooser);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+ GdkRGBA color;
+
+ gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (chooser), &color);
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (parent_chooser), &color);
+
+ g_signal_emit_by_name (parent_chooser, "color-activated", &color);
+ }
+
+ gtk_widget_destroy (dialog);
+
+ priv = E_COLOR_CHOOSER_WIDGET_GET_PRIVATE (parent_chooser);
+ priv->showing_editor = FALSE;
+
+ return FALSE;
+}
+
+static void
+color_chooser_show_editor_notify_cb (EColorChooserWidget *chooser,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ gboolean show_editor;
+
+ g_object_get (G_OBJECT (chooser), "show-editor", &show_editor, NULL);
+
+ /* Nothing to do here... */
+ if ((show_editor == FALSE) || (chooser->priv->showing_editor == TRUE))
+ return;
+
+ chooser->priv->showing_editor = TRUE;
+
+ /* Hide the editor - we don't want to display the single-color editor
+ * within this widget. We rather create a dialog window with the editor
+ * (we can't do it from this callback as Gtk would stop it in order to
+ * prevent endless recursion probably) */
+ g_idle_add (run_color_chooser_dialog, chooser);
+ g_signal_emit (chooser, signals[SIGNAL_EDITOR_ACTIVATED], 0);
+}
+
+void
+e_color_chooser_widget_class_init (EColorChooserWidgetClass *class)
+{
+ g_type_class_add_private (class, sizeof (EColorChooserWidgetPrivate));
+
+ signals[SIGNAL_EDITOR_ACTIVATED] = g_signal_new (
+ "editor-activated",
+ E_TYPE_COLOR_CHOOSER_WIDGET,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EColorChooserWidgetClass, editor_activated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+/* Recursively go through GtkContainers within the GtkColorChooserWidget
+ * and try to find GtkColorSwatch widget. */
+static GtkWidget *
+find_swatch (GtkContainer *container)
+{
+ GList *children, *child;
+
+ children = gtk_container_get_children (container);
+ for (child = children; child; child = g_list_next (child)) {
+ GtkWidget *widget = child->data;
+ GtkWidget *swatch;
+
+ if (GTK_IS_CONTAINER (widget)) {
+ swatch = find_swatch (GTK_CONTAINER (widget));
+
+ if (swatch != NULL) {
+ g_list_free (children);
+ return swatch;
+ }
+ }
+
+ if (g_strcmp0 (G_OBJECT_TYPE_NAME (widget), "GtkColorSwatch") == 0) {
+ g_list_free (children);
+ return widget;
+ }
+ }
+
+ g_list_free (children);
+
+ return NULL;
+}
+
+void
+e_color_chooser_widget_init (EColorChooserWidget *widget)
+{
+ GtkWidget *swatch;
+
+ widget->priv = E_COLOR_CHOOSER_WIDGET_GET_PRIVATE (widget);
+ widget->priv->showing_editor = FALSE;
+
+ swatch = find_swatch (GTK_CONTAINER (widget));
+
+ /* If swatch is NULL then GTK changed something and this widget
+ * becomes broken... */
+ g_return_if_fail (swatch != NULL);
+
+ if (swatch) {
+ GtkWidgetClass *swatch_class;
+ swatch_class = GTK_WIDGET_GET_CLASS (swatch);
+ swatch_class->button_press_event = color_chooser_widget_button_press_event;
+ }
+
+ g_signal_connect (
+ widget, "color-activated",
+ G_CALLBACK (color_chooser_widget_color_activated), NULL);
+
+ g_signal_connect (
+ widget, "notify::show-editor",
+ G_CALLBACK (color_chooser_show_editor_notify_cb), NULL);
+}
+
+GtkWidget *
+e_color_chooser_widget_new (void)
+{
+ return g_object_new (
+ E_TYPE_COLOR_CHOOSER_WIDGET,
+ "show-editor", FALSE,
+ "use-alpha", FALSE,
+ NULL);
+}