]> Pileus Git - ~andy/gtk/blob - gtk/gtkadjustment.c
gtkadjustment: Move documentation to inline comments
[~andy/gtk] / gtk / gtkadjustment.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 "config.h"
28 #include "gtkadjustment.h"
29 #include "gtkmarshalers.h"
30 #include "gtkprivate.h"
31 #include "gtkintl.h"
32
33
34 /**
35  * SECTION:gtkadjustment
36  * @Short_description: A representation of an adjustable bounded value
37  * @Title: GtkAdjustment
38  *
39  * The #GtkAdjustment object represents a value which has an associated lower
40  * and upper bound, together with step and page increments, and a page size.
41  * It is used within several GTK+ widgets, including
42  * #GtkSpinButton, #GtkViewport, and #GtkRange (which is a base class for
43  * #GtkHScrollbar, #GtkVScrollbar, #GtkHScale, and #GtkVScale).
44  *
45  * The #GtkAdjustment object does not update the value itself. Instead
46  * it is left up to the owner of the #GtkAdjustment to control the value.
47  *
48  * The owner of the #GtkAdjustment typically calls the
49  * gtk_adjustment_value_changed() and gtk_adjustment_changed() functions
50  * after changing the value and its bounds. This results in the emission of the
51  * #GtkAdjustment::value_changed or #GtkAdjustment::changed signal respectively.
52  */
53
54
55 enum
56 {
57   PROP_0,
58   PROP_VALUE,
59   PROP_LOWER,
60   PROP_UPPER,
61   PROP_STEP_INCREMENT,
62   PROP_PAGE_INCREMENT,
63   PROP_PAGE_SIZE
64 };
65
66 enum
67 {
68   CHANGED,
69   VALUE_CHANGED,
70   LAST_SIGNAL
71 };
72
73
74 static void gtk_adjustment_get_property                (GObject      *object,
75                                                         guint         prop_id,
76                                                         GValue       *value,
77                                                         GParamSpec   *pspec);
78 static void gtk_adjustment_set_property                (GObject      *object,
79                                                         guint         prop_id,
80                                                         const GValue *value,
81                                                         GParamSpec   *pspec);
82 static void gtk_adjustment_dispatch_properties_changed (GObject      *object,
83                                                         guint         n_pspecs,
84                                                         GParamSpec  **pspecs);
85
86 static guint adjustment_signals[LAST_SIGNAL] = { 0 };
87
88 static guint64 adjustment_changed_stamp = 0; /* protected by global gdk lock */
89
90 G_DEFINE_TYPE (GtkAdjustment, gtk_adjustment, G_TYPE_INITIALLY_UNOWNED)
91
92 static void
93 gtk_adjustment_class_init (GtkAdjustmentClass *class)
94 {
95   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
96
97   gobject_class->set_property                = gtk_adjustment_set_property;
98   gobject_class->get_property                = gtk_adjustment_get_property;
99   gobject_class->dispatch_properties_changed = gtk_adjustment_dispatch_properties_changed;
100
101   class->changed = NULL;
102   class->value_changed = NULL;
103
104   /**
105    * GtkAdjustment:value:
106    * 
107    * The value of the adjustment.
108    * 
109    * Since: 2.4
110    */
111   g_object_class_install_property (gobject_class,
112                                    PROP_VALUE,
113                                    g_param_spec_double ("value",
114                                                         P_("Value"),
115                                                         P_("The value of the adjustment"),
116                                                         -G_MAXDOUBLE, 
117                                                         G_MAXDOUBLE, 
118                                                         0.0, 
119                                                         GTK_PARAM_READWRITE));
120   
121   /**
122    * GtkAdjustment:lower:
123    * 
124    * The minimum value of the adjustment.
125    * 
126    * Since: 2.4
127    */
128   g_object_class_install_property (gobject_class,
129                                    PROP_LOWER,
130                                    g_param_spec_double ("lower",
131                                                         P_("Minimum Value"),
132                                                         P_("The minimum value of the adjustment"),
133                                                         -G_MAXDOUBLE, 
134                                                         G_MAXDOUBLE, 
135                                                         0.0,
136                                                         GTK_PARAM_READWRITE));
137   
138   /**
139    * GtkAdjustment:upper:
140    * 
141    * The maximum value of the adjustment. 
142    * Note that values will be restricted by 
143    * <literal>upper - page-size</literal> if the page-size 
144    * property is nonzero.
145    *
146    * Since: 2.4
147    */
148   g_object_class_install_property (gobject_class,
149                                    PROP_UPPER,
150                                    g_param_spec_double ("upper",
151                                                         P_("Maximum Value"),
152                                                         P_("The maximum value of the adjustment"),
153                                                         -G_MAXDOUBLE, 
154                                                         G_MAXDOUBLE, 
155                                                         0.0, 
156                                                         GTK_PARAM_READWRITE));
157   
158   /**
159    * GtkAdjustment:step-increment:
160    * 
161    * The step increment of the adjustment.
162    * 
163    * Since: 2.4
164    */
165   g_object_class_install_property (gobject_class,
166                                    PROP_STEP_INCREMENT,
167                                    g_param_spec_double ("step-increment",
168                                                         P_("Step Increment"),
169                                                         P_("The step increment of the adjustment"),
170                                                         -G_MAXDOUBLE, 
171                                                         G_MAXDOUBLE, 
172                                                         0.0, 
173                                                         GTK_PARAM_READWRITE));
174   
175   /**
176    * GtkAdjustment:page-increment:
177    * 
178    * The page increment of the adjustment.
179    * 
180    * Since: 2.4
181    */
182   g_object_class_install_property (gobject_class,
183                                    PROP_PAGE_INCREMENT,
184                                    g_param_spec_double ("page-increment",
185                                                         P_("Page Increment"),
186                                                         P_("The page increment of the adjustment"),
187                                                         -G_MAXDOUBLE, 
188                                                         G_MAXDOUBLE, 
189                                                         0.0, 
190                                                         GTK_PARAM_READWRITE));
191   
192   /**
193    * GtkAdjustment:page-size:
194    * 
195    * The page size of the adjustment. 
196    * Note that the page-size is irrelevant and should be set to zero
197    * if the adjustment is used for a simple scalar value, e.g. in a 
198    * #GtkSpinButton.
199    * 
200    * Since: 2.4
201    */
202   g_object_class_install_property (gobject_class,
203                                    PROP_PAGE_SIZE,
204                                    g_param_spec_double ("page-size",
205                                                         P_("Page Size"),
206                                                         P_("The page size of the adjustment"),
207                                                         -G_MAXDOUBLE, 
208                                                         G_MAXDOUBLE, 
209                                                         0.0, 
210                                                         GTK_PARAM_READWRITE));
211
212   /**
213    * GtkAdjustment::changed:
214    * @adjustment: the object which received the signal.
215    *
216    * Emitted when one or more of the #GtkAdjustment fields have been changed,
217    * other than the value field.
218    */
219   adjustment_signals[CHANGED] =
220     g_signal_new (I_("changed"),
221                   G_OBJECT_CLASS_TYPE (class),
222                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
223                   G_STRUCT_OFFSET (GtkAdjustmentClass, changed),
224                   NULL, NULL,
225                   _gtk_marshal_VOID__VOID,
226                   G_TYPE_NONE, 0);
227
228   /**
229    * GtkAdjustment::value-changed:
230    * @adjustment: the object which received the signal.
231    *
232    * Emitted when the #GtkAdjustment value field has been changed.
233    */
234   adjustment_signals[VALUE_CHANGED] =
235     g_signal_new (I_("value-changed"),
236                   G_OBJECT_CLASS_TYPE (class),
237                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
238                   G_STRUCT_OFFSET (GtkAdjustmentClass, value_changed),
239                   NULL, NULL,
240                   _gtk_marshal_VOID__VOID,
241                   G_TYPE_NONE, 0);
242 }
243
244 static void
245 gtk_adjustment_init (GtkAdjustment *adjustment)
246 {
247   adjustment->value = 0.0;
248   adjustment->lower = 0.0;
249   adjustment->upper = 0.0;
250   adjustment->step_increment = 0.0;
251   adjustment->page_increment = 0.0;
252   adjustment->page_size = 0.0;
253 }
254
255 static void
256 gtk_adjustment_get_property (GObject    *object,
257                              guint       prop_id,
258                              GValue     *value,
259                              GParamSpec *pspec)
260 {
261   GtkAdjustment *adjustment = GTK_ADJUSTMENT (object);
262
263   switch (prop_id)
264     {
265     case PROP_VALUE:
266       g_value_set_double (value, adjustment->value);
267       break;
268     case PROP_LOWER:
269       g_value_set_double (value, adjustment->lower);
270       break;
271     case PROP_UPPER:
272       g_value_set_double (value, adjustment->upper);
273       break;
274     case PROP_STEP_INCREMENT:
275       g_value_set_double (value, adjustment->step_increment);
276       break;
277     case PROP_PAGE_INCREMENT:
278       g_value_set_double (value, adjustment->page_increment);
279       break;
280     case PROP_PAGE_SIZE:
281       g_value_set_double (value, adjustment->page_size);
282       break;
283     default:
284       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
285       break;
286     }
287 }
288
289 static void
290 gtk_adjustment_set_property (GObject      *object,
291                              guint         prop_id,
292                              const GValue *value,
293                              GParamSpec   *pspec)
294 {
295   GtkAdjustment *adjustment = GTK_ADJUSTMENT (object);
296   gdouble double_value = g_value_get_double (value);
297
298   switch (prop_id)
299     {
300     case PROP_VALUE:
301       gtk_adjustment_set_value (adjustment, double_value);
302       break;
303     case PROP_LOWER:
304       adjustment->lower = double_value;
305       break;
306     case PROP_UPPER:
307       adjustment->upper = double_value;
308       break;
309     case PROP_STEP_INCREMENT:
310       adjustment->step_increment = double_value;
311       break;
312     case PROP_PAGE_INCREMENT:
313       adjustment->page_increment = double_value;
314       break;
315     case PROP_PAGE_SIZE:
316       adjustment->page_size = double_value;
317       break;
318     default:
319       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
320       break;
321     }
322 }
323
324 static void
325 gtk_adjustment_dispatch_properties_changed (GObject     *object,
326                                             guint        n_pspecs,
327                                             GParamSpec **pspecs)
328 {
329   gboolean changed = FALSE;
330   gint i;
331
332   G_OBJECT_CLASS (gtk_adjustment_parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
333
334   for (i = 0; i < n_pspecs; i++)
335     switch (pspecs[i]->param_id)
336       {
337       case PROP_LOWER:
338       case PROP_UPPER:
339       case PROP_STEP_INCREMENT:
340       case PROP_PAGE_INCREMENT:
341       case PROP_PAGE_SIZE:
342         changed = TRUE;
343         break;
344       default:
345         break;
346       }
347
348   if (changed)
349     {
350       adjustment_changed_stamp++;
351       gtk_adjustment_changed (GTK_ADJUSTMENT (object));
352     }
353 }
354
355 /**
356  * gtk_adjustment_new:
357  * @value: the initial value.
358  * @lower: the minimum value.
359  * @upper: the maximum value.
360  * @step_increment: the step increment.
361  * @page_increment: the page increment.
362  * @page_size: the page size.
363  *
364  * Creates a new #GtkAdjustment.
365  *
366  * Returns: a new #GtkAdjustment.
367  */
368 GtkAdjustment *
369 gtk_adjustment_new (gdouble value,
370                     gdouble lower,
371                     gdouble upper,
372                     gdouble step_increment,
373                     gdouble page_increment,
374                     gdouble page_size)
375 {
376   return g_object_new (GTK_TYPE_ADJUSTMENT,
377                        "lower", lower,
378                        "upper", upper,
379                        "step-increment", step_increment,
380                        "page-increment", page_increment,
381                        "page-size", page_size,
382                        "value", value,
383                        NULL);
384 }
385
386 /**
387  * gtk_adjustment_get_value:
388  * @adjustment: a #GtkAdjustment
389  *
390  * Gets the current value of the adjustment. See
391  * gtk_adjustment_set_value ().
392  *
393  * Return value: The current value of the adjustment.
394  **/
395 gdouble
396 gtk_adjustment_get_value (GtkAdjustment *adjustment)
397 {
398   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), 0.0);
399
400   return adjustment->value;
401 }
402
403 /**
404  * gtk_adjustment_set_value:
405  * @adjustment: a #GtkAdjustment.
406  * @value: the new value.
407  *
408  * Sets the #GtkAdjustment value. The value is clamped to lie between
409  * #GtkAdjustment.lower and #GtkAdjustment.upper.
410  *
411  * Note that for adjustments which are used in a #GtkScrollbar, the effective
412  * range of allowed values goes from #GtkAdjustment.lower to
413  * #GtkAdjustment.upper - #GtkAdjustment.page_size.
414  */
415 void
416 gtk_adjustment_set_value (GtkAdjustment *adjustment,
417                           gdouble        value)
418 {
419   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
420
421   /* don't use CLAMP() so we don't end up below lower if upper - page_size
422    * is smaller than lower
423    */
424   value = MIN (value, adjustment->upper - adjustment->page_size);
425   value = MAX (value, adjustment->lower);
426
427   if (value != adjustment->value)
428     {
429       adjustment->value = value;
430
431       gtk_adjustment_value_changed (adjustment);
432     }
433 }
434
435 /**
436  * gtk_adjustment_get_lower:
437  * @adjustment: a #GtkAdjustment
438  *
439  * Retrieves the minimum value of the adjustment.
440  *
441  * Return value: The current minimum value of the adjustment.
442  *
443  * Since: 2.14
444  **/
445 gdouble
446 gtk_adjustment_get_lower (GtkAdjustment *adjustment)
447 {
448   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), 0.0);
449
450   return adjustment->lower;
451 }
452
453 /**
454  * gtk_adjustment_set_lower:
455  * @adjustment: a #GtkAdjustment
456  * @lower: the new minimum value
457  *
458  * Sets the minimum value of the adjustment.
459  *
460  * When setting multiple adjustment properties via their individual
461  * setters, multiple "changed" signals will be emitted. However, since
462  * the emission of the "changed" signal is tied to the emission of the
463  * "GObject::notify" signals of the changed properties, it's possible
464  * to compress the "changed" signals into one by calling
465  * g_object_freeze_notify() and g_object_thaw_notify() around the
466  * calls to the individual setters.
467  *
468  * Alternatively, using a single g_object_set() for all the properties
469  * to change, or using gtk_adjustment_configure() has the same effect
470  * of compressing "changed" emissions.
471  *
472  * Since: 2.14
473  **/
474 void
475 gtk_adjustment_set_lower (GtkAdjustment *adjustment,
476                           gdouble        lower)
477 {
478   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
479
480   if (lower != adjustment->lower)
481     g_object_set (adjustment, "lower", lower, NULL);
482 }
483
484 /**
485  * gtk_adjustment_get_upper:
486  * @adjustment: a #GtkAdjustment
487  *
488  * Retrieves the maximum value of the adjustment.
489  *
490  * Return value: The current maximum value of the adjustment.
491  *
492  * Since: 2.14
493  **/
494 gdouble
495 gtk_adjustment_get_upper (GtkAdjustment *adjustment)
496 {
497   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), 0.0);
498
499   return adjustment->upper;
500 }
501
502 /**
503  * gtk_adjustment_set_upper:
504  * @adjustment: a #GtkAdjustment
505  * @upper: the new maximum value
506  *
507  * Sets the maximum value of the adjustment.
508  *
509  * Note that values will be restricted by
510  * <literal>upper - page-size</literal> if the page-size
511  * property is nonzero.
512  *
513  * See gtk_adjustment_set_lower() about how to compress multiple
514  * emissions of the "changed" signal when setting multiple adjustment
515  * properties.
516  *
517  * Since: 2.14
518  **/
519 void
520 gtk_adjustment_set_upper (GtkAdjustment *adjustment,
521                           gdouble        upper)
522 {
523   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
524
525   if (upper != adjustment->upper)
526     g_object_set (adjustment, "upper", upper, NULL);
527 }
528
529 /**
530  * gtk_adjustment_get_step_increment:
531  * @adjustment: a #GtkAdjustment
532  *
533  * Retrieves the step increment of the adjustment.
534  *
535  * Return value: The current step increment of the adjustment.
536  *
537  * Since: 2.14
538  **/
539 gdouble
540 gtk_adjustment_get_step_increment (GtkAdjustment *adjustment)
541 {
542   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), 0.0);
543
544   return adjustment->step_increment;
545 }
546
547 /**
548  * gtk_adjustment_set_step_increment:
549  * @adjustment: a #GtkAdjustment
550  * @step_increment: the new step increment
551  *
552  * Sets the step increment of the adjustment.
553  *
554  * See gtk_adjustment_set_lower() about how to compress multiple
555  * emissions of the "changed" signal when setting multiple adjustment
556  * properties.
557  *
558  * Since: 2.14
559  **/
560 void
561 gtk_adjustment_set_step_increment (GtkAdjustment *adjustment,
562                                    gdouble        step_increment)
563 {
564   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
565
566   if (step_increment != adjustment->step_increment)
567     g_object_set (adjustment, "step-increment", step_increment, NULL);
568 }
569
570 /**
571  * gtk_adjustment_get_page_increment:
572  * @adjustment: a #GtkAdjustment
573  *
574  * Retrieves the page increment of the adjustment.
575  *
576  * Return value: The current page increment of the adjustment.
577  *
578  * Since: 2.14
579  **/
580 gdouble
581 gtk_adjustment_get_page_increment (GtkAdjustment *adjustment)
582 {
583   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), 0.0);
584
585   return adjustment->page_increment;
586 }
587
588 /**
589  * gtk_adjustment_set_page_increment:
590  * @adjustment: a #GtkAdjustment
591  * @page_increment: the new page increment
592  *
593  * Sets the page increment of the adjustment.
594  *
595  * See gtk_adjustment_set_lower() about how to compress multiple
596  * emissions of the "changed" signal when setting multiple adjustment
597  * properties.
598  *
599  * Since: 2.14
600  **/
601 void
602 gtk_adjustment_set_page_increment (GtkAdjustment *adjustment,
603                                    gdouble        page_increment)
604 {
605   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
606
607   if (page_increment != adjustment->page_increment)
608     g_object_set (adjustment, "page-increment", page_increment, NULL);
609 }
610
611 /**
612  * gtk_adjustment_get_page_size:
613  * @adjustment: a #GtkAdjustment
614  *
615  * Retrieves the page size of the adjustment.
616  *
617  * Return value: The current page size of the adjustment.
618  *
619  * Since: 2.14
620  **/
621 gdouble
622 gtk_adjustment_get_page_size (GtkAdjustment *adjustment)
623 {
624   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), 0.0);
625
626   return adjustment->page_size;
627 }
628
629 /**
630  * gtk_adjustment_set_page_size:
631  * @adjustment: a #GtkAdjustment
632  * @page_size: the new page size
633  *
634  * Sets the page size of the adjustment.
635  *
636  * See gtk_adjustment_set_lower() about how to compress multiple
637  * emissions of the "changed" signal when setting multiple adjustment
638  * properties.
639  *
640  * Since: 2.14
641  **/
642 void
643 gtk_adjustment_set_page_size (GtkAdjustment *adjustment,
644                               gdouble        page_size)
645 {
646   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
647
648   if (page_size != adjustment->page_size)
649     g_object_set (adjustment, "page-size", page_size, NULL);
650 }
651
652 /**
653  * gtk_adjustment_configure:
654  * @adjustment: a #GtkAdjustment
655  * @value: the new value
656  * @lower: the new minimum value
657  * @upper: the new maximum value
658  * @step_increment: the new step increment
659  * @page_increment: the new page increment
660  * @page_size: the new page size
661  *
662  * Sets all properties of the adjustment at once.
663  *
664  * Use this function to avoid multiple emissions of the "changed"
665  * signal. See gtk_adjustment_set_lower() for an alternative way
666  * of compressing multiple emissions of "changed" into one.
667  *
668  * Since: 2.14
669  **/
670 void
671 gtk_adjustment_configure (GtkAdjustment *adjustment,
672                           gdouble        value,
673                           gdouble        lower,
674                           gdouble        upper,
675                           gdouble        step_increment,
676                           gdouble        page_increment,
677                           gdouble        page_size)
678 {
679   gboolean value_changed = FALSE;
680   guint64 old_stamp = adjustment_changed_stamp;
681
682   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
683
684   g_object_freeze_notify (G_OBJECT (adjustment));
685
686   g_object_set (adjustment,
687                 "lower", lower,
688                 "upper", upper,
689                 "step-increment", step_increment,
690                 "page-increment", page_increment,
691                 "page-size", page_size,
692                 NULL);
693
694   /* don't use CLAMP() so we don't end up below lower if upper - page_size
695    * is smaller than lower
696    */
697   value = MIN (value, upper - page_size);
698   value = MAX (value, lower);
699
700   if (value != adjustment->value)
701     {
702       /* set value manually to make sure "changed" is emitted with the
703        * new value in place and is emitted before "value-changed"
704        */
705       adjustment->value = value;
706       value_changed = TRUE;
707     }
708
709   g_object_thaw_notify (G_OBJECT (adjustment));
710
711   if (old_stamp == adjustment_changed_stamp)
712     gtk_adjustment_changed (adjustment); /* force emission before ::value-changed */
713
714   if (value_changed)
715     gtk_adjustment_value_changed (adjustment);
716 }
717
718 /**
719  * gtk_adjustment_changed:
720  * @adjustment: a #GtkAdjustment
721  *
722  * Emits a #GtkAdjustment::changed signal from the #GtkAdjustment.
723  * This is typically called by the owner of the #GtkAdjustment after it has
724  * changed any of the #GtkAdjustment fields other than the value.
725  */
726 void
727 gtk_adjustment_changed (GtkAdjustment *adjustment)
728 {
729   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
730
731   g_signal_emit (adjustment, adjustment_signals[CHANGED], 0);
732 }
733
734 /**
735  * gtk_adjustment_value_changed:
736  * @adjustment: a #GtkAdjustment
737  *
738  * Emits a #GtkAdjustment::value_changed signal from the #GtkAdjustment.
739  * This is typically called by the owner of the #GtkAdjustment after it has
740  * changed the #GtkAdjustment value field.
741  */
742 void
743 gtk_adjustment_value_changed (GtkAdjustment *adjustment)
744 {
745   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
746
747   g_signal_emit (adjustment, adjustment_signals[VALUE_CHANGED], 0);
748   g_object_notify (G_OBJECT (adjustment), "value");
749 }
750
751 /**
752  * gtk_adjustment_clamp_page:
753  * @adjustment: a #GtkAdjustment.
754  * @lower: the lower value.
755  * @upper: the upper value.
756  *
757  * Updates the #GtkAdjustment #GtkAdjustment.value to ensure that the range
758  * between @lower and @upper is in the current page (i.e. between
759  * #GtkAdjustment.value and #GtkAdjustment.value + #GtkAdjustment.page_size).
760  * If the range is larger than the page size, then only the start of it will
761  * be in the current page.
762  * A #GtkAdjustment::changed signal will be emitted if the value is changed.
763  */
764 void
765 gtk_adjustment_clamp_page (GtkAdjustment *adjustment,
766                            gdouble        lower,
767                            gdouble        upper)
768 {
769   gboolean need_emission;
770
771   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
772
773   lower = CLAMP (lower, adjustment->lower, adjustment->upper);
774   upper = CLAMP (upper, adjustment->lower, adjustment->upper);
775
776   need_emission = FALSE;
777
778   if (adjustment->value + adjustment->page_size < upper)
779     {
780       adjustment->value = upper - adjustment->page_size;
781       need_emission = TRUE;
782     }
783   if (adjustment->value > lower)
784     {
785       adjustment->value = lower;
786       need_emission = TRUE;
787     }
788
789   if (need_emission)
790     gtk_adjustment_value_changed (adjustment);
791 }