[gtk+/wip/cosimoc/range-gadget] scale: add gadgets for indicator/label in scale marks



commit 27fc7a1f1d3c45636a79034e3b86e95cdb589b52
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Sun Feb 28 21:13:54 2016 -0800

    scale: add gadgets for indicator/label in scale marks
    
    This will allow us to theme them indepdendently, and specify a size for
    the indicator from the theme.

 gtk/gtkscale.c                           |  280 ++++++++++++++++++++----------
 gtk/theme/Adwaita/_common.scss           |   10 +-
 gtk/theme/Adwaita/gtk-contained-dark.css |    8 +-
 gtk/theme/Adwaita/gtk-contained.css      |    8 +-
 4 files changed, 209 insertions(+), 97 deletions(-)
---
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
index 4adc022..3caecb7 100644
--- a/gtk/gtkscale.c
+++ b/gtk/gtkscale.c
@@ -140,6 +140,8 @@ struct _GtkScaleMark
   int              stop_position;
   gchar           *markup;
   GtkCssGadget    *gadget;
+  GtkCssGadget    *indicator_gadget;
+  GtkCssGadget    *label_gadget;
   GtkPositionType  position; /* always GTK_POS_TOP or GTK_POS_BOTTOM */
 };
 
@@ -257,6 +259,81 @@ gtk_scale_notify (GObject    *object,
     G_OBJECT_CLASS (gtk_scale_parent_class)->notify (object, pspec);
 }
 
