]> Pileus Git - ~andy/gtk/blob - gtk/gtkscale.c
fix some shell typos
[~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 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 "gtkintl.h"
29 #include "gtkscale.h"
30 #include "gtkmarshal.h"
31
32 enum {
33   ARG_0,
34   ARG_DIGITS,
35   ARG_DRAW_VALUE,
36   ARG_VALUE_POS
37 };
38
39 enum {
40   FORMAT_VALUE,
41   LAST_SIGNAL
42 };
43
44 static guint signals[LAST_SIGNAL];
45
46 static void gtk_scale_class_init      (GtkScaleClass *klass);
47 static void gtk_scale_init            (GtkScale      *scale);
48 static void gtk_scale_set_arg         (GtkObject     *object,
49                                        GtkArg        *arg,
50                                        guint          arg_id);
51 static void gtk_scale_get_arg         (GtkObject     *object,
52                                        GtkArg        *arg,
53                                        guint          arg_id);
54 static void gtk_scale_map             (GtkWidget     *widget);
55 static void gtk_scale_unmap           (GtkWidget     *widget);
56
57 static void gtk_scale_draw_background (GtkRange      *range);
58
59
60 static GtkRangeClass *parent_class = NULL;
61
62
63 GtkType
64 gtk_scale_get_type (void)
65 {
66   static GtkType scale_type = 0;
67
68   if (!scale_type)
69     {
70       static const GtkTypeInfo scale_info =
71       {
72         "GtkScale",
73         sizeof (GtkScale),
74         sizeof (GtkScaleClass),
75         (GtkClassInitFunc) gtk_scale_class_init,
76         (GtkObjectInitFunc) gtk_scale_init,
77         /* reserved_1 */ NULL,
78         /* reserved_2 */ NULL,
79         (GtkClassInitFunc) NULL,
80       };
81
82       scale_type = gtk_type_unique (GTK_TYPE_RANGE, &scale_info);
83     }
84
85   return scale_type;
86 }
87
88 gboolean
89 single_string_accumulator (GSignalInvocationHint *ihint,
90                            GValue                *return_accu,
91                            const GValue          *handler_return,
92                            gpointer               dummy)
93 {
94   gboolean continue_emission;
95   gchar *str;
96   
97   str = g_value_get_string (handler_return);
98   g_value_set_string (return_accu, str);
99   continue_emission = str == NULL;
100   
101   return continue_emission;
102 }
103
104 static void
105 gtk_scale_class_init (GtkScaleClass *class)
106 {
107   GtkObjectClass *object_class;
108   GtkWidgetClass *widget_class;
109   GtkRangeClass *range_class;
110
111   object_class = (GtkObjectClass*) class;
112   range_class = (GtkRangeClass*) class;
113   widget_class = (GtkWidgetClass*) class;
114   
115   parent_class = gtk_type_class (GTK_TYPE_RANGE);
116   
117   gtk_object_add_arg_type ("GtkScale::digits",
118                            GTK_TYPE_INT,
119                            GTK_ARG_READWRITE,
120                            ARG_DIGITS);
121   gtk_object_add_arg_type ("GtkScale::draw_value",
122                            GTK_TYPE_BOOL,
123                            GTK_ARG_READWRITE,
124                            ARG_DRAW_VALUE);
125   gtk_object_add_arg_type ("GtkScale::value_pos",
126                            GTK_TYPE_POSITION_TYPE,
127                            GTK_ARG_READWRITE,
128                            ARG_VALUE_POS);
129
130   signals[FORMAT_VALUE] =
131     g_signal_newc ("format_value",
132                    G_TYPE_FROM_CLASS (object_class),
133                    G_SIGNAL_RUN_LAST,
134                    G_STRUCT_OFFSET (GtkScaleClass, format_value),
135                    single_string_accumulator, NULL,
136                    gtk_marshal_STRING__DOUBLE,
137                    G_TYPE_STRING, 1,
138                    G_TYPE_DOUBLE);
139   
140   object_class->set_arg = gtk_scale_set_arg;
141   object_class->get_arg = gtk_scale_get_arg;
142
143   widget_class->map = gtk_scale_map;
144   widget_class->unmap = gtk_scale_unmap;
145   
146   range_class->draw_background = gtk_scale_draw_background;
147
148   gtk_widget_class_install_style_property (widget_class,
149                                            g_param_spec_int ("slider_length",
150                                                              _("Slider Length"),
151                                                              _("Length of scale's slider"),
152                                                              0,
153                                                              G_MAXINT,
154                                                              31,
155                                                              G_PARAM_READABLE));
156   class->value_spacing = 2;
157   class->draw_value = NULL;
158 }
159
160 static void
161 gtk_scale_set_arg (GtkObject      *object,
162                    GtkArg         *arg,
163                    guint           arg_id)
164 {
165   GtkScale *scale;
166
167   scale = GTK_SCALE (object);
168
169   switch (arg_id)
170     {
171     case ARG_DIGITS:
172       gtk_scale_set_digits (scale, GTK_VALUE_INT (*arg));
173       break;
174     case ARG_DRAW_VALUE:
175       gtk_scale_set_draw_value (scale, GTK_VALUE_BOOL (*arg));
176       break;
177     case ARG_VALUE_POS:
178       gtk_scale_set_value_pos (scale, GTK_VALUE_ENUM (*arg));
179       break;
180     default:
181       break;
182     }
183 }
184
185 static void
186 gtk_scale_get_arg (GtkObject      *object,
187                    GtkArg         *arg,
188                    guint           arg_id)
189 {
190   GtkScale *scale;
191
192   scale = GTK_SCALE (object);
193
194   switch (arg_id)
195     {
196     case ARG_DIGITS:
197       GTK_VALUE_INT (*arg) = GTK_RANGE (scale)->digits;
198       break;
199     case ARG_DRAW_VALUE:
200       GTK_VALUE_BOOL (*arg) = scale->draw_value;
201       break;
202     case ARG_VALUE_POS:
203       GTK_VALUE_ENUM (*arg) = scale->value_pos;
204       break;
205     default:
206       arg->type = GTK_TYPE_INVALID;
207       break;
208     }
209 }
210
211 static void
212 gtk_scale_init (GtkScale *scale)
213 {
214   GTK_WIDGET_SET_FLAGS (scale, GTK_CAN_FOCUS);
215   GTK_WIDGET_SET_FLAGS (scale, GTK_NO_WINDOW);
216   GTK_RANGE (scale)->digits = 1;
217   scale->draw_value = TRUE;
218   scale->value_pos = GTK_POS_TOP;
219 }
220
221 static void
222 gtk_scale_map (GtkWidget *widget)
223 {
224   GtkRange *range;
225
226   g_return_if_fail (widget != NULL);
227   g_return_if_fail (GTK_IS_SCALE (widget));
228
229   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
230   range = GTK_RANGE (widget);
231
232   gdk_window_show (range->trough);
233 }
234
235 static void
236 gtk_scale_unmap (GtkWidget *widget)
237 {
238   GtkRange *range;
239
240   g_return_if_fail (widget != NULL);
241   g_return_if_fail (GTK_IS_SCALE (widget));
242
243   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
244   range = GTK_RANGE (widget);
245
246   if (GTK_WIDGET_NO_WINDOW (widget))
247      gtk_widget_queue_clear (widget);
248
249   gdk_window_hide (range->trough);
250 }
251
252 void
253 gtk_scale_set_digits (GtkScale *scale,
254                       gint      digits)
255 {
256   g_return_if_fail (scale != NULL);
257   g_return_if_fail (GTK_IS_SCALE (scale));
258
259   digits = CLAMP (digits, -1, 16);
260
261   if (GTK_RANGE (scale)->digits != digits)
262     {
263       GTK_RANGE (scale)->digits = digits;
264
265       gtk_widget_queue_resize (GTK_WIDGET (scale));
266     }
267 }
268
269 void
270 gtk_scale_set_draw_value (GtkScale *scale,
271                           gboolean  draw_value)
272 {
273   g_return_if_fail (scale != NULL);
274   g_return_if_fail (GTK_IS_SCALE (scale));
275
276   draw_value = draw_value != FALSE;
277
278   if (scale->draw_value != draw_value)
279     {
280       scale->draw_value = draw_value;
281
282       gtk_widget_queue_resize (GTK_WIDGET (scale));
283     }
284 }
285
286 void
287 gtk_scale_set_value_pos (GtkScale        *scale,
288                          GtkPositionType  pos)
289 {
290   g_return_if_fail (scale != NULL);
291   g_return_if_fail (GTK_IS_SCALE (scale));
292
293   if (scale->value_pos != pos)
294     {
295       scale->value_pos = pos;
296
297       if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
298         gtk_widget_queue_resize (GTK_WIDGET (scale));
299     }
300 }
301
302 void
303 gtk_scale_get_value_size (GtkScale *scale,
304                           gint     *width,
305                           gint     *height)
306 {
307   GtkRange *range;
308
309   g_return_if_fail (scale != NULL);
310   g_return_if_fail (GTK_IS_SCALE (scale));
311
312   if (scale->draw_value)
313     {
314       PangoLayout *layout;
315       PangoRectangle logical_rect;
316       gchar *txt;
317       
318       range = GTK_RANGE (scale);
319
320       layout = gtk_widget_create_pango_layout (GTK_WIDGET (scale), NULL);
321
322       txt = _gtk_scale_format_value (scale, range->adjustment->lower);
323       pango_layout_set_text (layout, txt, -1);
324       g_free (txt);
325       
326       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
327
328       if (width)
329         *width = logical_rect.width;
330       if (height)
331         *height = logical_rect.height;
332
333       txt = _gtk_scale_format_value (scale, range->adjustment->upper);
334       pango_layout_set_text (layout, txt, -1);
335       g_free (txt);
336       
337       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
338
339       if (width)
340         *width = MAX (*width, logical_rect.width);
341       if (height)
342         *height = MAX (*height, logical_rect.height);
343
344       g_object_unref (G_OBJECT (layout));
345     }
346   else
347     {
348       if (width)
349         *width = 0;
350       if (height)
351         *height = 0;
352     }
353
354 }
355
356 gint
357 gtk_scale_get_value_width (GtkScale *scale)
358 {
359   gint width;
360
361   g_return_val_if_fail (scale != NULL, 0);
362   g_return_val_if_fail (GTK_IS_SCALE (scale), 0);
363   
364   gtk_scale_get_value_size (scale, &width, NULL);
365
366   return width;
367 }
368
369 void
370 gtk_scale_draw_value (GtkScale *scale)
371 {
372   g_return_if_fail (scale != NULL);
373   g_return_if_fail (GTK_IS_SCALE (scale));
374
375   if (GTK_SCALE_GET_CLASS (scale)->draw_value)
376     GTK_SCALE_GET_CLASS (scale)->draw_value (scale);
377 }
378
379
380 static void
381 gtk_scale_draw_background (GtkRange *range)
382 {
383   g_return_if_fail (range != NULL);
384   g_return_if_fail (GTK_IS_SCALE (range));
385
386   gtk_scale_draw_value (GTK_SCALE (range));
387 }
388
389 /**
390  * _gtk_scale_format_value:
391  * @scale: a #GtkScale
392  * @value: adjustment value
393  * 
394  * Emits "format_value" signal to format the value, if no user
395  * signal handlers, falls back to a default format.
396  * 
397  * Return value: formatted value
398  **/
399 gchar*
400 _gtk_scale_format_value (GtkScale *scale,
401                          gdouble   value)
402 {
403   gchar *fmt = NULL;
404
405   g_signal_emit (G_OBJECT (scale),
406                  signals[FORMAT_VALUE],
407                  0,
408                  value,
409                  &fmt);
410
411   if (fmt)
412     return fmt;
413   else
414     return g_strdup_printf ("%0.*f", GTK_RANGE (scale)->digits,
415                             value);
416 }