[gtk+/wip/colorchooser-v2: 26/77] Finishing touches



commit 79f729427896a72db3acbcfa04c47a991b17e038
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Feb 3 01:41:45 2012 -0500

    Finishing touches
    
    Implement popups in the editor, fix window sizing, fix RTL flipping.
    GtkColorPlane is now using adjustments, and GtkColorEditor is using
    adjustments as its model as well.

 gtk/gtkcolorchooserwidget.c |   33 +++-
 gtk/gtkcoloreditor.c        |  421 +++++++++++++++++++++++++++++++++++--------
 gtk/gtkcolorplane.c         |  170 +++++++++---------
 gtk/gtkcolorplane.h         |   16 +--
 gtk/gtkcolorscale.c         |   11 +-
 5 files changed, 471 insertions(+), 180 deletions(-)
---
diff --git a/gtk/gtkcolorchooserwidget.c b/gtk/gtkcolorchooserwidget.c
index 7888d10..71e60e1 100644
--- a/gtk/gtkcolorchooserwidget.c
+++ b/gtk/gtkcolorchooserwidget.c
@@ -31,6 +31,8 @@
 #include "gtkorientable.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtksizegroup.h"
+#include "gtkalignment.h"
 
 struct _GtkColorChooserWidgetPrivate
 {
@@ -45,6 +47,8 @@ struct _GtkColorChooserWidgetPrivate
   GtkColorSwatch *current;
   gboolean show_alpha;
 
+  GtkSizeGroup *size_group;
+
   GSettings *settings;
 };
 
@@ -184,9 +188,11 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
 {
   GtkWidget *grid;
   GtkWidget *p;
+  GtkWidget *alignment;
   GtkWidget *button;
   GtkWidget *label;
   gint i, j;
+  gint left;
   GdkRGBA color;
   GVariant *variant;
   GVariantIter iter;
@@ -252,6 +258,8 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
   gtk_grid_set_column_spacing (GTK_GRID (grid), 4);
   gtk_container_add (GTK_CONTAINER (cc->priv->palette), grid);
 
+  left = (gtk_widget_get_direction (GTK_WIDGET (cc)) == GTK_TEXT_DIR_LTR) ? 0 : 8;
+
   for (i = 0; i < 9; i++)
     {
        gdk_rgba_parse (&color, default_grayscale[i]);
@@ -259,9 +267,9 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
 
        p = gtk_color_swatch_new ();
        connect_swatch_signals (p, cc);
-       if (i == 0)
+       if (i == left)
          gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 10, 1, 1, 10);
-       else if (i == 8)
+       else if (i == (8 - left))
          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);
@@ -307,12 +315,22 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
 
   if (i > 0)
     {
-      gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 10, 10, 1);
-      gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (button), 10, 1, 1, 10);
+      if (gtk_widget_get_direction (GTK_WIDGET (cc)) == GTK_TEXT_DIR_LTR)
+        {
+          gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 1, 10, 10, 1);
+          gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (button), 10, 1, 1, 10);
+        }
+      else
+        {
+          gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (button), 1, 10, 10, 1);
+          gtk_color_swatch_set_corner_radii (GTK_COLOR_SWATCH (p), 10, 1, 1, 10);
+        }
     }
 
   cc->priv->editor = gtk_color_editor_new ();
-  gtk_container_add (GTK_CONTAINER (cc), cc->priv->editor);
+  alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
+  gtk_container_add (GTK_CONTAINER (cc), alignment);
+  gtk_container_add (GTK_CONTAINER (alignment), cc->priv->editor);
 
   g_settings_get (cc->priv->settings, "selected-color", "(bdddd)",
                   &selected,
@@ -326,6 +344,10 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
 
   gtk_widget_set_no_show_all (cc->priv->palette, TRUE);
   gtk_widget_set_no_show_all (cc->priv->editor, TRUE);
+
+  cc->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+  gtk_size_group_add_widget (cc->priv->size_group, cc->priv->palette);
+  gtk_size_group_add_widget (cc->priv->size_group, alignment);
 }
 
 static void
