]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkvscale.c
/tmp/cvsX7MHVx
[~andy/gtk] / gtk / gtkvscale.c
index 2dca2cc99e3723710fadd69bf431b9d4cbbb5010..a9c02142e51fe16105cfd3a13fbd110288cbbc14 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
+#include <math.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include "gtkvscale.h"
-#include "gtksignal.h"
 #include "gtkintl.h"
+#include "gtkalias.h"
 
 #define VALUE_SPACING 2
 
-static gpointer parent_class;
-
-static void     gtk_vscale_class_init       (GtkVScaleClass *klass);
-static void     gtk_vscale_init             (GtkVScale      *vscale);
 static gboolean gtk_vscale_expose           (GtkWidget      *widget,
                                              GdkEventExpose *event);
 
-GtkType
-gtk_vscale_get_type (void)
-{
-  static GtkType vscale_type = 0;
-  
-  if (!vscale_type)
-    {
-      static const GtkTypeInfo vscale_info =
-      {
-        "GtkVScale",
-        sizeof (GtkVScale),
-        sizeof (GtkVScaleClass),
-        (GtkClassInitFunc) gtk_vscale_class_init,
-        (GtkObjectInitFunc) gtk_vscale_init,
-        /* reserved_1 */ NULL,
-        /* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
-      
-      vscale_type = gtk_type_unique (GTK_TYPE_SCALE, &vscale_info);
-    }
-  
-  return vscale_type;
-}
+static void    gtk_vscale_get_layout_offsets (GtkScale         *scale,
+                                               gint            *x,
+                                               gint            *y);
+
+G_DEFINE_TYPE (GtkVScale, gtk_vscale, GTK_TYPE_SCALE)
 
 static void
 gtk_vscale_class_init (GtkVScaleClass *class)
 {
-  GObjectClass   *gobject_class;
   GtkWidgetClass *widget_class;
   GtkRangeClass *range_class;
+  GtkScaleClass *scale_class;
   
-  gobject_class = G_OBJECT_CLASS (class);
   widget_class = GTK_WIDGET_CLASS (class);
   range_class = GTK_RANGE_CLASS (class); 
-
-  parent_class = g_type_class_peek_parent (class);
+  scale_class = GTK_SCALE_CLASS (class); 
 
   range_class->slider_detail = "vscale";
   
+  scale_class->get_layout_offsets = gtk_vscale_get_layout_offsets;
+
   widget_class->expose_event = gtk_vscale_expose;
 }
 
@@ -94,13 +74,7 @@ gtk_vscale_init (GtkVScale *vscale)
 GtkWidget*
 gtk_vscale_new (GtkAdjustment *adjustment)
 {
-  GtkWidget *vscale;
-  
-  vscale = gtk_widget_new (GTK_TYPE_VSCALE,
-                          "adjustment", adjustment,
-                          NULL);
-  
-  return vscale;
+  return g_object_new (GTK_TYPE_VSCALE, "adjustment", adjustment, NULL);
 }
 
 
@@ -110,10 +84,14 @@ gtk_vscale_new (GtkAdjustment *adjustment)
  * @max: maximum value
  * @step: step increment (tick size) used with keyboard shortcuts
  * 
- * Creates a new vertical scale widget that lets the user
- * input a number between @min and @max with the increment @step.
- * @step must be nonzero; it's the distance the slider moves when
- * using the arrow keys to adjust the scale value.
+ * Creates a new vertical scale widget that lets the user input a
+ * number between @min and @max (including @min and @max) with the
+ * increment @step.  @step must be nonzero; it's the distance the
+ * slider moves when using the arrow keys to adjust the scale value.
+ * 
+ * Note that the way in which the precision is derived works best if @step 
+ * is a power of ten. If the resulting precision is not suitable for your 
+ * needs, use gtk_scale_set_digits() to correct it. 
  * 
  * Return value: a new #GtkVScale
  **/
@@ -129,7 +107,7 @@ gtk_vscale_new_with_range (gdouble min,
   g_return_val_if_fail (min < max, NULL);
   g_return_val_if_fail (step != 0.0, NULL);
 
-  adj = gtk_adjustment_new (min, min, max, step, 10 * step, step);
+  adj = gtk_adjustment_new (min, min, max, step, 10 * step, 0);
   
   scale = g_object_new (GTK_TYPE_VSCALE,
                         "adjustment", adj,
@@ -152,64 +130,25 @@ static gboolean
 gtk_vscale_expose (GtkWidget      *widget,
                    GdkEventExpose *event)
 {
-  GtkRange *range;
-  GtkVScale *vscale;
   GtkScale *scale;
   
-  range = GTK_RANGE (widget);
   scale = GTK_SCALE (widget);
-  vscale = GTK_VSCALE (widget);
   
+  /* We need to chain up _first_ so the various geometry members of
+   * GtkRange struct are updated.
+   */
+  if (GTK_WIDGET_CLASS (gtk_vscale_parent_class)->expose_event)
+    GTK_WIDGET_CLASS (gtk_vscale_parent_class)->expose_event (widget, event);
+
   if (scale->draw_value)
     {
       PangoLayout *layout;
-      PangoRectangle logical_rect;
-      gchar *txt;
       gint x, y;
       GtkStateType state_type;
-      gint value_spacing;
 
-      gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
-      
-      txt = _gtk_scale_format_value (scale,
-                                     GTK_RANGE (scale)->adjustment->value);
-      
-      layout = gtk_widget_create_pango_layout (widget, txt);
-      g_free (txt);
-      
-      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-      
-      switch (scale->value_pos)
-        {
-        case GTK_POS_LEFT:
-          x = range->range_rect.x - logical_rect.width - value_spacing;
-          y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
-          y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
-          break;
-          
-        case GTK_POS_RIGHT:
-          x = range->range_rect.x + range->range_rect.width + value_spacing;
-          y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
-          y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
-          break;
-          
-        case GTK_POS_TOP:
-          x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
-          y = range->range_rect.y - logical_rect.height - value_spacing;
-          break;
-          
-        case GTK_POS_BOTTOM:
-          x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
-          y = range->range_rect.y + range->range_rect.height + value_spacing;
-          break;
-
-        default:
-          g_return_val_if_reached (FALSE);
-          x = 0;
-          y = 0;
-          break;
-        }
-      
+      layout = gtk_scale_get_layout (scale);
+      gtk_scale_get_layout_offsets (scale, &x, &y);
+
       state_type = GTK_STATE_NORMAL;
       if (!GTK_WIDGET_IS_SENSITIVE (scale))
         state_type = GTK_STATE_INSENSITIVE;
@@ -223,9 +162,75 @@ gtk_vscale_expose (GtkWidget      *widget,
                         "vscale",
                         x, y,
                         layout);
-
-      g_object_unref (G_OBJECT (layout));
     }
   
-  return (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
+  return FALSE;
+
 }
+
+static void
+gtk_vscale_get_layout_offsets (GtkScale *scale,
+                               gint     *x,
+                               gint     *y)
+{
+  GtkWidget *widget;
+  GtkRange *range;
+  PangoLayout *layout;
+  PangoRectangle logical_rect;
+  gint value_spacing;
+
+  widget = GTK_WIDGET (scale);
+  layout = gtk_scale_get_layout (scale);
+      
+  if (!layout)
+    {
+      *x = 0;
+      *y = 0;
+
+      return;
+    }
+
+  range = GTK_RANGE (widget);
+  scale = GTK_SCALE (widget);
+
+  gtk_widget_style_get (widget, "value-spacing", &value_spacing, NULL);
+      
+  pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+    
+  switch (scale->value_pos)
+    {
+    case GTK_POS_LEFT:
+      *x = range->range_rect.x - logical_rect.width - value_spacing;
+      *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
+      *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
+      break;
+      
+    case GTK_POS_RIGHT:
+      *x = range->range_rect.x + range->range_rect.width + value_spacing;
+      *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
+      *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
+      break;
+          
+    case GTK_POS_TOP:
+      *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
+      *y = range->range_rect.y - logical_rect.height - value_spacing;
+      break;
+          
+    case GTK_POS_BOTTOM:
+      *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
+      *y = range->range_rect.y + range->range_rect.height + value_spacing;
+      break;
+
+    default:
+      g_return_if_reached ();
+      *x = 0;
+      *y = 0;
+      break;
+    }
+
+  *x += widget->allocation.x;
+  *y += widget->allocation.y;
+}
+
+#define __GTK_VSCALE_C__
+#include "gtkaliasdef.c"