[gtk+/wip/matthiasc/gadget: 3/16] colorswatch: Convert to gadgets



commit 6253214f59a910581d5f4cf32674e6eab253cc98
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Dec 2 13:47:02 2015 -0500

    colorswatch: Convert to gadgets
    
    Use gadgets for the widget and the overlay. The Adwaita
    adjustments in this patch are very provisional and need
    more work.

 gtk/gtkcolorswatch.c                     |  294 ++++++++++++++++++++----------
 gtk/theme/Adwaita/_common.scss           |   16 +-
 gtk/theme/Adwaita/gtk-contained-dark.css |   25 ++-
 gtk/theme/Adwaita/gtk-contained.css      |   25 ++-
 4 files changed, 229 insertions(+), 131 deletions(-)
---
diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c
index edcc60f..f33f9a9 100644
--- a/gtk/gtkcolorswatch.c
+++ b/gtk/gtkcolorswatch.c
@@ -30,6 +30,7 @@
 #include "gtkintl.h"
 #include "gtkrenderprivate.h"
 #include "gtkcssnodeprivate.h"
+#include "gtkcsscustomgadgetprivate.h"
 #include "gtkwidgetprivate.h"
 #include "gtkstylecontextprivate.h"
 #include "a11y/gtkcolorswatchaccessibleprivate.h"
@@ -59,7 +60,8 @@ struct _GtkColorSwatchPrivate
 
   GtkGesture *long_press_gesture;
   GtkGesture *multipress_gesture;
-  GtkCssNode *overlay_node;
+  GtkCssGadget *gadget;
+  GtkCssGadget *overlay_gadget;
 
   GtkWidget *popover;
 };
@@ -81,85 +83,44 @@ enum
 
 static guint signals[LAST_SIGNAL];
 
-static void hold_action (GtkGestureLongPress  *gesture,
-                         gdouble               x,
-                         gdouble               y,
-                         GtkColorSwatch       *swatch);
-static void tap_action  (GtkGestureMultiPress *gesture,
-                         gint                  n_press,
-                         gdouble               x,
-                         gdouble               y,
-                         GtkColorSwatch       *swatch);
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_WIDGET)
 
-static void
-gtk_color_swatch_init (GtkColorSwatch *swatch)
+static gboolean
+swatch_draw (GtkWidget *widget,
+             cairo_t   *cr)
 {
-  GtkCssNode *widget_node;
-  GtkStyleContext *context;
-
-  swatch->priv = gtk_color_swatch_get_instance_private (swatch);
-  swatch->priv->use_alpha = TRUE;
-  swatch->priv->selectable = TRUE;
-  swatch->priv->has_menu = TRUE;
-
-  gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
-  gtk_widget_set_has_window (GTK_WIDGET (swatch), FALSE);
+  gtk_css_gadget_draw (GTK_COLOR_SWATCH (widget)->priv->gadget, cr);
 
-  swatch->priv->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (swatch));
-  gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (swatch->priv->long_press_gesture),
-                                     TRUE);
-  g_signal_connect (swatch->priv->long_press_gesture, "pressed",
-                    G_CALLBACK (hold_action), swatch);
-
-  swatch->priv->multipress_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (swatch));
-  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (swatch->priv->multipress_gesture), 0);
-  g_signal_connect (swatch->priv->multipress_gesture, "pressed",
-                    G_CALLBACK (tap_action), swatch);
-
-  widget_node = gtk_widget_get_css_node (GTK_WIDGET (swatch));
-  swatch->priv->overlay_node = gtk_css_node_new ();
-  gtk_css_node_set_name (swatch->priv->overlay_node, I_("overlay"));
-  gtk_css_node_set_parent (swatch->priv->overlay_node, widget_node);
-  gtk_css_node_set_state (swatch->priv->overlay_node, gtk_css_node_get_state (widget_node));
-  g_object_unref (swatch->priv->overlay_node);
-
-  context = gtk_widget_get_style_context (GTK_WIDGET (swatch));
-  gtk_style_context_add_class (context, "activatable");
+  return FALSE;
 }
 
 #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
 #define PIXBUF_SIZE 16
 
 static gboolean