@@ -430,6 +452,7 @@ gtk_color_chooser_widget_finalize (GObject *object)
 {
   GtkColorChooserWidget *cc = GTK_COLOR_CHOOSER_WIDGET (object);
 
+  g_object_unref (cc->priv->size_group);
   g_object_unref (cc->priv->settings);
 
   G_OBJECT_CLASS (gtk_color_chooser_widget_parent_class)->finalize (object);
diff --git a/gtk/gtkcoloreditor.c b/gtk/gtkcoloreditor.c
index dcf1a40..b8a8a6e 100644
--- a/gtk/gtkcoloreditor.c
+++ b/gtk/gtkcoloreditor.c
@@ -17,10 +17,6 @@
  * Boston, MA 02111-1307, USA.
  */
 
-/* TODO
- * - pop-up entries
- */
-
 #include "config.h"
 
 #include "gtkcolorchooserprivate.h"
@@ -33,26 +29,40 @@
 #include "gtkaspectframe.h"
 #include "gtkdrawingarea.h"
 #include "gtkentry.h"
+#include "gtkoverlay.h"
 #include "gtkhsv.h"
 #include "gtkadjustment.h"
+#include "gtklabel.h"
+#include "gtkspinbutton.h"
+#include "gtkalignment.h"
 #include "gtkintl.h"
 
 #include <math.h>
 
 struct _GtkColorEditorPrivate
 {
+  GtkWidget *overlay;
   GtkWidget *grid;
   GtkWidget *swatch;
   GtkWidget *entry;
   GtkWidget *h_slider;
-  GtkWidget *sv_plane;
+  GtkWidget *h_popup;
+  GtkWidget *h_entry;
   GtkWidget *a_slider;
+  GtkWidget *a_popup;
+  GtkWidget *a_entry;
+  GtkWidget *sv_plane;
+  GtkWidget *sv_popup;
+  GtkWidget *s_entry;
+  GtkWidget *v_entry;
+  GtkWidget *current_popup;
+  GtkWidget *popdown_focus;
 
   GtkAdjustment *h_adj;
+  GtkAdjustment *s_adj;
+  GtkAdjustment *v_adj;
   GtkAdjustment *a_adj;
 
-  GdkRGBA color;
-  gdouble h, s, v;
   guint text_changed : 1;
   guint show_alpha   : 1;
 };
@@ -83,11 +93,18 @@ static void
 update_entry (GtkColorEditor *editor)
 {
   gchar *text;
+  gdouble h, s, v;
+  gdouble r, g, b;
+
+  h = gtk_adjustment_get_value (editor->priv->h_adj);
+  s = gtk_adjustment_get_value (editor->priv->s_adj);
+  v = gtk_adjustment_get_value (editor->priv->v_adj);
+  gtk_hsv_to_rgb (h, s, v, &r, &g, &b);
 
   text = g_strdup_printf ("#%02X%02X%02X",
-                          scale_round (editor->priv->color.red, 255),
-                          scale_round (editor->priv->color.green, 255),
-                          scale_round (editor->priv->color.blue, 255));
+                          scale_round (r, 255),
+                          scale_round (g, 255),
+                          scale_round (b, 255));
   gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), text);
   editor->priv->text_changed = FALSE;
   g_free (text);
@@ -106,7 +123,7 @@ entry_apply (GtkWidget      *entry,
   text = gtk_editable_get_chars (GTK_EDITABLE (editor->priv->entry), 0, -1);
   if (gdk_rgba_parse (&color, text))
     {
-      color.alpha = editor->priv->color.alpha;
+      color.alpha = gtk_adjustment_get_value (editor->priv->a_adj);
       gtk_color_chooser_set_color (GTK_COLOR_CHOOSER (editor), &color);
     }
 
@@ -133,59 +150,225 @@ entry_text_changed (GtkWidget      *entry,
 }
 
 static void
-h_changed (GtkAdjustment  *adj,
-           GtkColorEditor *editor)
+hsv_changed (GtkColorEditor *editor)
 {
-  editor->priv->h = gtk_adjustment_get_value (adj);
-  gtk_hsv_to_rgb (editor->priv->h, editor->priv->s, editor->priv->v,
-                  &editor->priv->color.red,
-                  &editor->priv->color.green,
-                  &editor->priv->color.blue);
-  gtk_color_plane_set_h (GTK_COLOR_PLANE (editor->priv->sv_plane), editor->priv->h);
+  GdkRGBA color;
+  gdouble h, s, v;
+
+  h = gtk_adjustment_get_value (editor->priv->h_adj);
+  s = gtk_adjustment_get_value (editor->priv->s_adj);
+  v = gtk_adjustment_get_value (editor->priv->v_adj);
+  gtk_hsv_to_rgb (h, s, v, &color.red, &color.green, &color.blue);
+  color.alpha = gtk_adjustment_get_value (editor->priv->a_adj);
   update_entry (editor);
-  gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), &editor->priv->color);
-  gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), &editor->priv->color);
+  gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), &color);
+  gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), &color);
   g_object_notify (G_OBJECT (editor), "color");
 }
 
 static void
