source: trunk/third/gtk/gtk/gtkhruler.c @ 14482

Revision 14482, 8.3 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14481, which included commits to RCS files with non-trunk default branches.
RevLine 
[14481]1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include <math.h>
28#include <stdio.h>
29#include <string.h>
30#include "gtkhruler.h"
31
32
33#define RULER_HEIGHT          14
34#define MINIMUM_INCR          5
35#define MAXIMUM_SUBDIVIDE     5
36#define MAXIMUM_SCALES        10
37
38#define ROUND(x) ((int) ((x) + 0.5))
39
40
41static void gtk_hruler_class_init    (GtkHRulerClass *klass);
42static void gtk_hruler_init          (GtkHRuler      *hruler);
43static gint gtk_hruler_motion_notify (GtkWidget      *widget,
44                                      GdkEventMotion *event);
45static void gtk_hruler_draw_ticks    (GtkRuler       *ruler);
46static void gtk_hruler_draw_pos      (GtkRuler       *ruler);
47
48
49guint
50gtk_hruler_get_type (void)
51{
52  static guint hruler_type = 0;
53
54  if (!hruler_type)
55    {
56      static const GtkTypeInfo hruler_info =
57      {
58        "GtkHRuler",
59        sizeof (GtkHRuler),
60        sizeof (GtkHRulerClass),
61        (GtkClassInitFunc) gtk_hruler_class_init,
62        (GtkObjectInitFunc) gtk_hruler_init,
63        /* reserved_1 */ NULL,
64        /* reserved_2 */ NULL,
65        (GtkClassInitFunc) NULL,
66      };
67
68      hruler_type = gtk_type_unique (gtk_ruler_get_type (), &hruler_info);
69    }
70
71  return hruler_type;
72}
73
74static void
75gtk_hruler_class_init (GtkHRulerClass *klass)
76{
77  GtkWidgetClass *widget_class;
78  GtkRulerClass *ruler_class;
79
80  widget_class = (GtkWidgetClass*) klass;
81  ruler_class = (GtkRulerClass*) klass;
82
83  widget_class->motion_notify_event = gtk_hruler_motion_notify;
84
85  ruler_class->draw_ticks = gtk_hruler_draw_ticks;
86  ruler_class->draw_pos = gtk_hruler_draw_pos;
87}
88
89static void
90gtk_hruler_init (GtkHRuler *hruler)
91{
92  GtkWidget *widget;
93
94  widget = GTK_WIDGET (hruler);
95  widget->requisition.width = widget->style->klass->xthickness * 2 + 1;
96  widget->requisition.height = widget->style->klass->ythickness * 2 + RULER_HEIGHT;
97}
98
99
100GtkWidget*
101gtk_hruler_new (void)
102{
103  return GTK_WIDGET (gtk_type_new (gtk_hruler_get_type ()));
104}
105
106static gint
107gtk_hruler_motion_notify (GtkWidget      *widget,
108                          GdkEventMotion *event)
109{
110  GtkRuler *ruler;
111  gint x;
112
113  g_return_val_if_fail (widget != NULL, FALSE);
114  g_return_val_if_fail (GTK_IS_HRULER (widget), FALSE);
115  g_return_val_if_fail (event != NULL, FALSE);
116
117  ruler = GTK_RULER (widget);
118
119  if (event->is_hint)
120    gdk_window_get_pointer (widget->window, &x, NULL, NULL);
121  else
122    x = event->x;
123
124  ruler->position = ruler->lower + ((ruler->upper - ruler->lower) * x) / widget->allocation.width;
125
126  /*  Make sure the ruler has been allocated already  */
127  if (ruler->backing_store != NULL)
128    gtk_ruler_draw_pos (ruler);
129
130  return FALSE;
131}
132
133static void
134gtk_hruler_draw_ticks (GtkRuler *ruler)
135{
136  GtkWidget *widget;
137  GdkGC *gc, *bg_gc;
138  GdkFont *font;
139  gint i;
140  gint width, height;
141  gint xthickness;
142  gint ythickness;
143  gint length, ideal_length;
144  gfloat lower, upper;          /* Upper and lower limits, in ruler units */
145  gfloat increment;             /* Number of pixels per unit */
146  gint scale;                   /* Number of units per major unit */
147  gfloat subd_incr;
148  gfloat start, end, cur;
149  gchar unit_str[32];
150  gint digit_height;
151  gint text_width;
152  gint pos;
153
154  g_return_if_fail (ruler != NULL);
155  g_return_if_fail (GTK_IS_HRULER (ruler));
156
157  if (!GTK_WIDGET_DRAWABLE (ruler))
158    return;
159
160  widget = GTK_WIDGET (ruler);
161
162  gc = widget->style->fg_gc[GTK_STATE_NORMAL];
163  bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
164  font = widget->style->font;
165
166  xthickness = widget->style->klass->xthickness;
167  ythickness = widget->style->klass->ythickness;
168  digit_height = font->ascent; /* assume descent == 0 ? */
169
170  width = widget->allocation.width;
171  height = widget->allocation.height - ythickness * 2;
172
173   
174   gtk_paint_box (widget->style, ruler->backing_store,
175                  GTK_STATE_NORMAL, GTK_SHADOW_OUT,
176                  NULL, widget, "hruler",
177                  0, 0,
178                  widget->allocation.width, widget->allocation.height);
179
180
181   gdk_draw_line (ruler->backing_store, gc,
182                 xthickness,
183                 height + ythickness,
184                 widget->allocation.width - xthickness,
185                 height + ythickness);
186
187  upper = ruler->upper / ruler->metric->pixels_per_unit;
188  lower = ruler->lower / ruler->metric->pixels_per_unit;
189
190  if ((upper - lower) == 0)
191    return;
192  increment = (gfloat) width / (upper - lower);
193
194  /* determine the scale
195   *  We calculate the text size as for the vruler instead of using
196   *  text_width = gdk_string_width(font, unit_str), so that the result
197   *  for the scale looks consistent with an accompanying vruler
198   */
199  scale = ceil (ruler->max_size / ruler->metric->pixels_per_unit);
200  sprintf (unit_str, "%d", scale);
201  text_width = strlen (unit_str) * digit_height + 1;
202
203  for (scale = 0; scale < MAXIMUM_SCALES; scale++)
204    if (ruler->metric->ruler_scale[scale] * fabs(increment) > 2 * text_width)
205      break;
206
207  if (scale == MAXIMUM_SCALES)
208    scale = MAXIMUM_SCALES - 1;
209
210  /* drawing starts here */
211  length = 0;
212  for (i = MAXIMUM_SUBDIVIDE - 1; i >= 0; i--)
213    {
214      subd_incr = (gfloat) ruler->metric->ruler_scale[scale] /
215                  (gfloat) ruler->metric->subdivide[i];
216      if (subd_incr * fabs(increment) <= MINIMUM_INCR)
217        continue;
218
219      /* Calculate the length of the tickmarks. Make sure that
220       * this length increases for each set of ticks
221       */
222      ideal_length = height / (i + 1) - 1;
223      if (ideal_length > ++length)
224        length = ideal_length;
225
226      if (lower < upper)
227        {
228          start = floor (lower / subd_incr) * subd_incr;
229          end   = ceil  (upper / subd_incr) * subd_incr;
230        }
231      else
232        {
233          start = floor (upper / subd_incr) * subd_incr;
234          end   = ceil  (lower / subd_incr) * subd_incr;
235        }
236
237 
238      for (cur = start; cur <= end; cur += subd_incr)
239        {
240          pos = ROUND ((cur - lower) * increment);
241
242          gdk_draw_line (ruler->backing_store, gc,
243                         pos, height + ythickness,
244                         pos, height - length + ythickness);
245
246          /* draw label */
247          if (i == 0)
248            {
249              sprintf (unit_str, "%d", (int) cur);
250              gdk_draw_string (ruler->backing_store, font, gc,
251                               pos + 2, ythickness + font->ascent - 1,
252                               unit_str);
253            }
254        }
255    }
256}
257
258static void
259gtk_hruler_draw_pos (GtkRuler *ruler)
260{
261  GtkWidget *widget;
262  GdkGC *gc;
263  int i;
264  gint x, y;
265  gint width, height;
266  gint bs_width, bs_height;
267  gint xthickness;
268  gint ythickness;
269  gfloat increment;
270
271  g_return_if_fail (ruler != NULL);
272  g_return_if_fail (GTK_IS_HRULER (ruler));
273
274  if (GTK_WIDGET_DRAWABLE (ruler))
275    {
276      widget = GTK_WIDGET (ruler);
277
278      gc = widget->style->fg_gc[GTK_STATE_NORMAL];
279      xthickness = widget->style->klass->xthickness;
280      ythickness = widget->style->klass->ythickness;
281      width = widget->allocation.width;
282      height = widget->allocation.height - ythickness * 2;
283
284      bs_width = height / 2;
285      bs_width |= 1;  /* make sure it's odd */
286      bs_height = bs_width / 2 + 1;
287
288      if ((bs_width > 0) && (bs_height > 0))
289        {
290          /*  If a backing store exists, restore the ruler  */
291          if (ruler->backing_store && ruler->non_gr_exp_gc)
292            gdk_draw_pixmap (ruler->widget.window,
293                             ruler->non_gr_exp_gc,
294                             ruler->backing_store,
295                             ruler->xsrc, ruler->ysrc,
296                             ruler->xsrc, ruler->ysrc,
297                             bs_width, bs_height);
298
299          increment = (gfloat) width / (ruler->upper - ruler->lower);
300
301          x = ROUND ((ruler->position - ruler->lower) * increment) + (xthickness - bs_width) / 2 - 1;
302          y = (height + bs_height) / 2 + ythickness;
303
304          for (i = 0; i < bs_height; i++)
305            gdk_draw_line (widget->window, gc,
306                           x + i, y + i,
307                           x + bs_width - 1 - i, y + i);
308
309
310          ruler->xsrc = x;
311          ruler->ysrc = y;
312        }
313    }
314}
Note: See TracBrowser for help on using the repository browser.