aaeb0fd639e2ac202fcc77041cd4a1ba1e41046e
[claws.git] / src / gtk / gtkshruler.c
1 /* GtkSHRuler
2  *
3  *  Copyright (C) 2000-2011 Alfons Hoogervorst & The Claws Mail Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 3 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17  */
18  
19 /* I derived this class from hruler. S in HRuler could be read as
20  * Sylpheed (sylpheed.good-day.net), but also [S]ettable HRuler.
21  * I basically ripped apart the draw_ticks member of HRuler; it
22  * now draws the ticks at ruler->max_size. so gtk_ruler_set_range's
23  * last parameter has the distance between two ticks (which is
24  * the width of the fixed font character!
25  * 
26  * -- Alfons
27  */
28
29 #include <math.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <gtk/gtk.h>
33 #include "gtkshruler.h"
34 #include "utils.h"
35 #include "gtkutils.h"
36
37 #if !GTK_CHECK_VERSION(2,24,0)
38
39 #define RULER_HEIGHT          14
40 #define MINIMUM_INCR          5
41 #define MAXIMUM_SUBDIVIDE     5
42 #define MAXIMUM_SCALES        10
43
44 #define ROUND(x) ((int) ((x) + 0.5))
45
46 static void gtk_shruler_class_init      (GtkSHRulerClass *klass);
47 static void gtk_shruler_init            (GtkSHRuler      *hruler);
48 static void gtk_shruler_draw_ticks      (GtkRuler        *ruler);
49
50 GType
51 gtk_shruler_get_type(void)
52 {
53         static GType shruler_type = 0;
54
55         if ( !shruler_type ) {
56                 static const GTypeInfo shruler_info = {
57                         sizeof (GtkSHRulerClass),
58
59                         (GBaseInitFunc) NULL,
60                         (GBaseFinalizeFunc) NULL,
61
62                         (GClassInitFunc) gtk_shruler_class_init,
63                         (GClassFinalizeFunc) NULL,
64                         NULL,   /* class_data */
65
66                         sizeof (GtkSHRuler),
67                         0,      /* n_preallocs */
68                         (GInstanceInitFunc) gtk_shruler_init,
69                 };
70                 /* inherit from GtkHRuler */
71                 shruler_type = g_type_register_static (GTK_TYPE_HRULER, "GtkSHRuler", &shruler_info, (GTypeFlags)0);
72         }
73         return shruler_type;
74 }
75
76 static void
77 gtk_shruler_class_init(GtkSHRulerClass * klass)
78 {
79         GtkWidgetClass * widget_class;
80         GtkRulerClass * hruler_class;
81
82         widget_class = GTK_WIDGET_CLASS(klass);
83         hruler_class = GTK_RULER_CLASS(klass);
84
85         /* just neglect motion notify events */
86         widget_class->motion_notify_event = NULL /* gtk_shruler_motion_notify */;
87
88         /* we want the old ruler draw ticks... */
89         /* ruler_class->draw_ticks = gtk_hruler_draw_ticks; */
90         hruler_class->draw_ticks = gtk_shruler_draw_ticks;
91         
92         /* unimplemented draw pos */
93         hruler_class->draw_pos = NULL;
94 /*
95         hruler_class->draw_pos = gtk_shruler_draw_pos;
96 */
97 }
98
99 static void
100 gtk_shruler_init (GtkSHRuler * shruler)
101 {
102         GtkWidget * widget;
103         
104         widget = GTK_WIDGET (shruler);
105         widget->requisition.width = widget->style->xthickness * 2 + 1;
106         widget->requisition.height = widget->style->ythickness * 2 + RULER_HEIGHT;
107 }
108
109
110 GtkWidget*
111 gtk_shruler_new(void)
112 {
113         return GTK_WIDGET( g_object_new( gtk_shruler_get_type(), NULL ) );
114 }
115
116 static void
117 gtk_shruler_draw_ticks(GtkRuler *ruler)
118 {
119         GtkWidget *widget;
120         cairo_t *cr;
121         gint i;
122         gint width, height;
123         gint xthickness;
124         gint ythickness;
125         gint pos;
126
127         cm_return_if_fail (ruler != NULL);
128         cm_return_if_fail (GTK_IS_HRULER (ruler));
129
130         if (!gtkut_widget_is_drawable (GTK_WIDGET(ruler))) 
131                 return;
132
133         widget = GTK_WIDGET (ruler);
134         
135         cr = gdk_cairo_create(ruler->backing_store);
136         cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
137         cairo_set_line_width(cr, 1.);
138         gdk_cairo_set_source_color(cr, &gtk_widget_get_style(widget)->text[GTK_STATE_NORMAL]);
139
140         xthickness = widget->style->xthickness;
141         ythickness = widget->style->ythickness;
142
143         width = widget->allocation.width;
144         height = widget->allocation.height - ythickness * 2;
145   
146         gtk_paint_box (widget->style, ruler->backing_store,
147                        GTK_STATE_NORMAL, GTK_SHADOW_OUT, 
148                        NULL, widget, "hruler",
149                        0, 0, 
150                        widget->allocation.width, widget->allocation.height);
151
152         /* assume ruler->max_size has the char width */
153         /* i is increment of char_width,  pos is label number
154          * y position is based on height of widget itself */
155         for ( i = 0, pos = 0; i < widget->allocation.width - xthickness; i += ruler->max_size, pos++ ) {        
156                 gint length = height / 8;
157         
158                 if ( pos % 10 == 0 ) length = ( 2 * height / 3 );
159                 else if ( pos % 5 == 0 ) length = ( height / 3 );
160                 
161                 cairo_move_to(cr, i, height + ythickness);
162                 cairo_line_to(cr, i, height - length);
163                 cairo_stroke(cr);
164                 
165                 if ( pos % 10 == 0 ) {
166                         gchar buf[8];
167                         PangoLayout *layout;
168
169                         /* draw label */
170                         g_snprintf(buf, sizeof buf, "%d", pos);
171
172                         layout = gtk_widget_create_pango_layout
173                                 (GTK_WIDGET(ruler), buf);
174
175                         cairo_move_to(cr, i+2, 0);
176                         pango_cairo_show_layout(cr, layout);
177
178                         g_object_unref(layout);
179                 }
180         }
181
182         cairo_destroy(cr);
183 }
184 #endif