-swatch_draw (GtkWidget *widget,
-             cairo_t   *cr)
-{
-  GtkColorSwatch *swatch = (GtkColorSwatch*)widget;
-  gdouble width, height;
+gtk_color_swatch_render_contents (GtkCssGadget *gadget,
+                                  cairo_t      *cr,
+                                  int           x,
+                                  int           y,
+                                  int           width,
+                                  int           height,
+                                  gpointer      data)
+{
+  GtkWidget *widget;
+  GtkColorSwatch *swatch;
   GtkStyleContext *context;
-  GtkStateFlags state;
-  GtkIconTheme *theme;
-  GtkBorder border, padding;
-  GdkRectangle rect;
-  GtkIconInfo *icon_info = NULL;
-  gint scale;
 
-  theme = gtk_icon_theme_get_default ();
+  widget = gtk_css_gadget_get_owner (gadget);
+  swatch = GTK_COLOR_SWATCH (widget);
   context = gtk_widget_get_style_context (widget);
-  state = gtk_style_context_get_state (context);
-  width = gtk_widget_get_allocated_width (widget);
-  height = gtk_widget_get_allocated_height (widget);
-
-  gtk_render_background (context, cr, 0, 0, width, height);
 
   if (swatch->priv->has_color)
     {
       cairo_pattern_t *pattern;
       cairo_matrix_t matrix;
 
-      gtk_render_content_path (context, cr, 0, 0, width, height);
+      gtk_render_content_path (context, cr, x, y, width, height);
 
       if (swatch->priv->use_alpha)
         {
@@ -193,7 +154,36 @@ swatch_draw (GtkWidget *widget,
       cairo_fill (cr);
     }
 
-  gtk_render_frame (context, cr, 0, 0, width, height);
+  gtk_render_frame (context, cr, x, y, width, height);
+
+  gtk_css_gadget_draw (swatch->priv->overlay_gadget, cr);
+
+  return gtk_widget_has_visible_focus (widget);
+}
+
+static gboolean
+gtk_color_swatch_render_overlay (GtkCssGadget *gadget,
+                                 cairo_t      *cr,
+                                 int           x,
+                                 int           y,
+                                 int           width,
+                                 int           height,
+                                 gpointer      data)
+{
+  GtkWidget *widget;
+  GtkColorSwatch *swatch;
+  GtkStyleContext *context;
+  GtkStateFlags state;
+  GtkIconTheme *theme;
+  GtkIconInfo *icon_info = NULL;
+  gint scale;
+
+  widget = gtk_css_gadget_get_owner (gadget);
+  swatch = GTK_COLOR_SWATCH (widget);
+
+  theme = gtk_icon_theme_get_default ();
+  context = gtk_widget_get_style_context (widget);
+  state = gtk_style_context_get_state (context);
 
   scale = gtk_widget_get_scale_factor (widget);
   if (swatch->priv->icon)
@@ -218,18 +208,6 @@ swatch_draw (GtkWidget *widget,
     }
 
   /* now draw the overlay image */
-  gtk_style_context_get_border (context, state, &border);
-  gtk_style_context_get_padding (context, state, &padding);
-  rect.width = width - (border.left + border.right + padding.left + padding.right);
-  rect.height = height - (border.top + border.bottom + padding.top + padding.bottom);
-  rect.x = border.left + padding.left;
-  rect.y = border.top + padding.top;
-
-  gtk_style_context_save_to_node (context, swatch->priv->overlay_node);
-
-  gtk_render_background (context, cr, rect.x, rect.y, rect.width, rect.height);
-  gtk_render_frame (context, cr, rect.x, rect.y, rect.width, rect.height);
-
   if (icon_info != NULL)
     {
       GdkPixbuf *pixbuf;
@@ -240,9 +218,7 @@ swatch_draw (GtkWidget *widget,
           cairo_surface_t *surface;
 
           surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, gtk_widget_get_window (widget));
-          gtk_render_icon_surface (context, cr, surface,
-                                   rect.x + (rect.width - (gdk_pixbuf_get_width (pixbuf) / scale)) / 2,
-                                   rect.y + (rect.height - (gdk_pixbuf_get_height (pixbuf) / scale)) / 2);
+          gtk_render_icon_surface (context, cr, surface, x, y);
           cairo_surface_destroy (surface);
           g_object_unref (pixbuf);
         }
@@ -250,11 +226,6 @@ swatch_draw (GtkWidget *widget,
       g_object_unref (icon_info);
     }
 
-  if (gtk_widget_has_visible_focus (widget))
-    gtk_render_focus (context, cr, 0, 0, width, height);
-
-  gtk_style_context_restore (context);
-
   return FALSE;
 }
 
@@ -349,33 +320,49 @@ swatch_drag_data_received (GtkWidget        *widget,
 }
 
 static void
-swatch_get_preferred_width (GtkWidget *widget,
-                            gint      *min,
-                            gint      *nat)
-{
-  gint w, h;
+gtk_color_swatch_get_content_size (GtkCssGadget   *gadget,
+                                   GtkOrientation  orientation,
+                                   gint            for_size,
+                                   gint           *minimum,
+                                   gint           *natural,
+                                   gint           *minimum_baseline,
+                                   gint           *natural_baseline,
+                                   gpointer        unused)
+{
+  GtkWidget *widget;
+  GtkColorSwatch *swatch;
+  gint w, h, min;
+
+  widget = gtk_css_gadget_get_owner (gadget);
+  swatch = GTK_COLOR_SWATCH (widget);
+
+  gtk_css_gadget_get_preferred_size (swatch->priv->overlay_gadget,
+                                     orientation,
+                                     -1,
+                                     minimum, natural,
+                                     NULL, NULL);
 
   gtk_widget_get_size_request (widget, &w, &h);
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    min = w < 0 ? 48 : w;
+  else
+    min = h < 0 ? 32 : h;
 
-  if (w < 0)
-    w = 48;
-
-  *min = *nat = w;
+  *minimum = MAX (*minimum, min);
+  *natural = MAX (*natural, min);
 }
 
 static void
-swatch_get_preferred_height (GtkWidget *widget,
-                             gint      *min,
-                             gint      *nat)
+gtk_color_swatch_get_overlay_size (GtkCssGadget   *gadget,
+                                   GtkOrientation  orientation,
+                                   gint            for_size,
+                                   gint           *minimum,
+                                   gint           *natural,
+                                   gint           *minimum_baseline,
+                                   gint           *natural_baseline,
+                                   gpointer        unused)
 {
-  gint w, h;
-
-  gtk_widget_get_size_request (widget, &w, &h);
-
-  if (h < 0)
-    h = 32;
-
-  *min = *nat = h;
+  *minimum = *natural = 16;
 }
 
 static gboolean
@@ -589,6 +576,7 @@ swatch_size_allocate (GtkWidget     *widget,
                       GtkAllocation *allocation)
 {
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
+  GtkAllocation clip;
 
   gtk_widget_set_allocation (widget, allocation);
 
@@ -599,7 +587,60 @@ swatch_size_allocate (GtkWidget     *widget,
                             allocation->width,
                             allocation->height);
 
-  _gtk_widget_set_simple_clip (widget, NULL);
+  gtk_css_gadget_allocate (swatch->priv->gadget,
+                           allocation,
+                           gtk_widget_get_allocated_baseline (widget),
+                           &clip);
+
+  gtk_widget_set_clip (widget, &clip);
+}
+
+static void
+gtk_color_swatch_allocate_contents (GtkCssGadget        *gadget,
+                                    const GtkAllocation *allocation,
+                                    int                  baseline,
+                                    GtkAllocation       *out_clip,
+                                    gpointer             unused)
+{
+  GtkColorSwatch *swatch;
+  GtkAllocation overlay_alloc;
+  gint overlay_width, overlay_height;
+
+  swatch = GTK_COLOR_SWATCH (gtk_css_gadget_get_owner (gadget));
+
+  gtk_css_gadget_get_preferred_size (swatch->priv->overlay_gadget, GTK_ORIENTATION_HORIZONTAL, -1, 
&overlay_width, NULL, NULL, NULL);
+  gtk_css_gadget_get_preferred_size (swatch->priv->overlay_gadget, GTK_ORIENTATION_VERTICAL, -1, 
&overlay_height, NULL, NULL, NULL);
+
+  overlay_alloc.x = allocation->x + (allocation->width - overlay_width) / 2;
+  overlay_alloc.y = allocation->y + (allocation->height - overlay_height) / 2;
+  overlay_alloc.width = overlay_width;
+  overlay_alloc.height = overlay_height;
+
+  gtk_css_gadget_allocate (swatch->priv->overlay_gadget, &overlay_alloc, baseline, out_clip);
+}
+
+static void
+swatch_get_preferred_width (GtkWidget *widget,
+                            gint      *minimum,
+                            gint      *natural)
+{
+  gtk_css_gadget_get_preferred_size (GTK_COLOR_SWATCH (widget)->priv->gadget,
+                                     GTK_ORIENTATION_HORIZONTAL,
+                                     -1,
+                                     minimum, natural,
+                                     NULL, NULL);
+}
+
+static void
+swatch_get_preferred_height (GtkWidget *widget,
+                             gint      *minimum,
+                             gint      *natural)
+{
+  gtk_css_gadget_get_preferred_size (GTK_COLOR_SWATCH (widget)->priv->gadget,
+                                     GTK_ORIENTATION_VERTICAL,
+                                     -1,
+                                     minimum, natural,
+                                     NULL, NULL);
 }
 
 static gboolean
@@ -615,7 +656,8 @@ swatch_state_flags_changed (GtkWidget     *widget,
 {
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
 
-  gtk_css_node_set_state (swatch->priv->overlay_node, gtk_widget_get_state_flags (widget));
+  gtk_css_node_set_state (gtk_css_gadget_get_node (swatch->priv->gadget), gtk_widget_get_state_flags 
(widget));
+  gtk_css_node_set_state (gtk_css_gadget_get_node (swatch->priv->overlay_gadget), gtk_widget_get_state_flags 
(widget));
 }
 
 /* GObject implementation {{{1 */
@@ -678,6 +720,8 @@ swatch_finalize (GObject *object)
   GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
 
   g_free (swatch->priv->icon);
+  g_clear_object (&swatch->priv->gadget);
+  g_clear_object (&swatch->priv->overlay_gadget);
 
   G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object);
 }
@@ -756,6 +800,54 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
 }
 
 
+static void
+gtk_color_swatch_init (GtkColorSwatch *swatch)
+{
+  GtkCssNode *widget_node;
+  GtkStyleContext *context;
+
+  swatch->priv = gtk_color_swatch_get_instance_private (swatch);
+  swatch->priv->use_alpha = TRUE;
+  swatch->priv->selectable = TRUE;
+  swatch->priv->has_menu = TRUE;
+
+  gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
+  gtk_widget_set_has_window (GTK_WIDGET (swatch), FALSE);
+
+  swatch->priv->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (swatch));
+  gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (swatch->priv->long_press_gesture),
+                                     TRUE);
+  g_signal_connect (swatch->priv->long_press_gesture, "pressed",
+                    G_CALLBACK (hold_action), swatch);
+
+  swatch->priv->multipress_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (swatch));
+  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (swatch->priv->multipress_gesture), 0);
+  g_signal_connect (swatch->priv->multipress_gesture, "pressed",
+                    G_CALLBACK (tap_action), swatch);
+
+  widget_node = gtk_widget_get_css_node (GTK_WIDGET (swatch));
+  swatch->priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
+                                                             GTK_WIDGET (swatch),
+                                                             gtk_color_swatch_get_content_size,
+                                                             gtk_color_swatch_allocate_contents,
+                                                             gtk_color_swatch_render_contents,
+                                                             NULL,
+                                                             NULL);
+
+  swatch->priv->overlay_gadget = gtk_css_custom_gadget_new ("overlay",
+                                                            GTK_WIDGET (swatch),
+                                                            swatch->priv->gadget,
+                                                            NULL,
+                                                            gtk_color_swatch_get_overlay_size,
+                                                            NULL,
+                                                            gtk_color_swatch_render_overlay,
+                                                            NULL,
+                                                            NULL);
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (swatch));
+  gtk_style_context_add_class (context, "activatable");
+}
+
 /* Public API {{{1 */
 
 GtkWidget *
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index fd9c890..1cfea18 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -3147,10 +3147,6 @@ colorswatch {
                                               transparentize(white, 1) 50%);
     box-shadow: inset 0 1px transparentize(white, 0.6),
                 inset 0 -1px if($variant == 'light', transparentize(black, 0.9), transparentize(black, 0.6));