-sv_changed (GtkColorPlane  *plane,
+dismiss_current_popup (GtkColorEditor *editor)
+{
+  if (editor->priv->current_popup)
+    {
+      gtk_widget_hide (editor->priv->current_popup);
+      editor->priv->current_popup = NULL;
+      if (editor->priv->popdown_focus)
+        {
+          gtk_widget_grab_focus (editor->priv->popdown_focus);
+          editor->priv->popdown_focus = NULL;
+        }
+    }
+}
+
+static void
+popup_edit (GtkWidget      *widget,
             GtkColorEditor *editor)
 {
-  editor->priv->s = gtk_color_plane_get_s (plane);
-  editor->priv->v = gtk_color_plane_get_v (plane);
-  gtk_hsv_to_rgb (editor->priv->h, editor->priv->s, editor->priv->v,
-                  &editor->priv->color.red,
-                  &editor->priv->color.green,
-                  &editor->priv->color.blue);
-  update_entry (editor);
-  gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), &editor->priv->color);
-  gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), &editor->priv->color);
-  g_object_notify (G_OBJECT (editor), "color");
+  GtkWidget *popup = NULL;
+  GtkWidget *toplevel;
+  GtkWidget *focus;
+
+  if (widget == editor->priv->sv_plane)
+    {
+      popup = editor->priv->sv_popup;
+      focus = editor->priv->s_entry;
+    }
+  else if (widget == editor->priv->h_slider)
+    {
+      popup = editor->priv->h_popup;
+      focus = editor->priv->h_entry;
+    }
+  else if (widget == editor->priv->a_slider)
+    {
+      popup = editor->priv->a_popup;
+      focus = editor->priv->a_entry;
+    }
+
+  if (popup)
+    {
+      dismiss_current_popup (editor);
+      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor));
+      editor->priv->popdown_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+      editor->priv->current_popup = popup;
+      gtk_widget_show (popup);
+      gtk_widget_grab_focus (focus);
+    }
+}
+
+static gboolean
+popup_key_press (GtkWidget      *popup,
+                 GdkEventKey    *event,
+                 GtkColorEditor *editor)
+{
+  if (event->keyval == GDK_KEY_Escape)
+    {
+      dismiss_current_popup (editor);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+get_child_position (GtkOverlay     *overlay,
+                    GtkWidget      *widget,
+                    GtkAllocation  *allocation,
+                    GtkColorEditor *editor)
+{
+  GtkRequisition req;
+  GtkAllocation alloc;
+  gint s, e;
+
+  gtk_widget_get_preferred_size (widget, &req, NULL);
+
+  allocation->width = req.width;
+  allocation->height = req.height;
+
+  if (widget == editor->priv->sv_popup)
+    {
+      if (gtk_widget_get_direction (overlay) == GTK_TEXT_DIR_RTL)
+        allocation->x = 0;
+      else
+        allocation->x = gtk_widget_get_allocated_width (GTK_WIDGET (overlay)) - req.width;
+      allocation->y = req.height / 3;
+    }
+  else if (widget == editor->priv->h_popup)
+    {
+      gtk_widget_get_allocation (editor->priv->h_slider, &alloc);
+      gtk_range_get_slider_range (GTK_RANGE (editor->priv->h_slider), &s, &e);
+
+      if (gtk_widget_get_direction (overlay) == GTK_TEXT_DIR_RTL)
+        gtk_widget_translate_coordinates (editor->priv->h_slider,
+                                          gtk_widget_get_parent (editor->priv->grid),
+                                          - req.width, (s + e - req.height) / 2,
+                                          &allocation->x, &allocation->y);
+      else
+        gtk_widget_translate_coordinates (editor->priv->h_slider,
+                                          gtk_widget_get_parent (editor->priv->grid),
+                                          alloc.width, (s + e - req.height) / 2,
+                                          &allocation->x, &allocation->y);
+    }
+  else if (widget == editor->priv->a_popup)
+    {
+      gtk_widget_get_allocation (editor->priv->a_slider, &alloc);
+      gtk_range_get_slider_range (GTK_RANGE (editor->priv->a_slider), &s, &e);
+
+      gtk_widget_translate_coordinates (editor->priv->a_slider,
+                                        gtk_widget_get_parent (editor->priv->grid),
+                                        (s + e - req.width) / 2, - req.height,
+                                        &allocation->x, &allocation->y);
+    }
+  else
+    return FALSE;
+
+  allocation->x = CLAMP (allocation->x, 0, gtk_widget_get_allocated_width (GTK_WIDGET (overlay)) - req.width);
+  allocation->y = CLAMP (allocation->y, 0, gtk_widget_get_allocated_height (GTK_WIDGET (overlay)) - req.height);
+
+  return TRUE;
 }
 
 static void
-a_changed (GtkAdjustment  *adj,
-           GtkColorEditor *editor)
+value_changed (GtkAdjustment *a, GtkAdjustment *as)
 {
-  editor->priv->color.alpha = gtk_adjustment_get_value (adj);
-  gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), &editor->priv->color);
-  g_object_notify (G_OBJECT (editor), "color");
+  gdouble scale;
+
+  scale = gtk_adjustment_get_upper (as) / gtk_adjustment_get_upper (a);
+  g_signal_handlers_block_by_func (as, value_changed, a);
+  gtk_adjustment_set_value (as, gtk_adjustment_get_value (a) * scale);
+  g_signal_handlers_unblock_by_func (as, value_changed, a);
+}
+
+static GtkAdjustment *
+scaled_adjustment (GtkAdjustment *a, gdouble scale)
+{
+  GtkAdjustment *as;
+
+  as = gtk_adjustment_new (gtk_adjustment_get_value (a) * scale,
+                           gtk_adjustment_get_lower (a) * scale,
+                           gtk_adjustment_get_upper (a) * scale,
+                           gtk_adjustment_get_step_increment (a) * scale,
+                           gtk_adjustment_get_page_increment (a) * scale,
+                           gtk_adjustment_get_page_size (a) * scale);
+
+  g_signal_connect (a, "value-changed", G_CALLBACK (value_changed), as);
+  g_signal_connect (as, "value-changed", G_CALLBACK (value_changed), a);
+
+  return as;
+}
+
+static gboolean
+popup_draw (GtkWidget *popup, cairo_t *cr, GtkColorEditor *editor)
+{
+  GtkStyleContext *context;
+  gint width, height;
+
+  context = gtk_widget_get_style_context (popup);
+  width = gtk_widget_get_allocated_width (popup);
+  height = gtk_widget_get_allocated_height (popup);
+
+  gtk_render_background (context, cr, 0, 0, width, height);
+  gtk_render_frame (context, cr, 0, 0, width, height);
+
+  return FALSE;
 }
 
 static void
 gtk_color_editor_init (GtkColorEditor *editor)
 {
   GtkWidget *grid;
+  GtkWidget *box;
   GtkWidget *slider;
+  GtkWidget *alignment;
+  GtkAdjustment *adj;
+  GdkRGBA transparent = { 0, 0, 0, 0 };
 
   editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (editor,
                                               GTK_TYPE_COLOR_EDITOR,
                                               GtkColorEditorPrivate);
   editor->priv->show_alpha = TRUE;
 
+  editor->priv->h_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
+  editor->priv->s_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
+  editor->priv->v_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
+  editor->priv->a_adj = gtk_adjustment_new (0, 0, 1, 0.01, 0.1, 0);
+  g_object_ref_sink (editor->priv->h_adj);
+  g_object_ref_sink (editor->priv->s_adj);
+  g_object_ref_sink (editor->priv->v_adj);
+  g_object_ref_sink (editor->priv->a_adj);
+  g_signal_connect_swapped (editor->priv->h_adj, "value-changed",
+                            G_CALLBACK (hsv_changed), editor);
+  g_signal_connect_swapped (editor->priv->s_adj, "value-changed",
+                            G_CALLBACK (hsv_changed), editor);
+  g_signal_connect_swapped (editor->priv->a_adj, "value-changed",
+                            G_CALLBACK (hsv_changed), editor);
+  g_signal_connect_swapped (editor->priv->v_adj, "value-changed",
+                            G_CALLBACK (hsv_changed), editor);
+
   gtk_widget_push_composite_child ();
 
+  editor->priv->overlay = gtk_overlay_new ();
+  gtk_widget_override_background_color (editor->priv->overlay, 0, &transparent);
   editor->priv->grid = grid = gtk_grid_new ();
   gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
   gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
@@ -202,35 +385,125 @@ gtk_color_editor_init (GtkColorEditor *editor)
   g_signal_connect (editor->priv->entry, "focus-out-event",
                     G_CALLBACK (entry_focus_out), editor);
 
-  editor->priv->h_slider = slider = gtk_color_scale_new ();
-  gtk_orientable_set_orientation (GTK_ORIENTABLE (slider), GTK_ORIENTATION_VERTICAL);
+  editor->priv->h_slider = slider = g_object_new (GTK_TYPE_COLOR_SCALE,
+                                                  "adjustment", editor->priv->h_adj,
+                                                  "draw-value", FALSE,
+                                                  "orientation", GTK_ORIENTATION_VERTICAL,
+                                                  NULL);
   gtk_color_scale_set_type (GTK_COLOR_SCALE (slider), GTK_COLOR_SCALE_HUE);
-  gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_BELOW);
-  editor->priv->h_adj = gtk_range_get_adjustment (GTK_RANGE (slider));
-  g_signal_connect (editor->priv->h_adj, "value-changed", G_CALLBACK (h_changed), editor);
-
-  editor->priv->sv_plane = gtk_color_plane_new ();
-  gtk_widget_set_size_request (editor->priv->sv_plane, 300, 300);
-  gtk_widget_set_hexpand (editor->priv->sv_plane, TRUE);
-  gtk_widget_set_vexpand (editor->priv->sv_plane, TRUE);
-
-  g_signal_connect (editor->priv->sv_plane, "changed", G_CALLBACK (sv_changed), editor);
-
-  editor->priv->a_slider = slider = gtk_color_scale_new ();
-  gtk_orientable_set_orientation (GTK_ORIENTABLE (slider), GTK_ORIENTATION_HORIZONTAL);
+  if (gtk_widget_get_direction (slider) == GTK_TEXT_DIR_RTL)
+    gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE);
+  else
+    gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_BELOW);
+
+  editor->priv->a_slider = slider = g_object_new (GTK_TYPE_COLOR_SCALE,
+                                                  "adjustment", editor->priv->a_adj,
+                                                  "draw-value", FALSE,
+                                                  "orientation", GTK_ORIENTATION_HORIZONTAL,
+                                                  NULL);
   gtk_color_scale_set_type (GTK_COLOR_SCALE (slider), GTK_COLOR_SCALE_ALPHA);
   gtk_style_context_add_class (gtk_widget_get_style_context (slider), GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE);