+static void
+gtk_scale_allocate_mark (GtkCssGadget        *gadget,
+                         const GtkAllocation *allocation,
+                         int                  baseline,
+                         GtkAllocation       *out_clip,
+                         gpointer             user_data)
+{
+  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+  GtkScaleMark *mark = user_data;
+  GtkAllocation indicator_alloc, widget_alloc;
+  int indicator_width, indicator_height;
+  GtkOrientation orientation;
+
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+  gtk_widget_get_allocation (widget, &widget_alloc);
+  gtk_css_gadget_get_preferred_size (mark->indicator_gadget,
+                                     GTK_ORIENTATION_HORIZONTAL, -1,
+                                     &indicator_width, NULL,
+                                     NULL, NULL);
+  gtk_css_gadget_get_preferred_size (mark->indicator_gadget,
+                                     GTK_ORIENTATION_VERTICAL, -1,
+                                     &indicator_height, NULL,
+                                     NULL, NULL);
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      indicator_alloc.x = mark->stop_position + widget_alloc.x - indicator_width / 2;
+      if (mark->position == GTK_POS_TOP)
+        indicator_alloc.y = allocation->y + allocation->height - indicator_height;
+      else
+        indicator_alloc.y = allocation->y;
+      indicator_alloc.width = indicator_width;
+      indicator_alloc.height = indicator_height;
+    }
+  else
+    {
+      if (mark->position == GTK_POS_TOP)
+        indicator_alloc.x = allocation->x + allocation->width - indicator_width;
+      else
+        indicator_alloc.x = allocation->x;
+      indicator_alloc.y = mark->stop_position + widget_alloc.y - indicator_height / 2;
+      indicator_alloc.width = indicator_width;
+      indicator_alloc.height = indicator_height;
+    }
+
+  gtk_css_gadget_allocate (mark->indicator_gadget,
+                           &indicator_alloc, baseline,
+                           out_clip);
+
+  if (mark->label_gadget)
+    {
+      GtkAllocation label_alloc, label_clip;
+
+      label_alloc = *allocation;
+
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        {
+          label_alloc.height = allocation->height - indicator_alloc.height;
+          if (mark->position == GTK_POS_BOTTOM)
+            label_alloc.y = indicator_alloc.y + indicator_alloc.height;
+        }
+      else
+        {
+          label_alloc.width = allocation->width - indicator_alloc.width;
+          if (mark->position == GTK_POS_BOTTOM)
+            label_alloc.x = indicator_alloc.x + indicator_alloc.width;
+        }
+
+      gtk_css_gadget_allocate (mark->label_gadget,
+                               &label_alloc, baseline,
+                               &label_clip);
+      gdk_rectangle_union (out_clip, &label_clip, out_clip);
+    }
+}
+
 static gint
 find_next_pos (GtkWidget       *widget,
                GSList          *list,
@@ -1255,14 +1332,14 @@ gtk_scale_screen_changed (GtkWidget *widget,
 }
 
 static void
-gtk_scale_measure_mark (GtkCssGadget   *gadget,
-                        GtkOrientation  orientation,
-                        gint            for_size,
-                        gint           *minimum,
-                        gint           *natural,
-                        gint           *minimum_baseline,
-                        gint           *natural_baseline,
-                        gpointer        user_data)
+gtk_scale_measure_mark_label (GtkCssGadget   *gadget,
+                              GtkOrientation  orientation,
+                              gint            for_size,
+                              gint           *minimum,
+                              gint           *natural,
+                              gint           *minimum_baseline,
+                              gint           *natural_baseline,
+                              gpointer        user_data)
 {
   GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
   GtkScaleMark *mark = user_data;
@@ -1288,6 +1365,36 @@ gtk_scale_measure_mark (GtkCssGadget   *gadget,
 }
 
 static void
+gtk_scale_measure_mark (GtkCssGadget   *gadget,
+                        GtkOrientation  orientation,
+                        gint            for_size,
+                        gint           *minimum,
+                        gint           *natural,
+                        gint           *minimum_baseline,
+                        gint           *natural_baseline,
+                        gpointer        user_data)
+{
+  GtkScaleMark *mark = user_data;
+
+  gtk_css_gadget_get_preferred_size (mark->indicator_gadget,
+                                     orientation, -1,
+                                     minimum, natural,
+                                     NULL, NULL);
+
+  if (mark->label_gadget)
+    {
+      int label_min, label_nat;
+
+      gtk_css_gadget_get_preferred_size (mark->label_gadget,
+                                         orientation, -1,
+                                         &label_min, &label_nat,
+                                         NULL, NULL);
+      *minimum += label_min;
+      *natural += label_nat;
+    }
+}
+
+static void
 gtk_scale_measure_marks (GtkCssGadget   *gadget,
                          GtkOrientation  orientation,
                          gint            for_size,
@@ -1397,100 +1504,57 @@ gtk_scale_get_preferred_height (GtkWidget *widget,
 }
 
 static gboolean
-gtk_scale_render_mark (GtkCssGadget *gadget,
-                       cairo_t      *cr,
-                       int           x,
-                       int           y,
-                       int           width,
-                       int           height,
-                       gpointer      user_data)
+gtk_scale_render_mark_indicator (GtkCssGadget *gadget,
+                                 cairo_t      *cr,
+                                 int           x,
+                                 int           y,
+                                 int           width,
+                                 int           height,
+                                 gpointer      user_data)
 {
   GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
-  GtkScale *scale = GTK_SCALE (widget);
-  GtkScaleMark *mark = user_data;
-  GtkOrientation orientation;
-  GtkAllocation slider_alloc;
-  GtkCssGadget *slider_gadget;
   GtkStyleContext *context;
-  PangoLayout *layout;
-
-  slider_gadget = gtk_range_get_slider_gadget (GTK_RANGE (scale));
-  gtk_css_gadget_get_content_allocation (slider_gadget,
-                                         &slider_alloc, NULL);
-
-  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (scale));
+  GtkOrientation orientation;
 
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
   context = gtk_widget_get_style_context (widget);
   gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget));
 
-  layout = gtk_widget_create_pango_layout (widget, NULL);
-
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    {
-      int y1, y2;
-
-      if (mark->position == GTK_POS_TOP)
-        {
-          y1 = y + height;
-          y2 = y + height - slider_alloc.height / 4;
-        }
-      else
-        {
-          y1 = y;
-          y2 = y + slider_alloc.height / 4;
-        }
-
-      gtk_render_line (context, cr,
-                       mark->stop_position, y1,
-                       mark->stop_position, y2);
-
-      if (mark->markup)
-        {
-          int y3;
-
-          pango_layout_set_markup (layout, mark->markup, -1);
-
-          if (mark->position == GTK_POS_TOP)
-            y3 = y;
-          else
-            y3 = y2;
-
-          gtk_render_layout (context, cr, x, y3, layout);
-        }
-    }
+    gtk_render_line (context, cr,
+                     x + width / 2, y,
+                     x + width / 2, y + height);
   else
-    {
-      int x1, x2;
+    gtk_render_line (context, cr,
+                     x, y + height / 2,
+                     x + width, y + height / 2);
 
-      if (mark->position == GTK_POS_TOP)
-        {
-          x1 = x + width;
-          x2 = x + width - slider_alloc.width / 4;
-        }
-      else
-        {
-          x1 = x;
-          x2 = x + slider_alloc.width / 4;
-        }
+  gtk_style_context_restore (context);
 
-      gtk_render_line (context, cr,
-                       x1, mark->stop_position,
-                       x2, mark->stop_position);
+  return FALSE;
+}
 
-      if (mark->markup)
-        {
-          int x3;
+static gboolean
+gtk_scale_render_mark_label (GtkCssGadget *gadget,
+                             cairo_t      *cr,
+                             int           x,
+                             int           y,
+                             int           width,
+                             int           height,
+                             gpointer      user_data)
+{
+  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+  GtkScaleMark *mark = user_data;
+  GtkStyleContext *context;
+  PangoLayout *layout;
 
-          pango_layout_set_markup (layout, mark->markup, -1);
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget));
 
-          if (mark->position == GTK_POS_TOP)
-            x3 = x;
-          else
-            x3 = x2;
+  layout = gtk_widget_create_pango_layout (widget, NULL);
+  pango_layout_set_markup (layout, mark->markup, -1);
 
-          gtk_render_layout (context, cr, x3, y, layout);
-        }
-    }
+  gtk_render_layout (context, cr, x, y, layout);
 
   gtk_style_context_restore (context);
   g_object_unref (layout);