-    &.dark overlay { // swatches with colors with luminosity lower than 50% get the dark class
-      background-image: linear-gradient(135deg, transparentize(white, 0.5),
-                                                transparentize(white, 1) 50%);
-    }
   }
   &:backdrop,
   &:backdrop:selected
@@ -3161,22 +3157,26 @@ colorswatch {
   }
 
   // indicator and keynav outline colors
-  &.dark overlay {
+  &.dark {
     color: white;
     outline-color: transparentize(white, 0.5);
+    border: 1px solid if($variant == 'light', transparentize(black, 0.7), $borders_color);
+    &:hover { border-color: if($variant == 'light', transparentize(black, 0.5), black); }
     &:backdrop { color: transparentize(white, 0.7); }
   }
-  &.light overlay {
+  &.light {
     color: black;
     outline-color: transparentize(black, 0.5);
+    border: 1px solid if($variant == 'light', transparentize(black, 0.7), $borders_color);
+    &:hover { border-color: if($variant == 'light', transparentize(black, 0.5), black); }
     &:backdrop { color: transparentize(black, 0.7); }
   }
 
   // border color
   & overlay,
   & overlay:selected {
-    border: 1px solid if($variant == 'light', transparentize(black, 0.7), $borders_color);
-    &:hover { border-color: if($variant == 'light', transparentize(black, 0.5), black); }
+    background: none;
+    border: none;
   }
 
   // make the add color button looks like, well, a button
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index 271dc25..6373d77 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -4317,26 +4317,29 @@ colorswatch {
   colorswatch.activatable:hover, colorswatch.activatable:hover:selected {
     background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0) 50%);
     box-shadow: inset 0 1px rgba(255, 255, 255, 0.4), inset 0 -1px rgba(0, 0, 0, 0.4); }
-    colorswatch.activatable:hover.dark overlay, colorswatch.activatable:hover:selected.dark overlay {
-      background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 50%); }
   colorswatch:backdrop, colorswatch:backdrop:selected
   colorswatch.dark:backdrop, colorswatch.dark:backdrop:selected {
     background-image: none;
     box-shadow: none; }