-  editor->priv->a_adj = gtk_range_get_adjustment (GTK_RANGE (slider));
-  g_signal_connect (editor->priv->a_adj, "value-changed", G_CALLBACK (a_changed), editor);
+
+  editor->priv->sv_plane = gtk_color_plane_new (editor->priv->h_adj,
+                                                editor->priv->s_adj,
+                                                editor->priv->v_adj);
+  gtk_widget_set_size_request (editor->priv->sv_plane, 300, 300);
 
   gtk_grid_attach (GTK_GRID (grid), editor->priv->swatch,   1, 0, 1, 1);
   gtk_grid_attach (GTK_GRID (grid), editor->priv->entry,    2, 0, 1, 1);
   gtk_grid_attach (GTK_GRID (grid), editor->priv->h_slider, 0, 1, 1, 1);
   gtk_grid_attach (GTK_GRID (grid), editor->priv->sv_plane, 1, 1, 2, 1);
   gtk_grid_attach (GTK_GRID (grid), editor->priv->a_slider, 1, 2, 2, 1);
-  gtk_widget_show_all (grid);
-
-  gtk_container_add (GTK_CONTAINER (editor), grid);
+  alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 30, 30);
+  gtk_container_add (GTK_CONTAINER (editor->priv->overlay), alignment);
+  gtk_container_add (GTK_CONTAINER (alignment), grid);
+
+  editor->priv->sv_popup = gtk_alignment_new (0.5, 0.5, 0, 0);
+  gtk_style_context_add_class (gtk_widget_get_style_context (editor->priv->sv_popup),
+                               GTK_STYLE_CLASS_TOOLTIP);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (editor->priv->sv_popup), 12, 12, 12, 12);
+  grid = gtk_grid_new ();
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+  adj = scaled_adjustment (editor->priv->s_adj, 100);
+  editor->priv->s_entry = gtk_spin_button_new (adj, 1, 0);
+  g_signal_connect (editor->priv->s_entry, "key-press-event",
+                    G_CALLBACK (popup_key_press), editor);
+
+  adj = scaled_adjustment (editor->priv->v_adj, 100);
+  editor->priv->v_entry = gtk_spin_button_new (adj, 1, 0);
+  g_signal_connect (editor->priv->v_entry, "key-press-event",
+                    G_CALLBACK (popup_key_press), editor);
+
+  gtk_container_add (GTK_CONTAINER (editor->priv->sv_popup), grid);
+  gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("S"), 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), editor->priv->s_entry, 1, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("V"), 0, 1, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), editor->priv->v_entry, 1, 1, 1, 1);
+  gtk_widget_show_all (editor->priv->sv_popup);
+  gtk_widget_hide (editor->priv->sv_popup);
+  gtk_widget_set_no_show_all (editor->priv->sv_popup, TRUE);
+
+  gtk_overlay_add_overlay (GTK_OVERLAY (editor->priv->overlay), editor->priv->sv_popup);
+
+  g_signal_connect (editor->priv->sv_popup, "draw",
+                    G_CALLBACK (popup_draw), editor);
+  g_signal_connect (editor->priv->sv_plane, "popup-menu",
+                    G_CALLBACK (popup_edit), editor);
+
+  editor->priv->h_popup = gtk_alignment_new (0.5, 0.5, 0, 0);
+  gtk_style_context_add_class (gtk_widget_get_style_context (editor->priv->h_popup),
+                               GTK_STYLE_CLASS_TOOLTIP);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (editor->priv->h_popup), 12, 12, 12, 12);
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  adj = scaled_adjustment (editor->priv->h_adj, 100);
+  editor->priv->h_entry = gtk_spin_button_new (adj, 1, 0);
+  g_signal_connect (editor->priv->h_entry, "key-press-event",
+                    G_CALLBACK (popup_key_press), editor);
+  gtk_container_add (GTK_CONTAINER (editor->priv->h_popup), box);
+  gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("H"));
+  gtk_container_add (GTK_CONTAINER (box), editor->priv->h_entry);
+  gtk_widget_show_all (editor->priv->h_popup);
+  gtk_widget_hide (editor->priv->h_popup);
+  gtk_widget_set_no_show_all (editor->priv->h_popup, TRUE);
+
+  gtk_overlay_add_overlay (GTK_OVERLAY (editor->priv->overlay), editor->priv->h_popup);
+
+  g_signal_connect (editor->priv->h_popup, "draw",
+                    G_CALLBACK (popup_draw), editor);
+  g_signal_connect (editor->priv->h_slider, "popup-menu",
+                    G_CALLBACK (popup_edit), editor);
+
+  editor->priv->a_popup = gtk_alignment_new (0.5, 0.5, 0, 0);
+  gtk_style_context_add_class (gtk_widget_get_style_context (editor->priv->a_popup),
+                               GTK_STYLE_CLASS_TOOLTIP);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (editor->priv->a_popup), 12, 12, 12, 12);
+  grid = gtk_grid_new ();
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+  adj = scaled_adjustment (editor->priv->a_adj, 100);
+  editor->priv->a_entry = gtk_spin_button_new (adj, 1, 0);
+  g_signal_connect (editor->priv->a_entry, "key-press-event",
+                    G_CALLBACK (popup_key_press), editor);
+  gtk_container_add (GTK_CONTAINER (editor->priv->a_popup), grid);
+  gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("A"), 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid), editor->priv->a_entry, 1, 0, 1, 1);
+  gtk_widget_show_all (editor->priv->a_popup);
+  gtk_widget_hide (editor->priv->a_popup);
+  gtk_widget_set_no_show_all (editor->priv->a_popup, TRUE);
+
+  gtk_overlay_add_overlay (GTK_OVERLAY (editor->priv->overlay), editor->priv->a_popup);
+
+  g_signal_connect (editor->priv->a_popup, "draw",
+                    G_CALLBACK (popup_draw), editor);
+  g_signal_connect (editor->priv->a_slider, "popup-menu",
+                    G_CALLBACK (popup_edit), editor);
+
+  g_signal_connect (editor->priv->overlay, "get-child-position",
+                    G_CALLBACK (get_child_position), editor);
+
+  gtk_widget_show_all (editor->priv->overlay);
+
+  gtk_container_add (GTK_CONTAINER (editor), editor->priv->overlay);
   gtk_widget_pop_composite_child ();
 }
 