@@ -1499,6 +1563,24 @@ gtk_scale_render_mark (GtkCssGadget *gadget,
 }
 
 static gboolean
+gtk_scale_render_mark (GtkCssGadget *gadget,
+                       cairo_t      *cr,
+                       int           x,
+                       int           y,
+                       int           width,
+                       int           height,
+                       gpointer      user_data)
+{
+  GtkScaleMark *mark = user_data;
+
+  gtk_css_gadget_draw (mark->indicator_gadget, cr);
+  if (mark->label_gadget)
+    gtk_css_gadget_draw (mark->label_gadget, cr);
+
+  return FALSE;
+}
+
+static gboolean
 gtk_scale_render_marks (GtkCssGadget *gadget,
                         cairo_t      *cr,
                         int           x,
@@ -1778,6 +1860,8 @@ gtk_scale_mark_free (gpointer data)
 {
   GtkScaleMark *mark = data;
 
+  g_clear_object (&mark->label_gadget);
+  g_object_unref (mark->indicator_gadget);
   g_object_unref (mark->gadget);
   g_free (mark->markup);
   g_free (mark);
@@ -1853,7 +1937,7 @@ gtk_scale_add_mark (GtkScale        *scale,
   priv = scale->priv;
   widget_node = gtk_widget_get_css_node (GTK_WIDGET (scale));
 
-  mark = g_new (GtkScaleMark, 1);
+  mark = g_new0 (GtkScaleMark, 1);
   mark->value = value;
   mark->markup = g_strdup (markup);
   if (position == GTK_POS_LEFT ||
@@ -1905,11 +1989,29 @@ gtk_scale_add_mark (GtkScale        *scale,
     gtk_css_custom_gadget_new ("mark",
                                GTK_WIDGET (scale), NULL, NULL,
                                gtk_scale_measure_mark,
-                               NULL,
+                               gtk_scale_allocate_mark,
                                gtk_scale_render_mark,
                                mark, NULL);
   gtk_css_gadget_set_state (mark->gadget, gtk_css_node_get_state (marks_node));
 
+  mark->indicator_gadget =
+    gtk_css_custom_gadget_new ("indicator",
+                               GTK_WIDGET (scale), mark->gadget, NULL,
+                               NULL,
+                               NULL,
+                               gtk_scale_render_mark_indicator,
+                               mark, NULL);
+  if (mark->markup)
+    mark->label_gadget =
+      gtk_css_custom_gadget_new ("label",
+                                 GTK_WIDGET (scale), mark->gadget,
+                                 mark->position == GTK_POS_TOP ?
+                                 NULL : mark->indicator_gadget,
+                                 gtk_scale_measure_mark_label,
+                                 NULL,
+                                 gtk_scale_render_mark_label,
+                                 mark, NULL);
+
   m = g_slist_find (priv->marks, mark);
   m = m->next;
   while (m)
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index 5adbd2a..2a06087 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -2578,8 +2578,14 @@ scale {
   }
 
   marks { color: gtkalpha(currentColor, 0.4); }
-  &.horizontal marks { min-height: 8px; }
-  &.vertical marks { min-width: 8px; }
+  &.horizontal mark indicator {
+    min-height: 8px;
+    min-width: 1px;
+  }
+  &.vertical mark indicator {
+    min-height: 1px;
+    min-width: 8px;
+  }
 
   // *WARNING* scale with marks madness following
 
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index f56f6b5..5025b17 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -2757,9 +2757,11 @@ scale {
         -gtk-icon-shadow: none; }
   scale marks {
     color: alpha(currentColor,0.4); }
-  scale.horizontal marks {
-    min-height: 8px; }
-  scale.vertical marks {
+  scale.horizontal mark indicator {
+    min-height: 8px;
+    min-width: 1px; }
+  scale.vertical mark indicator {
+    min-height: 1px;
     min-width: 8px; }
   scale.color.horizontal trough > trough > slider, scale.horizontal contents:last-child:not(:only-child) > 
trough > slider {
     margin: -9px;
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 3662aff..e35f5be 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -2788,9 +2788,11 @@ scale {
         -gtk-icon-shadow: none; }
   scale marks {
     color: alpha(currentColor,0.4); }
-  scale.horizontal marks {
-    min-height: 8px; }
-  scale.vertical marks {
+  scale.horizontal mark indicator {
+    min-height: 8px;
+    min-width: 1px; }
+  scale.vertical mark indicator {
+    min-height: 1px;
     min-width: 8px; }
   scale.color.horizontal trough > trough > slider, scale.horizontal contents:last-child:not(:only-child) > 
trough > slider {
     margin: -9px;


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