]> Pileus Git - ~andy/gtk/blob - gtk/gtkvscale.c
Intern some more strings.
[~andy/gtk] / gtk / gtkvscale.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2001 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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-2000.  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 <config.h>
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include "gtkvscale.h"
32 #include "gtkintl.h"
33 #include "gtkalias.h"
34
35 #define VALUE_SPACING 2
36
37 static gpointer parent_class;
38
39 static void     gtk_vscale_class_init       (GtkVScaleClass *klass);
40 static void     gtk_vscale_init             (GtkVScale      *vscale);
41 static gboolean gtk_vscale_expose           (GtkWidget      *widget,
42                                              GdkEventExpose *event);
43
44 static void     gtk_vscale_get_layout_offsets (GtkScale         *scale,
45                                                gint             *x,
46                                                gint             *y);
47
48 GType
49 gtk_vscale_get_type (void)
50 {
51   static GType vscale_type = 0;
52   
53   if (!vscale_type)
54     {
55       static const GTypeInfo vscale_info =
56       {
57         sizeof (GtkVScaleClass),
58         NULL,           /* base_init */
59         NULL,           /* base_finalize */
60         (GClassInitFunc) gtk_vscale_class_init,
61         NULL,           /* class_finalize */
62         NULL,           /* class_data */
63         sizeof (GtkVScale),
64         0,              /* n_preallocs */
65         (GInstanceInitFunc) gtk_vscale_init,
66       };
67       
68       vscale_type = g_type_register_static (GTK_TYPE_SCALE, I_("GtkVScale"),
69                                             &vscale_info, 0);
70     }
71   
72   return vscale_type;
73 }
74
75 static void
76 gtk_vscale_class_init (GtkVScaleClass *class)
77 {
78   GtkWidgetClass *widget_class;
79   GtkRangeClass *range_class;
80   GtkScaleClass *scale_class;
81   
82   widget_class = GTK_WIDGET_CLASS (class);
83   range_class = GTK_RANGE_CLASS (class); 
84   scale_class = GTK_SCALE_CLASS (class); 
85
86   parent_class = g_type_class_peek_parent (class);
87
88   range_class->slider_detail = "vscale";
89   
90   scale_class->get_layout_offsets = gtk_vscale_get_layout_offsets;
91
92   widget_class->expose_event = gtk_vscale_expose;
93 }
94
95 static void
96 gtk_vscale_init (GtkVScale *vscale)
97 {
98   GtkRange *range;
99
100   range = GTK_RANGE (vscale);
101   
102   range->orientation = GTK_ORIENTATION_VERTICAL;
103 }
104
105 GtkWidget*
106 gtk_vscale_new (GtkAdjustment *adjustment)
107 {
108   return g_object_new (GTK_TYPE_VSCALE, "adjustment", adjustment, NULL);
109 }
110
111
112 /**
113  * gtk_vscale_new_with_range:
114  * @min: minimum value
115  * @max: maximum value
116  * @step: step increment (tick size) used with keyboard shortcuts
117  * 
118  * Creates a new vertical scale widget that lets the user input a
119  * number between @min and @max (including @min and @max) with the
120  * increment @step.  @step must be nonzero; it's the distance the
121  * slider moves when using the arrow keys to adjust the scale value.
122  * 
123  * Note that the way in which the precision is derived works best if @step 
124  * is a power of ten. If the resulting precision is not suitable for your 
125  * needs, use gtk_scale_set_digits() to correct it. 
126  * 
127  * Return value: a new #GtkVScale
128  **/
129 GtkWidget*
130 gtk_vscale_new_with_range (gdouble min,
131                            gdouble max,
132                            gdouble step)
133 {
134   GtkObject *adj;
135   GtkScale *scale;
136   gint digits;
137
138   g_return_val_if_fail (min < max, NULL);
139   g_return_val_if_fail (step != 0.0, NULL);
140
141   adj = gtk_adjustment_new (min, min, max, step, 10 * step, 0);
142   
143   scale = g_object_new (GTK_TYPE_VSCALE,
144                         "adjustment", adj,
145                         NULL);
146
147   if (fabs (step) >= 1.0 || step == 0.0)
148     digits = 0;
149   else {
150     digits = abs ((gint) floor (log10 (fabs (step))));
151     if (digits > 5)
152       digits = 5;
153   }
154
155   gtk_scale_set_digits (scale, digits);
156   
157   return GTK_WIDGET (scale);
158 }
159
160 static gboolean
161 gtk_vscale_expose (GtkWidget      *widget,
162                    GdkEventExpose *event)
163 {
164   GtkScale *scale;
165   
166   scale = GTK_SCALE (widget);
167   
168   /* We need to chain up _first_ so the various geometry members of
169    * GtkRange struct are updated.
170    */
171   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
172     GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
173
174   if (scale->draw_value)
175     {
176       PangoLayout *layout;
177       gint x, y;
178       GtkStateType state_type;
179
180       layout = gtk_scale_get_layout (scale);
181       gtk_scale_get_layout_offsets (scale, &x, &y);
182
183       state_type = GTK_STATE_NORMAL;
184       if (!GTK_WIDGET_IS_SENSITIVE (scale))
185         state_type = GTK_STATE_INSENSITIVE;
186
187       gtk_paint_layout (widget->style,
188                         widget->window,
189                         state_type,
190                         FALSE,
191                         NULL,
192                         widget,
193                         "vscale",
194                         x, y,
195                         layout);
196     }
197   
198   return FALSE;
199
200 }
201
202 static void
203 gtk_vscale_get_layout_offsets (GtkScale *scale,
204                                gint     *x,
205                                gint     *y)
206 {
207   GtkWidget *widget;
208   GtkRange *range;
209   PangoLayout *layout;
210   PangoRectangle logical_rect;
211   gint value_spacing;
212
213   widget = GTK_WIDGET (scale);
214   layout = gtk_scale_get_layout (scale);
215       
216   if (!layout)
217     {
218       *x = 0;
219       *y = 0;
220
221       return;
222     }
223
224   range = GTK_RANGE (widget);
225   scale = GTK_SCALE (widget);
226
227   gtk_widget_style_get (widget, "value-spacing", &value_spacing, NULL);
228       
229   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
230     
231   switch (scale->value_pos)
232     {
233     case GTK_POS_LEFT:
234       *x = range->range_rect.x - logical_rect.width - value_spacing;
235       *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
236       *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
237       break;
238       
239     case GTK_POS_RIGHT:
240       *x = range->range_rect.x + range->range_rect.width + value_spacing;
241       *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
242       *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
243       break;
244           
245     case GTK_POS_TOP:
246       *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
247       *y = range->range_rect.y - logical_rect.height - value_spacing;
248       break;
249           
250     case GTK_POS_BOTTOM:
251       *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
252       *y = range->range_rect.y + range->range_rect.height + value_spacing;
253       break;
254
255     default:
256       g_return_if_reached ();
257       *x = 0;
258       *y = 0;
259       break;
260     }
261
262   *x += widget->allocation.x;
263   *y += widget->allocation.y;
264 }
265
266 #define __GTK_VSCALE_C__
267 #include "gtkaliasdef.c"