1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
27 /* modified by andreas meyer <hexx3000@gmx.de> */
28 /* subsequently specialized for audio time displays by paul davis <paul@linuxaudiosystems.com> */
33 #include "gtk-custom-hruler.h"
35 #define RULER_HEIGHT 14
36 #define MINIMUM_INCR 5
37 #define MAXIMUM_SUBDIVIDE 5
39 #define ROUND(x) ((int) ((x) + 0.5))
41 static void gtk_custom_hruler_class_init (GtkCustomHRulerClass
* klass
);
42 static void gtk_custom_hruler_init (GtkCustomHRuler
* custom_hruler
);
43 static gint
gtk_custom_hruler_motion_notify (GtkWidget
* widget
, GdkEventMotion
* event
);
44 static void gtk_custom_hruler_draw_ticks (GtkCustomRuler
* ruler
);
45 static void gtk_custom_hruler_draw_pos (GtkCustomRuler
* ruler
);
47 GType
gtk_custom_hruler_get_type (void)
49 static GType hruler_type
= 0;
52 static const GTypeInfo hruler_info
=
54 sizeof (GtkCustomHRulerClass
),
56 NULL
, /* base_finalize */
57 (GClassInitFunc
) gtk_custom_hruler_class_init
,
58 NULL
, /* class_finalize */
59 NULL
, /* class_data */
60 sizeof (GtkCustomHRuler
),
62 (GInstanceInitFunc
) gtk_custom_hruler_init
,
63 NULL
/* value_table */
66 hruler_type
= g_type_register_static (gtk_custom_ruler_get_type(), "GtkCustomHRuler",
74 gtk_custom_hruler_class_init (GtkCustomHRulerClass
* klass
)
76 GtkWidgetClass
*widget_class
;
77 GtkCustomRulerClass
*ruler_class
;
79 widget_class
= (GtkWidgetClass
*) klass
;
80 ruler_class
= (GtkCustomRulerClass
*) klass
;
82 widget_class
->motion_notify_event
= gtk_custom_hruler_motion_notify
;
84 ruler_class
->draw_ticks
= gtk_custom_hruler_draw_ticks
;
85 ruler_class
->draw_pos
= gtk_custom_hruler_draw_pos
;
89 gtk_custom_hruler_init (GtkCustomHRuler
* custom_hruler
)
93 widget
= GTK_WIDGET (custom_hruler
);
94 widget
->requisition
.width
= widget
->style
->xthickness
* 2 + 1;
95 widget
->requisition
.height
= widget
->style
->ythickness
* 2 + RULER_HEIGHT
;
100 gtk_custom_hruler_new (void)
102 return GTK_WIDGET (gtk_type_new (gtk_custom_hruler_get_type ()));
106 gtk_custom_hruler_motion_notify (GtkWidget
* widget
, GdkEventMotion
* event
)
108 GtkCustomRuler
*ruler
;
111 g_return_val_if_fail (widget
!= NULL
, FALSE
);
112 g_return_val_if_fail (GTK_IS_CUSTOM_HRULER (widget
), FALSE
);
113 g_return_val_if_fail (event
!= NULL
, FALSE
);
115 ruler
= GTK_CUSTOM_RULER (widget
);
118 gdk_window_get_pointer (widget
->window
, &x
, NULL
, NULL
);
122 ruler
->position
= ruler
->lower
+ ((ruler
->upper
- ruler
->lower
) * x
) / widget
->allocation
.width
;
124 /* Make sure the ruler has been allocated already */
125 if (ruler
->backing_store
!= NULL
)
126 gtk_custom_ruler_draw_pos (ruler
);
132 gtk_custom_hruler_draw_ticks (GtkCustomRuler
* ruler
)
137 GtkCustomRulerMark
*marks
;
144 PangoRectangle logical_rect
, ink_rect
;
146 g_return_if_fail (ruler
!= NULL
);
147 g_return_if_fail (GTK_IS_CUSTOM_HRULER (ruler
));
149 if (!GTK_WIDGET_DRAWABLE (ruler
))
152 widget
= GTK_WIDGET (ruler
);
154 gc
= widget
->style
->fg_gc
[GTK_STATE_NORMAL
];
155 bg_gc
= widget
->style
->bg_gc
[GTK_STATE_NORMAL
];
157 layout
= gtk_widget_create_pango_layout (widget
, "012456789");
158 pango_layout_get_extents (layout
, &ink_rect
, &logical_rect
);
160 digit_offset
= ink_rect
.y
;
162 xthickness
= widget
->style
->xthickness
;
163 ythickness
= widget
->style
->ythickness
;
165 gtk_paint_box (widget
->style
, ruler
->backing_store
,
166 GTK_STATE_NORMAL
, GTK_SHADOW_NONE
,
167 NULL
, widget
, "custom_hruler", 0, 0, widget
->allocation
.width
, widget
->allocation
.height
);
169 gdk_draw_line (ruler
->backing_store
, gc
, 0, widget
->allocation
.height
- 1,
170 widget
->allocation
.width
, widget
->allocation
.height
- 1);
172 if ((ruler
->upper
- ruler
->lower
) == 0) {
176 /* we have to assume a fixed width font here */
178 max_chars
= widget
->allocation
.width
/ 12; // XXX FIX ME: pixel with of the char `8'
180 nmarks
= ruler
->metric
->get_marks (&marks
, ruler
->lower
, ruler
->upper
, max_chars
);
182 for (i
= 0; i
< nmarks
; i
++) {
186 pos
= ROUND ((marks
[i
].position
- ruler
->lower
) / ruler
->metric
->units_per_pixel
);
187 height
= widget
->allocation
.height
;
189 switch (marks
[i
].style
) {
190 case GtkCustomRulerMarkMajor
:
191 gdk_draw_line (ruler
->backing_store
, gc
, pos
, height
, pos
, 0);
193 case GtkCustomRulerMarkMinor
:
194 gdk_draw_line (ruler
->backing_store
, gc
, pos
, height
, pos
, height
- (height
/2));
196 case GtkCustomRulerMarkMicro
:
197 gdk_draw_line (ruler
->backing_store
, gc
, pos
, height
, pos
, height
- 3);
201 pango_layout_set_text (layout
, marks
[i
].label
, -1);
202 pango_layout_get_extents (layout
, &logical_rect
, NULL
);
204 gtk_paint_layout (widget
->style
,
205 ruler
->backing_store
,
206 GTK_WIDGET_STATE (widget
),
211 pos
+ 2, ythickness
+ PANGO_PIXELS (logical_rect
.y
- digit_offset
),
214 g_free (marks
[i
].label
);
221 g_object_unref (layout
);
225 gtk_custom_hruler_draw_pos (GtkCustomRuler
* ruler
)
232 gint bs_width
, bs_height
;
237 g_return_if_fail (ruler
!= NULL
);
238 g_return_if_fail (GTK_IS_CUSTOM_HRULER (ruler
));
239 if (GTK_WIDGET_DRAWABLE (ruler
) && (ruler
->upper
- ruler
->lower
) > 0) {
240 widget
= GTK_WIDGET (ruler
);
241 gc
= widget
->style
->fg_gc
[GTK_STATE_NORMAL
];
242 xthickness
= widget
->style
->xthickness
;
243 ythickness
= widget
->style
->ythickness
;
244 width
= widget
->allocation
.width
;
245 height
= widget
->allocation
.height
- ythickness
* 2;
247 bs_width
= height
/ 2;
248 bs_width
|= 1; /* make sure it's odd */
249 bs_height
= bs_width
/ 2 + 1;
251 if ((bs_width
> 0) && (bs_height
> 0)) {
252 /* If a backing store exists, restore the ruler */
253 if (ruler
->backing_store
&& ruler
->non_gr_exp_gc
)
254 gdk_draw_pixmap (ruler
->widget
.window
,
255 ruler
->non_gr_exp_gc
,
256 ruler
->backing_store
, ruler
->xsrc
, ruler
->ysrc
, ruler
->xsrc
, ruler
->ysrc
, bs_width
, bs_height
);
258 increment
= (gfloat
) width
/ (ruler
->upper
- ruler
->lower
);
259 x
= ROUND ((ruler
->position
- ruler
->lower
) * increment
) + (xthickness
- bs_width
) / 2 - 1;
260 y
= (height
+ bs_height
) / 2 + ythickness
;
262 for (i
= 0; i
< bs_height
; i
++)
263 gdk_draw_line (widget
->window
, gc
, x
+ i
, y
+ i
, x
+ bs_width
- 1 - i
, y
+ i
);