@@ -301,6 +574,13 @@ gtk_color_editor_set_property (GObject      *object,
 static void
 gtk_color_editor_finalize (GObject *object)
 {
+  GtkColorEditor *editor = GTK_COLOR_EDITOR (object);
+
+  g_clear_object (&editor->priv->h_adj);
+  g_clear_object (&editor->priv->s_adj);
+  g_clear_object (&editor->priv->v_adj);
+  g_clear_object (&editor->priv->a_adj);
+
   G_OBJECT_CLASS (gtk_color_editor_parent_class)->finalize (object);
 }
 
@@ -324,11 +604,13 @@ gtk_color_editor_get_color (GtkColorChooser *chooser,
                             GdkRGBA         *color)
 {
   GtkColorEditor *editor = GTK_COLOR_EDITOR (chooser);
+  gdouble h, s, v;
 
-  color->red = editor->priv->color.red;
-  color->green = editor->priv->color.green;
-  color->blue = editor->priv->color.blue;
-  color->alpha = editor->priv->color.alpha;
+  h = gtk_adjustment_get_value (editor->priv->h_adj);
+  s = gtk_adjustment_get_value (editor->priv->s_adj);
+  v = gtk_adjustment_get_value (editor->priv->v_adj);
+  gtk_hsv_to_rgb (h, s, v, &color->red, &color->green, &color->blue);
+  color->alpha = gtk_adjustment_get_value (editor->priv->a_adj);
 }
 
 static void
@@ -338,22 +620,15 @@ gtk_color_editor_set_color (GtkColorChooser *chooser,
   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);
-  editor->priv->h = h;
-  editor->priv->s = s;
-  editor->priv->v = v;
-  gtk_color_plane_set_h (GTK_COLOR_PLANE (editor->priv->sv_plane), h);
-  gtk_color_plane_set_s (GTK_COLOR_PLANE (editor->priv->sv_plane), s);
-  gtk_color_plane_set_v (GTK_COLOR_PLANE (editor->priv->sv_plane), v);
-  gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), color);
 
   gtk_adjustment_set_value (editor->priv->h_adj, h);
