]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkvruler.c
get XDisplay from window instead of display, as display has not been
[~andy/gtk] / gtk / gtkvruler.c
index e75995379722000c4a07a566a5e05b0b27bf65ff..978f62345bb8bb687075cfe08098e5a29108fbec 100644 (file)
@@ -2,20 +2,28 @@
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
 #include <math.h>
 #include <stdio.h>
 #include <string.h>
@@ -38,25 +46,26 @@ static void gtk_vruler_draw_ticks    (GtkRuler       *ruler);
 static void gtk_vruler_draw_pos      (GtkRuler       *ruler);
 
 
-guint
+GtkType
 gtk_vruler_get_type (void)
 {
-  static guint vruler_type = 0;
+  static GtkType vruler_type = 0;
 
   if (!vruler_type)
     {
-      GtkTypeInfo vruler_info =
+      static const GtkTypeInfo vruler_info =
       {
        "GtkVRuler",
        sizeof (GtkVRuler),
        sizeof (GtkVRulerClass),
        (GtkClassInitFunc) gtk_vruler_class_init,
        (GtkObjectInitFunc) gtk_vruler_init,
-       (GtkArgSetFunc) NULL,
-        (GtkArgGetFunc) NULL,
+       /* reserved_1 */ NULL,
+        /* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
       };
 
-      vruler_type = gtk_type_unique (gtk_ruler_get_type (), &vruler_info);
+      vruler_type = gtk_type_unique (GTK_TYPE_RULER, &vruler_info);
     }
 
   return vruler_type;
@@ -83,14 +92,14 @@ gtk_vruler_init (GtkVRuler *vruler)
   GtkWidget *widget;
 
   widget = GTK_WIDGET (vruler);
-  widget->requisition.width = widget->style->klass->xthickness * 2 + RULER_WIDTH;
-  widget->requisition.height = widget->style->klass->ythickness * 2 + 1;
+  widget->requisition.width = widget->style->xthickness * 2 + RULER_WIDTH;
+  widget->requisition.height = widget->style->ythickness * 2 + 1;
 }
 
 GtkWidget*
 gtk_vruler_new (void)
 {
-  return GTK_WIDGET (gtk_type_new (gtk_vruler_get_type ()));
+  return GTK_WIDGET (gtk_type_new (GTK_TYPE_VRULER));
 }
 
 
@@ -101,10 +110,6 @@ gtk_vruler_motion_notify (GtkWidget      *widget,
   GtkRuler *ruler;
   gint y;
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_VRULER (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
   ruler = GTK_RULER (widget);
 
   if (event->is_hint)
@@ -113,6 +118,7 @@ gtk_vruler_motion_notify (GtkWidget      *widget,
     y = event->y;
 
   ruler->position = ruler->lower + ((ruler->upper - ruler->lower) * y) / widget->allocation.height;
+  g_object_notify (G_OBJECT (ruler), "position");
 
   /*  Make sure the ruler has been allocated already  */
   if (ruler->backing_store != NULL)
@@ -126,118 +132,145 @@ gtk_vruler_draw_ticks (GtkRuler *ruler)
 {
   GtkWidget *widget;
   GdkGC *gc, *bg_gc;
-  GdkFont * font;
   gint i, j;
   gint width, height;
   gint xthickness;
   gint ythickness;
   gint length, ideal_length;
-  gfloat subd_incr;
-  gfloat step_incr;
-  gfloat increment;
-  gfloat start, end, cur;
+  gdouble lower, upper;                /* Upper and lower limits, in ruler units */
+  gdouble increment;           /* Number of pixels per unit */
+  gint scale;                  /* Number of units per major unit */
+  gdouble subd_incr;
+  gdouble start, end, cur;
   gchar unit_str[32];
-  gchar digit_str[2] = { '\0', '\0' };
-  gint text_height;
   gint digit_height;
+  gint digit_offset;
+  gint text_height;
   gint pos;
-  gint scale;
-
-  g_return_if_fail (ruler != NULL);
-  g_return_if_fail (GTK_IS_VRULER (ruler));
-
-  if (GTK_WIDGET_DRAWABLE (ruler))
+  PangoLayout *layout;
+  PangoRectangle logical_rect, ink_rect;
+
+  if (!GTK_WIDGET_DRAWABLE (ruler)) 
+    return;
+
+  widget = GTK_WIDGET (ruler);
+
+  gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+  bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
+
+  xthickness = widget->style->xthickness;
+  ythickness = widget->style->ythickness;
+
+  layout = gtk_widget_create_pango_layout (widget, "012456789");
+  pango_layout_get_extents (layout, &ink_rect, &logical_rect);
+  
+  digit_height = PANGO_PIXELS (ink_rect.height) + 2;
+  digit_offset = ink_rect.y;
+
+  width = widget->allocation.height;
+  height = widget->allocation.width - ythickness * 2;
+
+  gtk_paint_box (widget->style, ruler->backing_store,
+                GTK_STATE_NORMAL, GTK_SHADOW_OUT, 
+                NULL, widget, "vruler",
+                0, 0, 
+                 widget->allocation.width, widget->allocation.height);
+  
+  gdk_draw_line (ruler->backing_store, gc,
+                height + xthickness,
+                ythickness,
+                height + xthickness,
+                widget->allocation.height - ythickness);
+  
+  upper = ruler->upper / ruler->metric->pixels_per_unit;
+  lower = ruler->lower / ruler->metric->pixels_per_unit;
+
+  if ((upper - lower) == 0)
+    return;
+  increment = (gdouble) width / (upper - lower);
+
+  /* determine the scale
+   *   use the maximum extents of the ruler to determine the largest
+   *   possible number to be displayed.  Calculate the height in pixels
+   *   of this displayed text. Use this height to find a scale which
+   *   leaves sufficient room for drawing the ruler.  
+   */
+  scale = ceil (ruler->max_size / ruler->metric->pixels_per_unit);
+  sprintf (unit_str, "%d", scale);
+  text_height = strlen (unit_str) * digit_height + 1;
+
+  for (scale = 0; scale < MAXIMUM_SCALES; scale++)
+    if (ruler->metric->ruler_scale[scale] * fabs(increment) > 2 * text_height)
+      break;
+
+  if (scale == MAXIMUM_SCALES)
+    scale = MAXIMUM_SCALES - 1;
+
+  /* drawing starts here */
+  length = 0;
+  for (i = MAXIMUM_SUBDIVIDE - 1; i >= 0; i--)
     {
-      widget = GTK_WIDGET (ruler);
+      subd_incr = (gdouble) ruler->metric->ruler_scale[scale] / 
+                 (gdouble) ruler->metric->subdivide[i];
+      if (subd_incr * fabs(increment) <= MINIMUM_INCR) 
+       continue;
 
-      gc = widget->style->fg_gc[GTK_STATE_NORMAL];
-      bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
-      font = widget->style->font;
-      xthickness = widget->style->klass->xthickness;
-      ythickness = widget->style->klass->ythickness;
-      digit_height = font->ascent; /* Assume descent == 0 ? */
-
-      width = widget->allocation.height;
-      height = widget->allocation.width - ythickness * 2;
-      gdk_draw_line (ruler->backing_store, gc,
-                    height + xthickness,
-                    ythickness,
-                    height + xthickness,
-                    widget->allocation.height - ythickness);
-
-      if ((ruler->upper - ruler->lower) == 0)
-       return;
-
-      increment = (gfloat) width * ruler->metric->pixels_per_unit / (ruler->upper - ruler->lower);
-
-      /*  determine the scale
-       *   use the maximum extents of the ruler to determine the largest possible
-       *   number to be displayed.  calculate the height in pixels of this displayed
-       *   text as for the vertical ruler case.  use this height to find a scale
-       *   which leaves sufficient room for drawing the ruler.
+      /* Calculate the length of the tickmarks. Make sure that
+       * this length increases for each set of ticks
        */
-      scale = ceil (ruler->max_size / ruler->metric->pixels_per_unit);
-      sprintf (unit_str, "%d", scale);
-      text_height = strlen (unit_str) * digit_height + 1;
-
-      for (scale = 0; scale < MAXIMUM_SCALES; scale++)
-       if (ruler->metric->ruler_scale[scale] * increment > 2 * text_height)
-         break;
+      ideal_length = height / (i + 1) - 1;
+      if (ideal_length > ++length)
+       length = ideal_length;
 
-      if (scale == MAXIMUM_SCALES)
-       scale = MAXIMUM_SCALES - 1;
-
-      length = 0;
-      for (i = MAXIMUM_SUBDIVIDE - 1; i >= 0; i--)
+      if (lower < upper)
+       {
+         start = floor (lower / subd_incr) * subd_incr;
+         end   = ceil  (upper / subd_incr) * subd_incr;
+       }
+      else
        {
-         subd_incr = (gfloat) ruler->metric->ruler_scale[scale] / (gfloat) ruler->metric->subdivide[i];
-         step_incr = subd_incr * increment;
-         if (step_incr <= MINIMUM_INCR)
-             continue;
+         start = floor (upper / subd_incr) * subd_incr;
+         end   = ceil  (lower / subd_incr) * subd_incr;
+       }
 
-         start = floor ((ruler->lower / ruler->metric->pixels_per_unit) / subd_incr) * subd_incr;
-         end = ceil ((ruler->upper / ruler->metric->pixels_per_unit) / subd_incr) * subd_incr;
+      for (cur = start; cur <= end; cur += subd_incr)
+       {
+         pos = ROUND ((cur - lower) * increment);
 
-         ideal_length = height / (i + 1) - 1;
-         if (ideal_length > ++length)
-             length = ideal_length;
+         gdk_draw_line (ruler->backing_store, gc,
+                        height + xthickness - length, pos,
+                        height + xthickness, pos);
 
-         cur = start;
-         while (cur <= end)
+         /* draw label */
+         if (i == 0)
            {
-             pos = ROUND ((cur - (ruler->lower / ruler->metric->pixels_per_unit)) * increment);
-
-             gdk_draw_line (ruler->backing_store, gc,
-                            height + xthickness - length,
-                            pos,
-                            height + xthickness,
-                            pos);
-
-             if (i == 0)
+             sprintf (unit_str, "%d", (int) cur);
+             
+             for (j = 0; j < (int) strlen (unit_str); j++)
                {
-                 sprintf (unit_str, "%d", (int) cur);
-                 for (j = 0; j < (int) strlen (unit_str); j++)
-                   {
-                     digit_str[0] = unit_str[j];
-                     gdk_draw_rectangle (ruler->backing_store,
-                                         bg_gc, TRUE,
-                                         xthickness + 1,
-                                         pos + digit_height * j + 1,
-                                         gdk_string_width(font, digit_str),
-                                         digit_height);
-                     gdk_draw_string (ruler->backing_store, font, gc,
-                                      xthickness + 1,
-                                      pos + digit_height * (j + 1) + 1,
-                                      digit_str);
-                   }
+                 pango_layout_set_text (layout, unit_str + j, 1);
+                 pango_layout_get_extents (layout, NULL, &logical_rect);
+
+      
+                  gtk_paint_layout (widget->style,
+                                    ruler->backing_store,
+                                    GTK_WIDGET_STATE (widget),
+                                   FALSE,
+                                    NULL,
+                                    widget,
+                                    "vruler",
+                                    xthickness + 1,
+                                    pos + digit_height * j + 2 + PANGO_PIXELS (logical_rect.y - digit_offset),
+                                    layout);
                }
-
-             cur += subd_incr;
            }
        }
     }
+
+  g_object_unref (G_OBJECT (layout));
 }
 
+
 static void
 gtk_vruler_draw_pos (GtkRuler *ruler)
 {
@@ -249,18 +282,15 @@ gtk_vruler_draw_pos (GtkRuler *ruler)
   gint bs_width, bs_height;
   gint xthickness;
   gint ythickness;
-  gfloat increment;
-
-  g_return_if_fail (ruler != NULL);
-  g_return_if_fail (GTK_IS_VRULER (ruler));
+  gdouble increment;
 
   if (GTK_WIDGET_DRAWABLE (ruler))
     {
       widget = GTK_WIDGET (ruler);
 
       gc = widget->style->fg_gc[GTK_STATE_NORMAL];
-      xthickness = widget->style->klass->xthickness;
-      ythickness = widget->style->klass->ythickness;
+      xthickness = widget->style->xthickness;
+      ythickness = widget->style->ythickness;
       width = widget->allocation.width - xthickness * 2;
       height = widget->allocation.height;
 
@@ -279,7 +309,7 @@ gtk_vruler_draw_pos (GtkRuler *ruler)
                             ruler->xsrc, ruler->ysrc,
                             bs_width, bs_height);
 
-         increment = (gfloat) height / (ruler->upper - ruler->lower);
+         increment = (gdouble) height / (ruler->upper - ruler->lower);
 
          x = (width + bs_width) / 2 + xthickness;
          y = ROUND ((ruler->position - ruler->lower) * increment) + (ythickness - bs_height) / 2 - 1;