-  colorswatch.dark overlay {
+  colorswatch.dark {
     color: white;
-    outline-color: rgba(255, 255, 255, 0.5); }
-    colorswatch.dark overlay:backdrop {
+    outline-color: rgba(255, 255, 255, 0.5);
+    border: 1px solid #1c1f1f; }
+    colorswatch.dark:hover {
+      border-color: black; }
+    colorswatch.dark:backdrop {
       color: rgba(255, 255, 255, 0.3); }
-  colorswatch.light overlay {
+  colorswatch.light {
     color: black;
-    outline-color: rgba(0, 0, 0, 0.5); }
-    colorswatch.light overlay:backdrop {
-      color: rgba(0, 0, 0, 0.3); }
-  colorswatch overlay, colorswatch overlay:selected {
+    outline-color: rgba(0, 0, 0, 0.5);
     border: 1px solid #1c1f1f; }
-    colorswatch overlay:hover, colorswatch overlay:selected:hover {
+    colorswatch.light:hover {
       border-color: black; }
+    colorswatch.light:backdrop {
+      color: rgba(0, 0, 0, 0.3); }
+  colorswatch overlay, colorswatch overlay:selected {
+    background: none;
+    border: none; }
   colorswatch#add-color-button {
     border-style: solid;
     border-width: 1px;
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 8b5fe3d..4a5a2c0 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -4489,26 +4489,29 @@ colorswatch {
   colorswatch.activatable:hover, colorswatch.activatable:hover:selected {
     background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0) 50%);
     box-shadow: inset 0 1px rgba(255, 255, 255, 0.4), inset 0 -1px rgba(0, 0, 0, 0.1); }
-    colorswatch.activatable:hover.dark overlay, colorswatch.activatable:hover:selected.dark overlay {
-      background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 50%); }
   colorswatch:backdrop, colorswatch:backdrop:selected
   colorswatch.dark:backdrop, colorswatch.dark:backdrop:selected {
     background-image: none;
     box-shadow: none; }
-  colorswatch.dark overlay {
+  colorswatch.dark {
     color: white;
-    outline-color: rgba(255, 255, 255, 0.5); }
-    colorswatch.dark overlay:backdrop {
+    outline-color: rgba(255, 255, 255, 0.5);
+    border: 1px solid rgba(0, 0, 0, 0.3); }
+    colorswatch.dark:hover {
+      border-color: rgba(0, 0, 0, 0.5); }
+    colorswatch.dark:backdrop {
       color: rgba(255, 255, 255, 0.3); }
-  colorswatch.light overlay {
+  colorswatch.light {
     color: black;
-    outline-color: rgba(0, 0, 0, 0.5); }
-    colorswatch.light overlay:backdrop {
-      color: rgba(0, 0, 0, 0.3); }
-  colorswatch overlay, colorswatch overlay:selected {
+    outline-color: rgba(0, 0, 0, 0.5);
     border: 1px solid rgba(0, 0, 0, 0.3); }
-    colorswatch overlay:hover, colorswatch overlay:selected:hover {
+    colorswatch.light:hover {
       border-color: rgba(0, 0, 0, 0.5); }
+    colorswatch.light:backdrop {
+      color: rgba(0, 0, 0, 0.3); }
+  colorswatch overlay, colorswatch overlay:selected {
+    background: none;
+    border: none; }
   colorswatch#add-color-button {
     border-style: solid;
     border-width: 1px;


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