+  gtk_adjustment_set_value (editor->priv->s_adj, s);
+  gtk_adjustment_set_value (editor->priv->v_adj, v);
   gtk_adjustment_set_value (editor->priv->a_adj, color->alpha);
-  gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), &editor->priv->color);
+  gtk_color_swatch_set_color (GTK_COLOR_SWATCH (editor->priv->swatch), color);
+  gtk_color_scale_set_color (GTK_COLOR_SCALE (editor->priv->a_slider), color);
+
   update_entry (editor);
 
   gtk_widget_queue_draw (GTK_WIDGET (editor));
diff --git a/gtk/gtkcolorplane.c b/gtk/gtkcolorplane.c
index ea1fec5..95f092a 100644
--- a/gtk/gtkcolorplane.c
+++ b/gtk/gtkcolorplane.c
@@ -21,23 +21,21 @@
 
 #include "gtkhsv.h"
 #include "gtkcolorplane.h"
+#include "gtkcontainer.h"
+#include "gtkwindow.h"
+#include "gtkbutton.h"
 
 struct _GtkColorPlanePrivate
 {
+  GtkAdjustment *h_adj;
+  GtkAdjustment *s_adj;
+  GtkAdjustment *v_adj;
+
   cairo_surface_t *surface;
-  gdouble h, s, v;
   gint x, y;
   gboolean in_drag;
 };
 
-enum
-{
-  CHANGED,
-  LAST_SIGNAL
-};
-
-guint signals[LAST_SIGNAL];
-
 G_DEFINE_TYPE (GtkColorPlane, gtk_color_plane, GTK_TYPE_DRAWING_AREA)
 
 static gboolean
@@ -118,7 +116,7 @@ create_sv_surface (GtkColorPlane *plane)
 
   data = g_malloc (height * stride);
 
-  h = plane->priv->h;
+  h = gtk_adjustment_get_value (plane->priv->h_adj);
   sf = 1.0 / (height - 1);
   vf = 1.0 / (width - 1);
   for (y = 0; y < height; y++)
@@ -151,13 +149,16 @@ create_sv_surface (GtkColorPlane *plane)
 static void
 hsv_to_xy (GtkColorPlane *plane)
 {
+  gdouble s, v;
   gint width, height;
 
   width = gtk_widget_get_allocated_width (GTK_WIDGET (plane));
   height = gtk_widget_get_allocated_height (GTK_WIDGET (plane));
 
-  plane->priv->x = CLAMP (width * plane->priv->v, 0, width - 1);
-  plane->priv->y = CLAMP (height * (1 - plane->priv->s), 0, height - 1);
+  s = gtk_adjustment_get_value (plane->priv->s_adj);
+  v = gtk_adjustment_get_value (plane->priv->v_adj);
+  plane->priv->x = CLAMP (width * v, 0, width - 1);
+  plane->priv->y = CLAMP (height * (1 - s), 0, height - 1);
 }
 
 static gboolean
