[gtk+/gtk-2-18] Avoid overlap of scale marks



commit 9149577e1a2f8c068768170d3b77c379137c4fce
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Feb 9 00:42:56 2010 -0500

    Avoid overlap of scale marks
    
    This was reported to be a problem in bug 608807.
    (cherry picked from commit 893408352d89a04fe70d4b160a6010a0e00072a4)

 gtk/gtkscale.c |   89 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 80 insertions(+), 9 deletions(-)
---
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
index 2f4cc98..a69e053 100644
--- a/gtk/gtkscale.c
+++ b/gtk/gtkscale.c
@@ -925,6 +925,27 @@ gtk_scale_size_request (GtkWidget      *widget,
     }
 }
 
+static gint
+find_next_pos (GtkWidget      *widget,
+               GSList          *list,
+               gint            *marks,
+               GtkPositionType  pos,
+               gint             match)
+{
+  GSList *m;
+  gint i;
+
+  for (m = list->next, i = 1; m; m = m->next, i++)
+    {
+      GtkScaleMark *mark = m->data;
+
+      if (match == (mark->position == pos))
+        return marks[i];
+    }
+
+  return widget->allocation.width;
+}
+
 static gboolean
 gtk_scale_expose (GtkWidget      *widget,
                   GdkEventExpose *event)
@@ -938,6 +959,7 @@ gtk_scale_expose (GtkWidget      *widget,
   gint focus_padding;
   gint slider_width;
   gint value_spacing;
+  gint min_sep = 4;
 
   gtk_widget_style_get (widget,
                         "focus-padding", &focus_padding,
@@ -961,10 +983,16 @@ gtk_scale_expose (GtkWidget      *widget,
       PangoLayout *layout;
       PangoRectangle logical_rect;
       GSList *m;
+      gint min_pos_before, min_pos_after;
+      gint min_pos, max_pos;
 
       n_marks = _gtk_range_get_stop_positions (range, &marks);
       layout = gtk_widget_create_pango_layout (widget, NULL);
 
+      if (range->orientation == GTK_ORIENTATION_HORIZONTAL)
+        min_pos_before = min_pos_after = widget->allocation.x;
+      else
+        min_pos_before = min_pos_after = widget->allocation.y;
       for (m = priv->marks, i = 0; m; m = m->next, i++)
         {
           GtkScaleMark *mark = m->data;
@@ -976,11 +1004,15 @@ gtk_scale_expose (GtkWidget      *widget,
                 {
                   y1 = widget->allocation.y + range->range_rect.y;
                   y2 = y1 - slider_width / 2;
+                  min_pos = min_pos_before;
+                  max_pos = widget->allocation.x + find_next_pos (widget, m, marks + i, GTK_POS_TOP, 1) - min_sep;
                 }
               else
                 {
                   y1 = widget->allocation.y + range->range_rect.y + range->range_rect.height;
                   y2 = y1 + slider_width / 2;
+                  min_pos = min_pos_after;
+                  max_pos = widget->allocation.x + find_next_pos (widget, m, marks + i, GTK_POS_TOP, 0) - min_sep;
                 }
 
               gtk_paint_vline (widget->style, widget->window, state_type,
@@ -990,15 +1022,27 @@ gtk_scale_expose (GtkWidget      *widget,
                 {
                   pango_layout_set_markup (layout, mark->markup, -1);
                   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-              
+
                   x3 = x1 - logical_rect.width / 2;
+                  if (x3 < min_pos)
+                    x3 = min_pos;
+                  if (x3 + logical_rect.width > max_pos)
+                        x3 = max_pos - logical_rect.width;
+                  if (x3 < widget->allocation.x)
+                     x3 = widget->allocation.x;
                   if (mark->position == GTK_POS_TOP)
-                    y3 = y2 - value_spacing - logical_rect.height;
+                    {
+                      y3 = y2 - value_spacing - logical_rect.height;
+                      min_pos_before = x3 + logical_rect.width + min_sep;
+                    }
                   else
-                    y3 = y2 + value_spacing; 
+                    {
+                      y3 = y2 + value_spacing;
+                      min_pos_after = x3 + logical_rect.width + min_sep;
+                    }
 
                   gtk_paint_layout (widget->style, widget->window, state_type,
-                                    FALSE, NULL, widget, "scale-mark", 
+                                    FALSE, NULL, widget, "scale-mark",
                                     x3, y3, layout);
                 }
             }
@@ -1008,11 +1052,15 @@ gtk_scale_expose (GtkWidget      *widget,
                 {
                   x1 = widget->allocation.x + range->range_rect.x;
                   x2 = widget->allocation.x + range->range_rect.x - slider_width / 2;
+                  min_pos = min_pos_before;
+                  max_pos = widget->allocation.y + find_next_pos (widget, m, marks + i, GTK_POS_LEFT, 1) - min_sep;
                 }
               else
                 {
                   x1 = widget->allocation.x + range->range_rect.x + range->range_rect.width;
                   x2 = widget->allocation.x + range->range_rect.x + range->range_rect.width + slider_width / 2;
+                  min_pos = min_pos_after;
+                  max_pos = widget->allocation.y + find_next_pos (widget, m, marks + i, GTK_POS_LEFT, 0) - min_sep;
                 }
               y1 = widget->allocation.y + marks[i];
 
@@ -1024,14 +1072,26 @@ gtk_scale_expose (GtkWidget      *widget,
                   pango_layout_set_markup (layout, mark->markup, -1);
                   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
               
+                  y3 = y1 - logical_rect.height / 2;
+                  if (y3 < min_pos)
+                    y3 = min_pos;
+                  if (y3 + logical_rect.height > max_pos)
+                    y3 = max_pos - logical_rect.height;
+                  if (y3 < widget->allocation.y)
+                    y3 = widget->allocation.y;
                   if (mark->position == GTK_POS_LEFT)
-                    x3 = x2 - value_spacing - logical_rect.width;
+                    {
+                      x3 = x2 - value_spacing - logical_rect.width;
+                      min_pos_before = y3 + logical_rect.height + min_sep;
+                    }
                   else
-                    x3 = x2 + value_spacing; 
-                  y3 = y1 - logical_rect.height / 2;
+                    {
+                      x3 = x2 + value_spacing;
+                      min_pos_after = y3 + logical_rect.height + min_sep;
+                    }
 
                   gtk_paint_layout (widget->style, widget->window, state_type,
-                                    FALSE, NULL, widget, "scale-mark", 
+                                    FALSE, NULL, widget, "scale-mark",
                                     x3, y3, layout);
                 }
             }
@@ -1315,6 +1375,16 @@ gtk_scale_clear_marks (GtkScale *scale)
   gtk_widget_queue_resize (GTK_WIDGET (scale));
 }
 
+static gint
+compare_marks (gpointer a, gpointer b)
+{
+  GtkScaleMark *ma, *mb;
+
+  ma = a; mb = b;
+
+  return (gint) (ma->value - mb->value);
+}
+
 /**
  * gtk_scale_add_mark:
  * @scale: a #GtkScale
@@ -1356,7 +1426,8 @@ gtk_scale_add_mark (GtkScale        *scale,
   mark->markup = g_strdup (markup);
   mark->position = position;
  
-  priv->marks = g_slist_prepend (priv->marks, mark);
+  priv->marks = g_slist_insert_sorted (priv->marks, mark,
+                                       (GCompareFunc) compare_marks);
 
   n = g_slist_length (priv->marks);
   values = g_new (gdouble, n);



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