]> Pileus Git - ~andy/gtk/blob - gtk/gtkvscale.c
Make it possible to specify additional modules to load via a setting.
[~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 "gtkalias.h"
32 #include "gtkvscale.h"
33 #include "gtkintl.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, "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  * Return value: a new #GtkVScale
124  **/
125 GtkWidget*
126 gtk_vscale_new_with_range (gdouble min,
127                            gdouble max,
128                            gdouble step)
129 {
130   GtkObject *adj;
131   GtkScale *scale;
132   gint digits;
133
134   g_return_val_if_fail (min < max, NULL);
135   g_return_val_if_fail (step != 0.0, NULL);
136
137   adj = gtk_adjustment_new (min, min, max, step, 10 * step, 0);
138   
139   scale = g_object_new (GTK_TYPE_VSCALE,
140                         "adjustment", adj,
141                         NULL);
142
143   if (fabs (step) >= 1.0 || step == 0.0)
144     digits = 0;
145   else {
146     digits = abs ((gint) floor (log10 (fabs (step))));
147     if (digits > 5)
148       digits = 5;
149   }
150
151   gtk_scale_set_digits (scale, digits);
152   
153   return GTK_WIDGET (scale);
154 }
155
156 static gboolean
157 gtk_vscale_expose (GtkWidget      *widget,
158                    GdkEventExpose *event)
159 {
160   GtkScale *scale;
161   
162   scale = GTK_SCALE (widget);
163   
164   /* We need to chain up _first_ so the various geometry members of
165    * GtkRange struct are updated.
166    */
167   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
168     GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
169
170   if (scale->draw_value)
171     {
172       PangoLayout *layout;
173       gint x, y;
174       GtkStateType state_type;
175
176       layout = gtk_scale_get_layout (scale);
177       gtk_scale_get_layout_offsets (scale, &x, &y);
178
179       state_type = GTK_STATE_NORMAL;
180       if (!GTK_WIDGET_IS_SENSITIVE (scale))
181         state_type = GTK_STATE_INSENSITIVE;
182
183       gtk_paint_layout (widget->style,
184                         widget->window,
185                         state_type,
186                         FALSE,
187                         NULL,
188                         widget,
189                         "vscale",
190                         x, y,
191                         layout);
192     }
193   
194   return FALSE;
195
196 }
197
198 static void
199 gtk_vscale_get_layout_offsets (GtkScale *scale,
200                                gint     *x,
201                                gint     *y)
202 {
203   GtkWidget *widget;
204   GtkRange *range;
205   PangoLayout *layout;
206   PangoRectangle logical_rect;
207   gint value_spacing;
208
209   widget = GTK_WIDGET (scale);
210   layout = gtk_scale_get_layout (scale);
211       
212   if (!layout)
213     {
214       *x = 0;
215       *y = 0;
216
217       return;
218     }
219
220   range = GTK_RANGE (widget);
221   scale = GTK_SCALE (widget);
222
223   gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
224       
225   pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
226     
227   switch (scale->value_pos)
228     {
229     case GTK_POS_LEFT:
230       *x = range->range_rect.x - logical_rect.width - value_spacing;
231       *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
232       *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
233       break;
234       
235     case GTK_POS_RIGHT:
236       *x = range->range_rect.x + range->range_rect.width + value_spacing;
237       *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
238       *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
239       break;
240           
241     case GTK_POS_TOP:
242       *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
243       *y = range->range_rect.y - logical_rect.height - value_spacing;
244       break;
245           
246     case GTK_POS_BOTTOM:
247       *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
248       *y = range->range_rect.y + range->range_rect.height + value_spacing;
249       break;
250
251     default:
252       g_return_if_reached ();
253       *x = 0;
254       *y = 0;
255       break;
256     }
257
258   *x += widget->allocation.x;
259   *y += widget->allocation.y;
260 }
261