@@ -168,6 +169,7 @@ sv_configure (GtkWidget         *widget,
 
   create_sv_surface (plane);
   hsv_to_xy (plane);
+
   return TRUE;
 }
 
@@ -209,13 +211,15 @@ sv_update_color (GtkColorPlane *plane,
                  gint           y)
 {
   GtkWidget *widget = GTK_WIDGET (plane);
+  gdouble s, v;
 
   plane->priv->x = x;
   plane->priv->y = y;
 
-  plane->priv->s = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1);
-  plane->priv->v = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1);
-  g_signal_emit (plane, signals[CHANGED], 0);
+  s = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1);
+  v = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1);
+  gtk_adjustment_set_value (plane->priv->s_adj, s);
+  gtk_adjustment_set_value (plane->priv->v_adj, v);
   gtk_widget_queue_draw (widget);
 }
 
@@ -225,6 +229,15 @@ sv_button_press (GtkWidget      *widget,
 {
   GtkColorPlane *plane = GTK_COLOR_PLANE (widget);
 
+  if (event->button == GDK_BUTTON_SECONDARY)
+    {
+      gboolean handled;
+
+      g_signal_emit_by_name (widget, "popup-menu", &handled);
+
+      return TRUE;
+    }
+
   if (plane->priv->in_drag || event->button != GDK_BUTTON_PRIMARY)
     return FALSE;
 
@@ -269,52 +282,69 @@ sv_motion (GtkWidget      *widget,
 }
 
 static void
+h_changed (GtkColorPlane *plane)
+{
+  create_sv_surface (plane);
+  gtk_widget_queue_draw (GTK_WIDGET (plane));
+}
+
+static void
+sv_changed (GtkColorPlane *plane)
+{
+  hsv_to_xy (plane);
+  gtk_widget_queue_draw (GTK_WIDGET (plane));
+}
+
+static void
 sv_move (GtkColorPlane *plane,
          gdouble        ds,
          gdouble        dv)
 {
-  if (plane->priv->s + ds > 1)
+  gdouble s, v;
+
+  s = gtk_adjustment_get_value (plane->priv->s_adj);
+  v = gtk_adjustment_get_value (plane->priv->v_adj);
+
+  if (s + ds > 1)
     {
-      if (plane->priv->s < 1)
-        plane->priv->s = 1;
+      if (s < 1)
+        s = 1;
       else
         goto error;
     }
-  else if (plane->priv->s + ds < 0)
+  else if (s + ds < 0)
     {
-      if (plane->priv->s > 0)
-        plane->priv->s = 0;
+      if (s > 0)
+        s = 0;
       else
         goto error;
     }
   else
     {
-      plane->priv->s += ds;
+      s += ds;
     }
 
-  if (plane->priv->v + dv > 1)
+  if (v + dv > 1)
     {
-      if (plane->priv->v < 1)
-        plane->priv->v = 1;
+      if (v < 1)
+        v = 1;
       else
         goto error;
     }
-  else if (plane->priv->v + dv < 0)
+  else if (v + dv < 0)
     {
-      if (plane->priv->v > 0)
-        plane->priv->v = 0;
+      if (v > 0)
+        v = 0;
       else
         goto error;
     }
   else
     {
-      plane->priv->v += dv;
+      v += dv;
     }
 
-  hsv_to_xy (plane);
-  g_signal_emit (plane, signals[CHANGED], 0);
-
-  gtk_widget_queue_draw (GTK_WIDGET (plane));
+  gtk_adjustment_set_value (plane->priv->s_adj, s);
+  gtk_adjustment_set_value (plane->priv->v_adj, v);
   return;
 
 error:
@@ -347,7 +377,7 @@ sv_key_press (GtkWidget      *widget,
            event->keyval == GDK_KEY_KP_Right)
     sv_move (plane, 0, step);
   else
-    return FALSE;
+    return GTK_WIDGET_CLASS (gtk_color_plane_parent_class)->key_press_event (widget, event);
 
   return TRUE;
 }
@@ -371,6 +401,9 @@ sv_finalize (GObject *object)
   GtkColorPlane *plane = GTK_COLOR_PLANE (object);
 
   cairo_surface_destroy (plane->priv->surface);
+  g_clear_object (&plane->priv->h_adj);
+  g_clear_object (&plane->priv->s_adj);
+  g_clear_object (&plane->priv->v_adj);
 
   G_OBJECT_CLASS (gtk_color_plane_parent_class)->finalize (object);
 }
@@ -391,65 +424,28 @@ gtk_color_plane_class_init (GtkColorPlaneClass *class)
   widget_class->grab_broken_event = sv_grab_broken;
   widget_class->key_press_event = sv_key_press;
 
-  signals[CHANGED] =
-    g_signal_new ("changed",
-                  GTK_TYPE_COLOR_PLANE,
-                  G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (GtkColorPlaneClass, changed),
-                  NULL, NULL,
-                  NULL,
-                  G_TYPE_NONE, 0);
-
   g_type_class_add_private (class, sizeof (GtkColorPlanePrivate));
 }
 
