]> Pileus Git - ~andy/gtk/blob - gtk/gtkvscale.c
Use the correct screen for getting the height. (Fix from Stephen Browne,
[~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 <math.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include "gtkvscale.h"
31 #include "gtkintl.h"
32
33 #define VALUE_SPACING 2
34
35 static gpointer parent_class;
36
37 static void     gtk_vscale_class_init       (GtkVScaleClass *klass);
38 static void     gtk_vscale_init             (GtkVScale      *vscale);
39 static gboolean gtk_vscale_expose           (GtkWidget      *widget,
40                                              GdkEventExpose *event);
41
42 GType
43 gtk_vscale_get_type (void)
44 {
45   static GType vscale_type = 0;
46   
47   if (!vscale_type)
48     {
49       static const GTypeInfo vscale_info =
50       {
51         sizeof (GtkVScaleClass),
52         NULL,           /* base_init */
53         NULL,           /* base_finalize */
54         (GClassInitFunc) gtk_vscale_class_init,
55         NULL,           /* class_finalize */
56         NULL,           /* class_data */
57         sizeof (GtkVScale),
58         0,              /* n_preallocs */
59         (GInstanceInitFunc) gtk_vscale_init,
60       };
61       
62       vscale_type = g_type_register_static (GTK_TYPE_SCALE, "GtkVScale",
63                                             &vscale_info, 0);
64     }
65   
66   return vscale_type;
67 }
68
69 static void
70 gtk_vscale_class_init (GtkVScaleClass *class)
71 {
72   GtkWidgetClass *widget_class;
73   GtkRangeClass *range_class;
74   
75   widget_class = GTK_WIDGET_CLASS (class);
76   range_class = GTK_RANGE_CLASS (class); 
77
78   parent_class = g_type_class_peek_parent (class);
79
80   range_class->slider_detail = "vscale";
81   
82   widget_class->expose_event = gtk_vscale_expose;
83 }
84
85 static void
86 gtk_vscale_init (GtkVScale *vscale)
87 {
88   GtkRange *range;
89
90   range = GTK_RANGE (vscale);
91   
92   range->orientation = GTK_ORIENTATION_VERTICAL;
93 }
94
95 GtkWidget*
96 gtk_vscale_new (GtkAdjustment *adjustment)
97 {
98   return g_object_new (GTK_TYPE_VSCALE, "adjustment", adjustment, NULL);
99 }
100
101
102 /**
103  * gtk_vscale_new_with_range:
104  * @min: minimum value
105  * @max: maximum value
106  * @step: step increment (tick size) used with keyboard shortcuts
107  * 
108  * Creates a new vertical scale widget that lets the user input a
109  * number between @min and @max (including @min and @max) with the
110  * increment @step.  @step must be nonzero; it's the distance the
111  * slider moves when using the arrow keys to adjust the scale value.
112  * 
113  * Return value: a new #GtkVScale
114  **/
115 GtkWidget*
116 gtk_vscale_new_with_range (gdouble min,
117                            gdouble max,
118                            gdouble step)
119 {
120   GtkObject *adj;
121   GtkScale *scale;
122   gint digits;
123
124   g_return_val_if_fail (min < max, NULL);
125   g_return_val_if_fail (step != 0.0, NULL);
126
127   adj = gtk_adjustment_new (min, min, max, step, 10 * step, 0);
128   
129   scale = g_object_new (GTK_TYPE_VSCALE,
130                         "adjustment", adj,
131                         NULL);
132
133   if (fabs (step) >= 1.0 || step == 0.0)
134     digits = 0;
135   else {
136     digits = abs ((gint) floor (log10 (fabs (step))));
137     if (digits > 5)
138       digits = 5;
139   }
140
141   gtk_scale_set_digits (scale, digits);
142   
143   return GTK_WIDGET (scale);
144 }
145
146 static gboolean
147 gtk_vscale_expose (GtkWidget      *widget,
148                    GdkEventExpose *event)
149 {
150   GtkRange *range;
151   GtkVScale *vscale;
152   GtkScale *scale;
153   
154   range = GTK_RANGE (widget);
155   scale = GTK_SCALE (widget);
156   vscale = GTK_VSCALE (widget);
157   
158   /* We need to chain up _first_ so the various geometry members of
159    * GtkRange struct are updated.
160    */
161   if (GTK_WIDGET_CLASS (parent_class)->expose_event)
162     GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
163
164   if (scale->draw_value)
165     {
166       PangoLayout *layout;
167       PangoRectangle logical_rect;
168       gchar *txt;
169       gint x, y;
170       GtkStateType state_type;
171       gint value_spacing;
172
173       gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
174       
175       txt = _gtk_scale_format_value (scale,
176                                      GTK_RANGE (scale)->adjustment->value);
177       
178       layout = gtk_widget_create_pango_layout (widget, txt);
179       g_free (txt);
180       
181       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
182       
183       switch (scale->value_pos)
184         {
185         case GTK_POS_LEFT:
186           x = range->range_rect.x - logical_rect.width - value_spacing;
187           y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
188           y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
189           break;
190           
191         case GTK_POS_RIGHT:
192           x = range->range_rect.x + range->range_rect.width + value_spacing;
193           y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
194           y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
195           break;
196           
197         case GTK_POS_TOP:
198           x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
199           y = range->range_rect.y - logical_rect.height - value_spacing;
200           break;
201           
202         case GTK_POS_BOTTOM:
203           x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
204           y = range->range_rect.y + range->range_rect.height + value_spacing;
205           break;
206
207         default:
208           g_return_val_if_reached (FALSE);
209           x = 0;
210           y = 0;
211           break;
212         }
213       
214       x += widget->allocation.x;
215       y += widget->allocation.y;
216       
217       state_type = GTK_STATE_NORMAL;
218       if (!GTK_WIDGET_IS_SENSITIVE (scale))
219         state_type = GTK_STATE_INSENSITIVE;
220
221       gtk_paint_layout (widget->style,
222                         widget->window,
223                         state_type,
224                         FALSE,
225                         NULL,
226                         widget,
227                         "vscale",
228                         x, y,
229                         layout);
230
231       g_object_unref (layout);
232     }
233   
234   return FALSE;
235 }