]> Pileus Git - ~andy/gtk/blob - gtk/gtkscale.c
deaebeccaad57f4aacb0ca9376f2dd6b94238d1d
[~andy/gtk] / gtk / gtkscale.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
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  * Library General Public License for more details.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include <math.h>
28 #include "gtkcontainer.h"
29 #include "gtkscale.h"
30
31
32 #define SCALE_CLASS(w)  GTK_SCALE_CLASS (GTK_OBJECT (w)->klass)
33
34 enum {
35   ARG_0,
36   ARG_DIGITS,
37   ARG_DRAW_VALUE,
38   ARG_VALUE_POS
39 };
40
41
42 static void gtk_scale_class_init      (GtkScaleClass *klass);
43 static void gtk_scale_init            (GtkScale      *scale);
44 static void gtk_scale_set_arg         (GtkObject     *object,
45                                        GtkArg        *arg,
46                                        guint          arg_id);
47 static void gtk_scale_get_arg         (GtkObject     *object,
48                                        GtkArg        *arg,
49                                        guint          arg_id);
50 static void gtk_scale_map             (GtkWidget     *widget);
51 static void gtk_scale_unmap           (GtkWidget     *widget);
52
53 static void gtk_scale_draw_background (GtkRange      *range);
54
55
56 static GtkRangeClass *parent_class = NULL;
57
58
59 GtkType
60 gtk_scale_get_type (void)
61 {
62   static GtkType scale_type = 0;
63
64   if (!scale_type)
65     {
66       static const GtkTypeInfo scale_info =
67       {
68         "GtkScale",
69         sizeof (GtkScale),
70         sizeof (GtkScaleClass),
71         (GtkClassInitFunc) gtk_scale_class_init,
72         (GtkObjectInitFunc) gtk_scale_init,
73         /* reserved_1 */ NULL,
74         /* reserved_2 */ NULL,
75         (GtkClassInitFunc) NULL,
76       };
77
78       scale_type = gtk_type_unique (GTK_TYPE_RANGE, &scale_info);
79     }
80
81   return scale_type;
82 }
83
84 static void
85 gtk_scale_class_init (GtkScaleClass *class)
86 {
87   GtkObjectClass *object_class;
88   GtkWidgetClass *widget_class;
89   GtkRangeClass *range_class;
90
91   object_class = (GtkObjectClass*) class;
92   range_class = (GtkRangeClass*) class;
93   widget_class = (GtkWidgetClass*) class;
94   
95   parent_class = gtk_type_class (GTK_TYPE_RANGE);
96   
97   gtk_object_add_arg_type ("GtkScale::digits",
98                            GTK_TYPE_INT,
99                            GTK_ARG_READWRITE,
100                            ARG_DIGITS);
101   gtk_object_add_arg_type ("GtkScale::draw_value",
102                            GTK_TYPE_BOOL,
103                            GTK_ARG_READWRITE,
104                            ARG_DRAW_VALUE);
105   gtk_object_add_arg_type ("GtkScale::value_pos",
106                            GTK_TYPE_POSITION_TYPE,
107                            GTK_ARG_READWRITE,
108                            ARG_VALUE_POS);
109
110   object_class->set_arg = gtk_scale_set_arg;
111   object_class->get_arg = gtk_scale_get_arg;
112
113   widget_class->map = gtk_scale_map;
114   widget_class->unmap = gtk_scale_unmap;
115   
116   range_class->draw_background = gtk_scale_draw_background;
117
118   class->slider_length = 31;
119   class->value_spacing = 2;
120   class->draw_value = NULL;
121 }
122
123 static void
124 gtk_scale_set_arg (GtkObject      *object,
125                    GtkArg         *arg,
126                    guint           arg_id)
127 {
128   GtkScale *scale;
129
130   scale = GTK_SCALE (object);
131
132   switch (arg_id)
133     {
134     case ARG_DIGITS:
135       gtk_scale_set_digits (scale, GTK_VALUE_INT (*arg));
136       break;
137     case ARG_DRAW_VALUE:
138       gtk_scale_set_draw_value (scale, GTK_VALUE_BOOL (*arg));
139       break;
140     case ARG_VALUE_POS:
141       gtk_scale_set_value_pos (scale, GTK_VALUE_ENUM (*arg));
142       break;
143     default:
144       break;
145     }
146 }
147
148 static void
149 gtk_scale_get_arg (GtkObject      *object,
150                    GtkArg         *arg,
151                    guint           arg_id)
152 {
153   GtkScale *scale;
154
155   scale = GTK_SCALE (object);
156
157   switch (arg_id)
158     {
159     case ARG_DIGITS:
160       GTK_VALUE_INT (*arg) = GTK_RANGE (scale)->digits;
161       break;
162     case ARG_DRAW_VALUE:
163       GTK_VALUE_BOOL (*arg) = scale->draw_value;
164       break;
165     case ARG_VALUE_POS:
166       GTK_VALUE_ENUM (*arg) = scale->value_pos;
167       break;
168     default:
169       arg->type = GTK_TYPE_INVALID;
170       break;
171     }
172 }
173
174 static void
175 gtk_scale_init (GtkScale *scale)
176 {
177   GTK_WIDGET_SET_FLAGS (scale, GTK_CAN_FOCUS);
178   GTK_WIDGET_SET_FLAGS (scale, GTK_NO_WINDOW);
179   GTK_RANGE (scale)->digits = 1;
180   scale->draw_value = TRUE;
181   scale->value_pos = GTK_POS_TOP;
182 }
183
184 static void
185 gtk_scale_map (GtkWidget *widget)
186 {
187   GtkRange *range;
188
189   g_return_if_fail (widget != NULL);
190   g_return_if_fail (GTK_IS_SCALE (widget));
191
192   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
193   range = GTK_RANGE (widget);
194
195   gdk_window_show (range->trough);
196 }
197
198 static void
199 gtk_scale_unmap (GtkWidget *widget)
200 {
201   GtkRange *range;
202
203   g_return_if_fail (widget != NULL);
204   g_return_if_fail (GTK_IS_SCALE (widget));
205
206   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
207   range = GTK_RANGE (widget);
208
209   if (GTK_WIDGET_NO_WINDOW (widget))
210      gtk_widget_queue_clear (widget);
211
212   gdk_window_hide (range->trough);
213 }
214
215 void
216 gtk_scale_set_digits (GtkScale *scale,
217                       gint      digits)
218 {
219   g_return_if_fail (scale != NULL);
220   g_return_if_fail (GTK_IS_SCALE (scale));
221
222   digits = CLAMP (digits, -1, 16);
223
224   if (GTK_RANGE (scale)->digits != digits)
225     {
226       GTK_RANGE (scale)->digits = digits;
227
228       gtk_widget_queue_resize (GTK_WIDGET (scale));
229     }
230 }
231
232 void
233 gtk_scale_set_draw_value (GtkScale *scale,
234                           gboolean  draw_value)
235 {
236   g_return_if_fail (scale != NULL);
237   g_return_if_fail (GTK_IS_SCALE (scale));
238
239   draw_value = draw_value != FALSE;
240
241   if (scale->draw_value != draw_value)
242     {
243       scale->draw_value = draw_value;
244
245       gtk_widget_queue_resize (GTK_WIDGET (scale));
246     }
247 }
248
249 void
250 gtk_scale_set_value_pos (GtkScale        *scale,
251                          GtkPositionType  pos)
252 {
253   g_return_if_fail (scale != NULL);
254   g_return_if_fail (GTK_IS_SCALE (scale));
255
256   if (scale->value_pos != pos)
257     {
258       scale->value_pos = pos;
259
260       if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
261         gtk_widget_queue_resize (GTK_WIDGET (scale));
262     }
263 }
264
265 gint
266 gtk_scale_get_value_width (GtkScale *scale)
267 {
268   GtkRange *range;
269   gchar buffer[128];
270   gfloat value;
271   gint temp;
272   gint return_val;
273   gint digits;
274   gint i, j;
275
276   g_return_val_if_fail (scale != NULL, 0);
277   g_return_val_if_fail (GTK_IS_SCALE (scale), 0);
278
279   return_val = 0;
280   if (scale->draw_value)
281     {
282       range = GTK_RANGE (scale);
283
284       value = ABS (range->adjustment->lower);
285       if (value == 0) value = 1;
286       digits = log10 (value) + 1;
287       if (digits > 13)
288         digits = 13;
289
290       i = 0;
291       if (range->adjustment->lower < 0)
292         buffer[i++] = '-';
293       for (j = 0; j < digits; j++)
294         buffer[i++] = '0';
295       if (GTK_RANGE (scale)->digits)
296         buffer[i++] = '.';
297       for (j = 0; j < GTK_RANGE (scale)->digits; j++)
298         buffer[i++] = '0';
299       buffer[i] = '\0';
300
301       return_val = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
302
303       value = ABS (range->adjustment->upper);
304       if (value == 0) value = 1;
305       digits = log10 (value) + 1;
306       if (digits > 13)
307         digits = 13;
308
309       i = 0;
310       if (range->adjustment->lower < 0)
311         buffer[i++] = '-';
312       for (j = 0; j < digits; j++)
313         buffer[i++] = '0';
314       if (GTK_RANGE (scale)->digits)
315         buffer[i++] = '.';
316       for (j = 0; j < GTK_RANGE (scale)->digits; j++)
317         buffer[i++] = '0';
318       buffer[i] = '\0';
319
320       temp = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
321       return_val = MAX (return_val, temp);
322     }
323
324   return return_val;
325 }
326
327 void
328 gtk_scale_draw_value (GtkScale *scale)
329 {
330   g_return_if_fail (scale != NULL);
331   g_return_if_fail (GTK_IS_SCALE (scale));
332
333   if (SCALE_CLASS (scale)->draw_value)
334     (* SCALE_CLASS (scale)->draw_value) (scale);
335 }
336
337
338 static void
339 gtk_scale_draw_background (GtkRange *range)
340 {
341   g_return_if_fail (range != NULL);
342   g_return_if_fail (GTK_IS_SCALE (range));
343
344   gtk_scale_draw_value (GTK_SCALE (range));
345 }