-gdouble
-gtk_color_plane_get_h (GtkColorPlane *plane)
-{
-  return plane->priv->h;
-}
-
-gdouble
-gtk_color_plane_get_s (GtkColorPlane *plane)
-{
-  return plane->priv->s;
-}
-
-gdouble
-gtk_color_plane_get_v (GtkColorPlane *plane)
+GtkWidget *
+gtk_color_plane_new (GtkAdjustment *h_adj,
+                     GtkAdjustment *s_adj,
+                     GtkAdjustment *v_adj)
 {
-  return plane->priv->v;
-}
+  GtkColorPlane *plane;
 
-void
-gtk_color_plane_set_h (GtkColorPlane *plane,
-                       gdouble        h)
-{
-  plane->priv->h = h;
-  create_sv_surface (plane);
-  gtk_widget_queue_draw (GTK_WIDGET (plane));
-}
+  plane = (GtkColorPlane *) g_object_new (GTK_TYPE_COLOR_PLANE, NULL);
 
-void
-gtk_color_plane_set_s (GtkColorPlane *plane,
-                       gdouble        s)
-{
-  plane->priv->s = s;
-  hsv_to_xy (plane);
-  gtk_widget_queue_draw (GTK_WIDGET (plane));
-}
 
-void
-gtk_color_plane_set_v (GtkColorPlane *plane,
-                       gdouble        v)
-{
-  plane->priv->v = v;
-  hsv_to_xy (plane);
-  gtk_widget_queue_draw (GTK_WIDGET (plane));
-}
+  plane->priv->h_adj = g_object_ref_sink (h_adj);
+  plane->priv->s_adj = g_object_ref_sink (s_adj);
+  plane->priv->v_adj = g_object_ref_sink (v_adj);
+  g_signal_connect_swapped (plane->priv->h_adj, "value-changed",
+                            G_CALLBACK (h_changed), plane);
+  g_signal_connect_swapped (plane->priv->s_adj, "value-changed",
+                            G_CALLBACK (sv_changed), plane);
+  g_signal_connect_swapped (plane->priv->v_adj, "value-changed",
+                            G_CALLBACK (sv_changed), plane);
 
-GtkWidget *
-gtk_color_plane_new (void)
-{
-  return (GtkWidget *) g_object_new (GTK_TYPE_COLOR_PLANE, NULL);
+  return (GtkWidget *)plane;
 }
diff --git a/gtk/gtkcolorplane.h b/gtk/gtkcolorplane.h
index 33dbe04..0c48a81 100644
--- a/gtk/gtkcolorplane.h
+++ b/gtk/gtkcolorplane.h
@@ -51,8 +51,6 @@ struct _GtkColorPlaneClass
 {
   GtkDrawingAreaClass parent_class;
 
-  void (* changed) (GtkColorPlane *plane);
-
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
   void (*_gtk_reserved2) (void);
@@ -63,17 +61,9 @@ struct _GtkColorPlaneClass
 
 GType       gtk_color_plane_get_type (void) G_GNUC_CONST;
 
-GtkWidget * gtk_color_plane_new      (void);
-
-gdouble     gtk_color_plane_get_h    (GtkColorPlane *plane);
-void        gtk_color_plane_set_h    (GtkColorPlane *plane,
-                                      gdouble        h);
-gdouble     gtk_color_plane_get_s    (GtkColorPlane *plane);
-void        gtk_color_plane_set_s    (GtkColorPlane *plane,
-                                      gdouble        s);
-gdouble     gtk_color_plane_get_v    (GtkColorPlane *plane);
-void        gtk_color_plane_set_v    (GtkColorPlane *plane,
-                                      gdouble        v);
+GtkWidget * gtk_color_plane_new      (GtkAdjustment *h_adj,
+                                      GtkAdjustment *s_adj,
+                                      GtkAdjustment *v_adj);
 
 G_END_DECLS
 
diff --git a/gtk/gtkcolorscale.c b/gtk/gtkcolorscale.c
index f520cf2..60ef228 100644
--- a/gtk/gtkcolorscale.c
+++ b/gtk/gtkcolorscale.c
@@ -232,9 +232,16 @@ scale_draw (GtkWidget *widget,
   if (scale_has_asymmetric_thumb (widget))
     {
       if (gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)) == GTK_ORIENTATION_VERTICAL)
-        cairo_rectangle (cr, width / 2, 1, width / 2 - 1, height - 2);
+        {
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+            cairo_rectangle (cr, 1, 1, width / 2 - 1, height - 2);
+          else
+            cairo_rectangle (cr, width / 2, 1, width / 2 - 1, height - 2);
+        }
       else
-        cairo_rectangle (cr, 1, 1, width - 2, height / 2);
+        {
+          cairo_rectangle (cr, 1, 1, width - 2, height / 2);
+        }
     }
   else
     cairo_rectangle (cr, 1, 1, width - 2, height - 2);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]