Range arrow screwup



Shortly before we released 2.0, we made a change
to gtkrange.c so that the steppers weren't drawn
as a single call to the ARROW function, but as a
BOX with an ARROW on top. (Offending change appended.)

I have a strong memory of telling Soeren to do it
this way (As I recall, so that themes that wanted the 
arrow-on-box look wouldn't have to duplicate the
arrow positioning and sizing code), but it was 
in fact a screwup. 

 * It makes it very hard for themes to draw 
   non-box-and-arrow themes since for the BOX
   paint function, there is no indication of 
   _which_ type of stepper is being drawn.

 * Even for box-and-arrow themes, the theme engine
   may want to draw different steppers differently
   so they, for instance, properly integrate into
   the trough bevel. (The metal theme engine did
   this.)

 * It broke existing themes and theme engines. In fact, 
   for pixmap engine themes, it is the biggest difficulty
   in porting a 1.2 pixmap theme to 2.0.

So, what can we do to restore the lost functionality?

 1) Revert the change, and do it the way Soeren
    originally had it - where the arrow sizing
    code is in the default theme engine.

    If theme engines want to take advantage
    of the default setup, they could chain up
    GtkArrow for a detail of "hscrollbar" or
    "vscrollbar".

    This would break existing working gtk-2.0 
    theme engines like Crux, thinice, because they
    would suddently start drawing naked arrows
    instead of steppers.

    And it would be impossible for pixmap themes
    to use the default code becuase there is
    no way in the pixmap theme engine code to 
    do negative matching. (Use this image *unless*
    the detail is ...)

 2) Add a new style function STEPPER that is drawn
    in the default theme with BOX/ARROW.

    This is cleanest, and completely compatible
    with themes that work currently.

    However, it's also an API addition.

    1.2 pixmap themes would need some fairly mechanical
    changes. (E.g. ARROW/hscrollbar to STEPPER/hscrollbar)n

 3) Nothing. Knowing the stepper size it's possible
    for a theme engine to:

     a) Ignore the BOX calls with the stepper detail
     b) Reverse engineer the entire stepper area
        when the ARROW call is made, and then 
        draw with the expaneded area.

    So, no functionality is actually lost for theme
    engines, it's just made incredibly ugly.

    And pixmap themes can't use this approach, though
    the pixmap theme engine could fake a "STEPPER"
    function without having to have it actually 
    implemented in GTK+.

My current best idea is to take approach 2) for 2.2,
and for now do 3) and hack metal to work as indicated.

Regards,
                                    Owen

Index: gtkrange.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -p -r1.78 -r1.79
--- gtkrange.c	23 Feb 2002 14:46:21 -0000	1.78
+++ gtkrange.c	26 Feb 2002 23:50:14 -0000	1.79
@@ -834,6 +853,11 @@ draw_stepper (GtkRange     *range,
   GdkRectangle intersection;
   GtkWidget *widget = GTK_WIDGET (range);
 
+  gint arrow_x;
+  gint arrow_y;
+  gint arrow_width;
+  gint arrow_height;
+
   /* More to get the right clip region than for efficiency */
   if (!gdk_rectangle_intersect (area, rect, &intersection))
     return;
@@ -854,17 +878,42 @@ draw_stepper (GtkRange     *range,
     shadow_type = GTK_SHADOW_IN;
   else
     shadow_type = GTK_SHADOW_OUT;
+
+  gtk_paint_box (widget->style,
+		 widget->window,
+		 state_type, shadow_type,
+		 &intersection, widget,
+		 GTK_RANGE_GET_CLASS (range)->stepper_detail,
+		 widget->allocation.x + rect->x,
+		 widget->allocation.y + rect->y,
+		 rect->width,
+		 rect->height);
+
+  arrow_width = rect->width / 2;
+  arrow_height = rect->height / 2;
+  arrow_x = widget->allocation.x + rect->x + (rect->width - arrow_width) / 2;
+  arrow_y = widget->allocation.y + rect->y + (rect->height - arrow_height) / 2;
   
-  gtk_paint_arrow (GTK_WIDGET (range)->style,
-                   GTK_WIDGET (range)->window,
+  if (clicked)
+    {
+      gint arrow_displacement_x;
+      gint arrow_displacement_y;
+
+      gtk_range_get_props (GTK_RANGE (widget), NULL, NULL, NULL, NULL,
+			   &arrow_displacement_x, &arrow_displacement_y);
+      
+      arrow_x += arrow_displacement_x;
+      arrow_y += arrow_displacement_y;
+    }
+  
+  gtk_paint_arrow (widget->style,
+                   widget->window,
                    state_type, shadow_type, 
-                   &intersection, GTK_WIDGET (range),
+                   &intersection, widget,
                    GTK_RANGE_GET_CLASS (range)->stepper_detail,
                    arrow_type,
                    TRUE,
-		   widget->allocation.x + rect->x,
-		   widget->allocation.y + rect->y,
-		   rect->width, rect->height);
+		   arrow_x, arrow_y, arrow_width, arrow_height);
 }
 
 static gint



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