gtkrange.c 120 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3
 * Copyright (C) 2001 Red Hat, Inc.
Elliot Lee's avatar
Elliot Lee committed
4 5
 *
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
16
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
17
 */
18 19

/*
20
 * Modified by the GTK+ Team and others 1997-2004.  See the AUTHORS
21 22 23 24 25
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

26
#include "config.h"
27

Elliot Lee's avatar
Elliot Lee committed
28
#include <stdio.h>
29
#include <math.h>
30

31
#include "gtkrange.h"
Matthias Clasen's avatar
Matthias Clasen committed
32
#include "gtkrangeprivate.h"
33

34
#include "gtkadjustmentprivate.h"
35
#include "gtkboxgadgetprivate.h"
36 37
#include "gtkbuiltiniconprivate.h"
#include "gtkcsscustomgadgetprivate.h"
38 39
#include "gtkcolorscaleprivate.h"
#include "gtkintl.h"
40
#include "gtkgesturelongpressprivate.h"
41
#include "gtkmain.h"
42
#include "gtkmarshalers.h"
43
#include "gtkorientableprivate.h"
44
#include "gtkprivate.h"
45
#include "gtkscale.h"
46
#include "gtkscrollbar.h"
47
#include "gtktypebuiltins.h"
48
#include "gtkwindow.h"
49
#include "gtkwidgetprivate.h"
50
#include "a11y/gtkrangeaccessible.h"
51
#include "gtkcssstylepropertyprivate.h"
52 53 54 55 56 57 58

/**
 * SECTION:gtkrange
 * @Short_description: Base class for widgets which visualize an adjustment
 * @Title: GtkRange
 *
 * #GtkRange is the common base class for widgets which visualize an
59
 * adjustment, e.g #GtkScale or #GtkScrollbar.
60 61 62
 *
 * Apart from signals for monitoring the parameters of the adjustment,
 * #GtkRange provides properties and methods for influencing the sensitivity
William Jon McCann's avatar
William Jon McCann committed
63 64
 * of the “steppers”. It also provides properties and methods for setting a
 * “fill level” on range widgets. See gtk_range_set_fill_level().
65 66 67
 */


68
#define TIMEOUT_INITIAL     500
Benjamin Otte's avatar
Benjamin Otte committed
69
#define TIMEOUT_REPEAT      250
70
#define AUTOSCROLL_FACTOR   20
Benjamin Otte's avatar
Benjamin Otte committed
71
#define SCROLL_EDGE_SIZE    15
Elliot Lee's avatar
Elliot Lee committed
72

73
typedef struct _GtkRangeStepTimer GtkRangeStepTimer;
74

75 76 77 78 79 80 81 82 83 84 85
typedef enum {
  MOUSE_OUTSIDE,
  MOUSE_STEPPER_A,
  MOUSE_STEPPER_B,
  MOUSE_STEPPER_C,
  MOUSE_STEPPER_D,
  MOUSE_TROUGH,
  MOUSE_SLIDER,
  MOUSE_WIDGET /* inside widget but not in any of the above GUI elements */
} MouseLocation;

86
struct _GtkRangePrivate
87 88
{
  MouseLocation      mouse_location;
89
  /* last mouse coords we got, or G_MININT if mouse is outside the range */
90 91 92
  gint  mouse_x;
  gint  mouse_y;
  MouseLocation      grab_location;   /* "grabbed" mouse location, OUTSIDE for no grab */
93

94
  GtkRangeStepTimer *timer;
95

96 97 98 99 100
  GtkAdjustment     *adjustment;
  GtkSensitivityType lower_sensitivity;
  GtkSensitivityType upper_sensitivity;

  GdkWindow         *event_window;
101

102 103 104
  /* Steppers are: < > ---- < >
   *               a b      c d
   */
105
  GtkCssGadget *gadget;
106 107 108 109 110 111 112 113
  GtkCssGadget *stepper_a_gadget;
  GtkCssGadget *stepper_b_gadget;
  GtkCssGadget *stepper_c_gadget;
  GtkCssGadget *stepper_d_gadget;
  GtkCssGadget *trough_gadget;
  GtkCssGadget *fill_gadget;
  GtkCssGadget *highlight_gadget;
  GtkCssGadget *slider_gadget;
114

115
  GtkOrientation     orientation;
116 117 118 119 120 121 122 123 124

  gdouble  fill_level;
  gdouble *marks;

  gint *mark_pos;
  gint  min_slider_size;
  gint  n_marks;
  gint  round_digits;                /* Round off value to this many digits, -1 for no rounding */
  gint  slide_initial_slider_position;
125
  gint  slide_initial_coordinate_delta;
126

127 128 129 130
  guint flippable              : 1;
  guint inverted               : 1;
  guint slider_size_fixed      : 1;
  guint trough_click_forward   : 1;  /* trough click was on the forward side of slider */
131 132

  /* Stepper sensitivity */
133 134
  guint lower_sensitive        : 1;
  guint upper_sensitive        : 1;
135

136 137 138
  /* The range has an origin, should be drawn differently. Used by GtkScale */
  guint has_origin             : 1;

139 140
  /* Whether we're doing fine adjustment */
  guint zoom                   : 1;
141

142
  /* Fill level */
143
  guint show_fill_level        : 1;
144
  guint restrict_to_fill_level : 1;
145 146 147

  /* Whether dragging is ongoing */
  guint in_drag                : 1;
148 149 150 151 152 153 154

  GtkGesture *long_press_gesture;
  GtkGesture *multipress_gesture;
  GtkGesture *drag_gesture;

  GtkScrollType autoscroll_mode;
  guint autoscroll_id;
155
};
156

157

158 159 160 161 162 163 164 165
enum {
  PROP_0,
  PROP_ADJUSTMENT,
  PROP_INVERTED,
  PROP_LOWER_STEPPER_SENSITIVITY,
  PROP_UPPER_STEPPER_SENSITIVITY,
  PROP_SHOW_FILL_LEVEL,
  PROP_RESTRICT_TO_FILL_LEVEL,
166
  PROP_FILL_LEVEL,
167 168 169
  PROP_ROUND_DIGITS,
  PROP_ORIENTATION,
  LAST_PROP = PROP_ORIENTATION
170
};
171

172 173 174 175 176 177
enum {
  VALUE_CHANGED,
  ADJUST_BOUNDS,
  MOVE_SLIDER,
  CHANGE_VALUE,
  LAST_SIGNAL
178 179
};

180
typedef enum {
181 182 183 184
  STEPPER_A = MOUSE_STEPPER_A,
  STEPPER_B = MOUSE_STEPPER_B,
  STEPPER_C = MOUSE_STEPPER_C,
  STEPPER_D = MOUSE_STEPPER_D
185
} Stepper;
186

187 188 189 190 191 192 193 194
static void gtk_range_set_property   (GObject          *object,
                                      guint             prop_id,
                                      const GValue     *value,
                                      GParamSpec       *pspec);
static void gtk_range_get_property   (GObject          *object,
                                      guint             prop_id,
                                      GValue           *value,
                                      GParamSpec       *pspec);
195
static void gtk_range_destroy        (GtkWidget        *widget);
196 197 198 199 200 201 202 203
static void gtk_range_get_preferred_width
                                     (GtkWidget        *widget,
                                      gint             *minimum,
                                      gint             *natural);
static void gtk_range_get_preferred_height
                                     (GtkWidget        *widget,
                                      gint             *minimum,
                                      gint             *natural);
204 205 206 207
static void gtk_range_size_allocate  (GtkWidget        *widget,
                                      GtkAllocation    *allocation);
static void gtk_range_realize        (GtkWidget        *widget);
static void gtk_range_unrealize      (GtkWidget        *widget);
208 209
static void gtk_range_map            (GtkWidget        *widget);
static void gtk_range_unmap          (GtkWidget        *widget);
Benjamin Otte's avatar
Benjamin Otte committed
210 211
static gboolean gtk_range_draw       (GtkWidget        *widget,
                                      cairo_t          *cr);
212 213 214 215 216 217 218 219 220 221 222

static void gtk_range_multipress_gesture_pressed  (GtkGestureMultiPress *gesture,
                                                   guint                 n_press,
                                                   gdouble               x,
                                                   gdouble               y,
                                                   GtkRange             *range);
static void gtk_range_multipress_gesture_released (GtkGestureMultiPress *gesture,
                                                   guint                 n_press,
                                                   gdouble               x,
                                                   gdouble               y,
                                                   GtkRange             *range);
223 224 225 226
static void gtk_range_drag_gesture_begin          (GtkGestureDrag       *gesture,
                                                   gdouble               offset_x,
                                                   gdouble               offset_y,
                                                   GtkRange             *range);
227 228 229 230 231 232 233 234 235 236
static void gtk_range_drag_gesture_update         (GtkGestureDrag       *gesture,
                                                   gdouble               offset_x,
                                                   gdouble               offset_y,
                                                   GtkRange             *range);
static void gtk_range_long_press_gesture_pressed  (GtkGestureLongPress  *gesture,
                                                   gdouble               x,
                                                   gdouble               y,
                                                   GtkRange             *range);


Matthias Clasen's avatar
Matthias Clasen committed
237
static gboolean gtk_range_scroll_event   (GtkWidget        *widget,
238
                                      GdkEventScroll   *event);
239 240
static gboolean gtk_range_event       (GtkWidget       *widget,
                                       GdkEvent        *event);
241 242 243
static void update_slider_position   (GtkRange	       *range,
				      gint              mouse_x,
				      gint              mouse_y);
244
static void stop_scrolling           (GtkRange         *range);
245 246
static void add_autoscroll           (GtkRange         *range);
static void remove_autoscroll        (GtkRange         *range);
247 248

/* Range methods */
249

250
static void gtk_range_move_slider              (GtkRange         *range,
251 252 253
                                                GtkScrollType     scroll);

/* Internals */
254 255 256
static void          gtk_range_compute_slider_position  (GtkRange      *range,
                                                         gdouble        adjustment_value,
                                                         GdkRectangle  *slider_rect);
257
static gboolean      gtk_range_scroll                   (GtkRange      *range,
258
                                                         GtkScrollType  scroll);
259
static void          gtk_range_update_mouse_location    (GtkRange      *range);
260 261
static void          gtk_range_calc_slider              (GtkRange      *range);
static void          gtk_range_calc_stepper_sensitivity (GtkRange      *range);
262
static void          gtk_range_calc_marks               (GtkRange      *range);
263 264 265 266 267 268 269
static void          gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
                                                         gpointer       data);
static void          gtk_range_adjustment_changed       (GtkAdjustment *adjustment,
                                                         gpointer       data);
static void          gtk_range_add_step_timer           (GtkRange      *range,
                                                         GtkScrollType  step);
static void          gtk_range_remove_step_timer        (GtkRange      *range);
Benjamin Otte's avatar
Benjamin Otte committed
270
static void          gtk_range_queue_draw_location      (GtkRange      *range,
271
                                                         MouseLocation  location);
272 273 274
static gboolean      gtk_range_real_change_value        (GtkRange      *range,
                                                         GtkScrollType  scroll,
                                                         gdouble        value);
275 276
static gboolean      gtk_range_key_press                (GtkWidget     *range,
							 GdkEventKey   *event);
277 278
static void          gtk_range_state_flags_changed      (GtkWidget     *widget,
                                                         GtkStateFlags  previous_state);
279 280
static void          gtk_range_measure_trough           (GtkCssGadget   *gadget,
                                                         GtkOrientation  orientation,
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
                                                         gint            for_size,
                                                         gint           *minimum,
                                                         gint           *natural,
                                                         gint           *minimum_baseline,
                                                         gint           *natural_baseline,
                                                         gpointer        user_data);
static void          gtk_range_allocate_trough          (GtkCssGadget        *gadget,
                                                         const GtkAllocation *allocation,
                                                         int                  baseline,
                                                         GtkAllocation       *out_clip,
                                                         gpointer             data);
static gboolean      gtk_range_render_trough            (GtkCssGadget *gadget,
                                                         cairo_t      *cr,
                                                         int           x,
                                                         int           y,
                                                         int           width,
                                                         int           height,
                                                         gpointer      user_data);

Elliot Lee's avatar
Elliot Lee committed
300

301
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkRange, gtk_range, GTK_TYPE_WIDGET,
302
                                  G_ADD_PRIVATE (GtkRange)
303 304 305
                                  G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,
                                                         NULL))

306
static guint signals[LAST_SIGNAL];
307
static GParamSpec *properties[LAST_PROP];
Elliot Lee's avatar
Elliot Lee committed
308 309 310 311

static void
gtk_range_class_init (GtkRangeClass *class)
{
Alexander Larsson's avatar
Alexander Larsson committed
312
  GObjectClass   *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
313 314
  GtkWidgetClass *widget_class;

Alexander Larsson's avatar
Alexander Larsson committed
315
  gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
316 317
  widget_class = (GtkWidgetClass*) class;

Alexander Larsson's avatar
Alexander Larsson committed
318 319
  gobject_class->set_property = gtk_range_set_property;
  gobject_class->get_property = gtk_range_get_property;
320

321
  widget_class->destroy = gtk_range_destroy;
322 323
  widget_class->get_preferred_width = gtk_range_get_preferred_width;
  widget_class->get_preferred_height = gtk_range_get_preferred_height;
324 325
  widget_class->size_allocate = gtk_range_size_allocate;
  widget_class->realize = gtk_range_realize;
326
  widget_class->unrealize = gtk_range_unrealize;
327 328
  widget_class->map = gtk_range_map;
  widget_class->unmap = gtk_range_unmap;
Benjamin Otte's avatar
Benjamin Otte committed
329
  widget_class->draw = gtk_range_draw;
330
  widget_class->event = gtk_range_event;
331
  widget_class->scroll_event = gtk_range_scroll_event;
332
  widget_class->key_press_event = gtk_range_key_press;
333
  widget_class->state_flags_changed = gtk_range_state_flags_changed;
334 335

  class->move_slider = gtk_range_move_slider;
336
  class->change_value = gtk_range_real_change_value;
337

Matthias Clasen's avatar
Matthias Clasen committed
338 339
  /**
   * GtkRange::value-changed:
340
   * @range: the #GtkRange that received the signal
Matthias Clasen's avatar
Matthias Clasen committed
341 342 343
   *
   * Emitted when the range value changes.
   */
344
  signals[VALUE_CHANGED] =
345
    g_signal_new (I_("value-changed"),
Manish Singh's avatar
Manish Singh committed
346
                  G_TYPE_FROM_CLASS (gobject_class),
347 348 349
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkRangeClass, value_changed),
                  NULL, NULL,
350
                  _gtk_marshal_VOID__VOID,
351
                  G_TYPE_NONE, 0);
352 353 354 355 356

  /**
   * GtkRange::adjust-bounds:
   * @range: the #GtkRange that received the signal
   * @value: the value before we clamp
357 358 359
   *
   * Emitted before clamping a value, to give the application a
   * chance to adjust the bounds.
360
   */
361
  signals[ADJUST_BOUNDS] =
362
    g_signal_new (I_("adjust-bounds"),
Manish Singh's avatar
Manish Singh committed
363
                  G_TYPE_FROM_CLASS (gobject_class),
364 365 366 367 368 369
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkRangeClass, adjust_bounds),
                  NULL, NULL,
                  _gtk_marshal_VOID__DOUBLE,
                  G_TYPE_NONE, 1,
                  G_TYPE_DOUBLE);
370

Matthias Clasen's avatar
Matthias Clasen committed
371 372
  /**
   * GtkRange::move-slider:
373
   * @range: the #GtkRange that received the signal
Matthias Clasen's avatar
Matthias Clasen committed
374 375 376 377
   * @step: how to move the slider
   *
   * Virtual function that moves the slider. Used for keybindings.
   */
378
  signals[MOVE_SLIDER] =
379
    g_signal_new (I_("move-slider"),
Manish Singh's avatar
Manish Singh committed
380
                  G_TYPE_FROM_CLASS (gobject_class),
381 382 383
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkRangeClass, move_slider),
                  NULL, NULL,
384
                  _gtk_marshal_VOID__ENUM,
385 386
                  G_TYPE_NONE, 1,
                  GTK_TYPE_SCROLL_TYPE);
387 388 389

  /**
   * GtkRange::change-value:
390
   * @range: the #GtkRange that received the signal
Matthias Clasen's avatar
Matthias Clasen committed
391 392
   * @scroll: the type of scroll action that was performed
   * @value: the new value resulting from the scroll action
393
   *
394
   * The #GtkRange::change-value signal is emitted when a scroll action is
395 396 397 398 399 400 401 402
   * performed on a range.  It allows an application to determine the
   * type of scroll event that occurred and the resultant new value.
   * The application can handle the event itself and return %TRUE to
   * prevent further processing.  Or, by returning %FALSE, it can pass
   * the event to other handlers until the default GTK+ handler is
   * reached.
   *
   * The value parameter is unrounded.  An application that overrides
403 404 405
   * the GtkRange::change-value signal is responsible for clamping the
   * value to the desired number of decimal digits; the default GTK+
   * handler clamps the value based on #GtkRange:round-digits.
406 407
   *
   * It is not possible to use delayed update policies in an overridden
408
   * #GtkRange::change-value handler.
409
   *
410 411 412
   * Returns: %TRUE to prevent other handlers from being invoked for
   *     the signal, %FALSE to propagate the signal further
   *
413 414 415
   * Since: 2.6
   */
  signals[CHANGE_VALUE] =
416
    g_signal_new (I_("change-value"),
417 418 419 420 421 422 423 424
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkRangeClass, change_value),
                  _gtk_boolean_handled_accumulator, NULL,
                  _gtk_marshal_BOOLEAN__ENUM_DOUBLE,
                  G_TYPE_BOOLEAN, 2,
                  GTK_TYPE_SCROLL_TYPE,
                  G_TYPE_DOUBLE);
Tim Janik's avatar
Tim Janik committed
425

426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
  g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");

  properties[PROP_ADJUSTMENT] =
      g_param_spec_object ("adjustment",
                           P_("Adjustment"),
                           P_("The GtkAdjustment that contains the current value of this range object"),
                           GTK_TYPE_ADJUSTMENT,
                           GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT);

  properties[PROP_INVERTED] =
      g_param_spec_boolean ("inverted",
                            P_("Inverted"),
                            P_("Invert direction slider moves to increase range value"),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  properties[PROP_LOWER_STEPPER_SENSITIVITY] =
      g_param_spec_enum ("lower-stepper-sensitivity",
                         P_("Lower stepper sensitivity"),
                         P_("The sensitivity policy for the stepper that points to the adjustment's lower side"),
                         GTK_TYPE_SENSITIVITY_TYPE,
                         GTK_SENSITIVITY_AUTO,
                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  properties[PROP_UPPER_STEPPER_SENSITIVITY] =
      g_param_spec_enum ("upper-stepper-sensitivity",
                         P_("Upper stepper sensitivity"),
                         P_("The sensitivity policy for the stepper that points to the adjustment's upper side"),
                         GTK_TYPE_SENSITIVITY_TYPE,
                         GTK_SENSITIVITY_AUTO,
                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
457

458 459 460
  /**
   * GtkRange:show-fill-level:
   *
Matthias Clasen's avatar
Matthias Clasen committed
461
   * The show-fill-level property controls whether fill level indicator
462 463 464 465 466
   * graphics are displayed on the trough. See
   * gtk_range_set_show_fill_level().
   *
   * Since: 2.12
   **/
467 468 469 470 471 472
  properties[PROP_SHOW_FILL_LEVEL] =
      g_param_spec_boolean ("show-fill-level",
                            P_("Show Fill Level"),
                            P_("Whether to display a fill level indicator graphics on trough."),
                            FALSE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
473 474 475 476

  /**
   * GtkRange:restrict-to-fill-level:
   *
Matthias Clasen's avatar
Matthias Clasen committed
477
   * The restrict-to-fill-level property controls whether slider
478
   * movement is restricted to an upper boundary set by the
Matthias Clasen's avatar
Matthias Clasen committed
479
   * fill level. See gtk_range_set_restrict_to_fill_level().
480 481 482
   *
   * Since: 2.12
   **/
483 484 485 486 487 488
  properties[PROP_RESTRICT_TO_FILL_LEVEL] =
      g_param_spec_boolean ("restrict-to-fill-level",
                            P_("Restrict to Fill Level"),
                            P_("Whether to restrict the upper boundary to the fill level."),
                            TRUE,
                            GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
489 490 491 492 493 494 495 496 497

  /**
   * GtkRange:fill-level:
   *
   * The fill level (e.g. prebuffering of a network stream).
   * See gtk_range_set_fill_level().
   *
   * Since: 2.12
   **/
498 499 500 501 502 503 504
  properties[PROP_FILL_LEVEL] =
      g_param_spec_double ("fill-level",
                           P_("Fill Level"),
                           P_("The fill level."),
                           -G_MAXDOUBLE, G_MAXDOUBLE,
                           G_MAXDOUBLE,
                           GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
505

506 507 508 509 510 511 512 513
  /**
   * GtkRange:round-digits:
   *
   * The number of digits to round the value to when
   * it changes, or -1. See #GtkRange::change-value.
   *
   * Since: 2.24
   */
514 515 516 517 518 519 520 521 522
  properties[PROP_ROUND_DIGITS] =
      g_param_spec_int ("round-digits",
                        P_("Round Digits"),
                        P_("The number of digits to round the value to."),
                        -1, G_MAXINT,
                        -1,
                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);

  g_object_class_install_properties (gobject_class, LAST_PROP, properties);
523

524 525 526 527 528 529 530 531
  /**
   * GtkRange:slider-width:
   *
   * Width of scrollbar or scale thumb.
   *
   * Depreacated: 3.20: Use the min-height/min-width CSS properties on the
   *   slider element. The value of this style property is ignored.
   */
532
  gtk_widget_class_install_style_property (widget_class,
533
					   g_param_spec_int ("slider-width",
534 535
							     P_("Slider Width"),
							     P_("Width of scrollbar or scale thumb"),
536 537
							     0,
							     G_MAXINT,
538
							     14,
539 540 541 542 543 544 545 546 547
							     GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
  /**
   * GtkRange:trough-border:
   *
   * Spacing between thumb/steppers and outer trough bevel.
   *
   * Depreacated: 3.20: Use the margin/padding CSS properties on the through and
   *   stepper elements. The value of this style property is ignored.
   */
548
  gtk_widget_class_install_style_property (widget_class,
549
					   g_param_spec_int ("trough-border",
550 551
                                                             P_("Trough Border"),
                                                             P_("Spacing between thumb/steppers and outer trough bevel"),
552 553 554
                                                             0,
                                                             G_MAXINT,
                                                             1,
555 556 557 558 559 560 561 562 563
                                                             GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
  /**
   * GtkRange:stepper-size:
   *
   * Length of step buttons at ends.
   *
   * Depreacated: 3.20: Use the min-height/min-width CSS properties on the
   *   stepper elements. The value of this style property is ignored.
   */
564
  gtk_widget_class_install_style_property (widget_class,
565
					   g_param_spec_int ("stepper-size",
566 567
							     P_("Stepper Size"),
							     P_("Length of step buttons at ends"),
568 569
							     0,
							     G_MAXINT,
570
							     14,
571
							     GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
572 573 574 575 576
  /**
   * GtkRange:stepper-spacing:
   *
   * The spacing between the stepper buttons and thumb. Note that
   * stepper-spacing won't have any effect if there are no steppers.
577 578 579
   *
   * Depreacated: 3.20: Use the margin CSS property on the stepper elements.
   *   The value of this style property is ignored.
580
   */
581
  gtk_widget_class_install_style_property (widget_class,
582
					   g_param_spec_int ("stepper-spacing",
583 584
							     P_("Stepper Spacing"),
							     P_("Spacing between step buttons and thumb"),
585
                                                             0,
586
							     G_MAXINT,
587
							     0,
588
							     GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
589 590 591 592 593 594 595 596

  /**
   * GtkRange:arrow-displacement-x:
   *
   * How far in the x direction to move the arrow when the button is depressed.
   *
   * Deprecated: 3.20: The value of this style property is ignored.
   */
597
  gtk_widget_class_install_style_property (widget_class,
598
					   g_param_spec_int ("arrow-displacement-x",
599 600
							     P_("Arrow X Displacement"),
							     P_("How far in the x direction to move the arrow when the button is depressed"),
601 602 603
							     G_MININT,
							     G_MAXINT,
							     0,
604
							     GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
605 606 607 608 609 610 611 612

  /**
   * GtkRange:arrow-displacement-y:
   *
   * How far in the y direction to move the arrow when the button is depressed.
   *
   * Deprecated: 3.20: The value of this style property is ignored.
   */
613
  gtk_widget_class_install_style_property (widget_class,
614
					   g_param_spec_int ("arrow-displacement-y",
615 616
							     P_("Arrow Y Displacement"),
							     P_("How far in the y direction to move the arrow when the button is depressed"),
617 618 619
							     G_MININT,
							     G_MAXINT,
							     0,
620
							     GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
621

622 623 624 625
  /**
   * GtkRange:trough-under-steppers:
   *
   * Whether to draw the trough across the full length of the range or
626
   * to exclude the steppers and their spacing.
627 628
   *
   * Since: 2.10
629 630 631
   *
   * Deprecated: 3.20: The value of this style property is ignored, and the
   *   widget will behave as if it was set to %TRUE.
632 633 634 635
   */
  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_boolean ("trough-under-steppers",
                                                                 P_("Trough Under Steppers"),
636
                                                                 P_("Whether to draw trough for full length of range or exclude the steppers and spacing"),
637
                                                                 TRUE,
638
                                                                 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
639

640 641 642 643 644 645
  /**
   * GtkRange:arrow-scaling:
   *
   * The arrow size proportion relative to the scroll button size.
   *
   * Since: 2.14
646 647 648
   *
   * Deprecated: 3.20: Use min-width/min-height on the "button" node instead.
   *   The value of this style property is ignored.
649 650 651 652 653 654
   */
  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_float ("arrow-scaling",
							       P_("Arrow scaling"),
							       P_("Arrow scaling with regard to scroll button size"),
							       0.0, 1.0, 0.5,
655
							       GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
656

657
  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_RANGE_ACCESSIBLE);
Elliot Lee's avatar
Elliot Lee committed
658 659
}

660 661 662 663 664 665 666 667 668 669 670
static void
gtk_range_sync_orientation (GtkRange *range)
{
  GtkRangePrivate *priv = range->priv;
  GtkOrientation orientation;

  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (range));
  _gtk_orientable_set_style_classes (GTK_ORIENTABLE (range));
  gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), orientation);

  if (orientation == GTK_ORIENTATION_VERTICAL)
671 672
    gtk_box_gadget_set_gadget_expand (GTK_BOX_GADGET (priv->gadget),
                                      priv->trough_gadget, FALSE, TRUE);
673
  else
674 675
    gtk_box_gadget_set_gadget_expand (GTK_BOX_GADGET (priv->gadget),
                                      priv->trough_gadget, TRUE, FALSE);
676 677
}

678
static void
Alexander Larsson's avatar
Alexander Larsson committed
679 680 681 682
gtk_range_set_property (GObject      *object,
			guint         prop_id,
			const GValue *value,
			GParamSpec   *pspec)
683
{
684
  GtkRange *range = GTK_RANGE (object);
685
  GtkRangePrivate *priv = range->priv;
686

Alexander Larsson's avatar
Alexander Larsson committed
687
  switch (prop_id)
688
    {
689
    case PROP_ORIENTATION:
690 691 692
      if (priv->orientation != g_value_get_enum (value))
        {
          priv->orientation = g_value_get_enum (value);
693
          gtk_range_sync_orientation (range);
694 695 696
          gtk_widget_queue_resize (GTK_WIDGET (range));
          g_object_notify_by_pspec (object, pspec);
        }
697
      break;
698 699 700
    case PROP_ADJUSTMENT:
      gtk_range_set_adjustment (range, g_value_get_object (value));
      break;
Havoc Pennington's avatar
Havoc Pennington committed
701 702 703
    case PROP_INVERTED:
      gtk_range_set_inverted (range, g_value_get_boolean (value));
      break;
704 705 706 707 708 709
    case PROP_LOWER_STEPPER_SENSITIVITY:
      gtk_range_set_lower_stepper_sensitivity (range, g_value_get_enum (value));
      break;
    case PROP_UPPER_STEPPER_SENSITIVITY:
      gtk_range_set_upper_stepper_sensitivity (range, g_value_get_enum (value));
      break;
710 711 712 713 714 715 716 717 718
    case PROP_SHOW_FILL_LEVEL:
      gtk_range_set_show_fill_level (range, g_value_get_boolean (value));
      break;
    case PROP_RESTRICT_TO_FILL_LEVEL:
      gtk_range_set_restrict_to_fill_level (range, g_value_get_boolean (value));
      break;
    case PROP_FILL_LEVEL:
      gtk_range_set_fill_level (range, g_value_get_double (value));
      break;
719 720 721
    case PROP_ROUND_DIGITS:
      gtk_range_set_round_digits (range, g_value_get_int (value));
      break;
722
    default:
Alexander Larsson's avatar
Alexander Larsson committed
723
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
724 725 726 727 728
      break;
    }
}

static void
Alexander Larsson's avatar
Alexander Larsson committed
729 730 731 732
gtk_range_get_property (GObject      *object,
			guint         prop_id,
			GValue       *value,
			GParamSpec   *pspec)
733
{
734
  GtkRange *range = GTK_RANGE (object);
735
  GtkRangePrivate *priv = range->priv;
736

Alexander Larsson's avatar
Alexander Larsson committed
737
  switch (prop_id)
738
    {
739
    case PROP_ORIENTATION:
740
      g_value_set_enum (value, priv->orientation);
741
      break;
742
    case PROP_ADJUSTMENT:
743
      g_value_set_object (value, priv->adjustment);
744
      break;
Havoc Pennington's avatar
Havoc Pennington committed
745
    case PROP_INVERTED:
746
      g_value_set_boolean (value, priv->inverted);
Havoc Pennington's avatar
Havoc Pennington committed
747
      break;
748 749 750 751 752 753
    case PROP_LOWER_STEPPER_SENSITIVITY:
      g_value_set_enum (value, gtk_range_get_lower_stepper_sensitivity (range));
      break;
    case PROP_UPPER_STEPPER_SENSITIVITY:
      g_value_set_enum (value, gtk_range_get_upper_stepper_sensitivity (range));
      break;
754 755 756 757 758 759 760 761 762
    case PROP_SHOW_FILL_LEVEL:
      g_value_set_boolean (value, gtk_range_get_show_fill_level (range));
      break;
    case PROP_RESTRICT_TO_FILL_LEVEL:
      g_value_set_boolean (value, gtk_range_get_restrict_to_fill_level (range));
      break;
    case PROP_FILL_LEVEL:
      g_value_set_double (value, gtk_range_get_fill_level (range));
      break;
763 764 765
    case PROP_ROUND_DIGITS:
      g_value_set_int (value, gtk_range_get_round_digits (range));
      break;
766
    default:
Alexander Larsson's avatar
Alexander Larsson committed
767
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
768 769 770 771
      break;
    }
}

Elliot Lee's avatar
Elliot Lee committed
772 773 774
static void
gtk_range_init (GtkRange *range)
{
775
  GtkRangePrivate *priv;
776
  GtkCssNode *widget_node;
777

778
  range->priv = gtk_range_get_instance_private (range);
779 780
  priv = range->priv;

781
  gtk_widget_set_has_window (GTK_WIDGET (range), FALSE);
782

783 784 785 786 787 788 789
  priv->orientation = GTK_ORIENTATION_HORIZONTAL;
  priv->adjustment = NULL;
  priv->inverted = FALSE;
  priv->flippable = FALSE;
  priv->min_slider_size = 1;
  priv->round_digits = -1;
  priv->mouse_location = MOUSE_OUTSIDE;
790 791
  priv->mouse_x = G_MININT;
  priv->mouse_y = G_MININT;
792 793 794 795 796
  priv->grab_location = MOUSE_OUTSIDE;
  priv->lower_sensitivity = GTK_SENSITIVITY_AUTO;
  priv->upper_sensitivity = GTK_SENSITIVITY_AUTO;
  priv->lower_sensitive = TRUE;
  priv->upper_sensitive = TRUE;
797
  priv->has_origin = FALSE;
798 799 800 801
  priv->show_fill_level = FALSE;
  priv->restrict_to_fill_level = TRUE;
  priv->fill_level = G_MAXDOUBLE;
  priv->timer = NULL;
802

803 804
  _gtk_orientable_set_style_classes (GTK_ORIENTABLE (range));

805
  widget_node = gtk_widget_get_css_node (GTK_WIDGET (range));
806 807
  priv->gadget = gtk_box_gadget_new_for_node (widget_node, GTK_WIDGET (range));

808 809 810 811
  priv->trough_gadget = gtk_css_custom_gadget_new ("trough",
                                                   GTK_WIDGET (range),
                                                   NULL, NULL,
                                                   gtk_range_measure_trough,
812 813
                                                   gtk_range_allocate_trough,
                                                   gtk_range_render_trough,
814
                                                   NULL, NULL);
815 816
  gtk_css_gadget_set_state (priv->trough_gadget,
                            gtk_css_node_get_state (widget_node));
817 818
  gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), -1, priv->trough_gadget,
                                TRUE, FALSE, GTK_ALIGN_CENTER);
819 820 821 822

  priv->slider_gadget = gtk_builtin_icon_new ("slider",
                                              GTK_WIDGET (range),
                                              priv->trough_gadget, NULL);
823 824
  gtk_css_gadget_set_state (priv->slider_gadget,
                            gtk_css_node_get_state (widget_node));
825

826 827 828 829 830 831 832
  /* Note: Order is important here.
   * The ::drag-begin handler relies on the state set up by the
   * multipress ::pressed handler. Gestures are handling events
   * in the oppposite order in which they are added to their
   * widget.
   */
  priv->drag_gesture = gtk_gesture_drag_new (GTK_WIDGET (range));
833
  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->drag_gesture), 0);
834 835 836 837 838
  g_signal_connect (priv->drag_gesture, "drag-begin",
                    G_CALLBACK (gtk_range_drag_gesture_begin), range);
  g_signal_connect (priv->drag_gesture, "drag-update",
                    G_CALLBACK (gtk_range_drag_gesture_update), range);

839
  priv->multipress_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (range));
840
  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture), 0);
841
  gtk_gesture_group (priv->drag_gesture, priv->multipress_gesture);
842 843 844 845 846 847
  g_signal_connect (priv->multipress_gesture, "pressed",
                    G_CALLBACK (gtk_range_multipress_gesture_pressed), range);
  g_signal_connect (priv->multipress_gesture, "released",
                    G_CALLBACK (gtk_range_multipress_gesture_released), range);

  priv->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (range));
848
  g_object_set (priv->long_press_gesture, "delay-factor", 2.0, NULL);
849 850 851
  gtk_gesture_group (priv->drag_gesture, priv->long_press_gesture);
  g_signal_connect (priv->long_press_gesture, "pressed",
                    G_CALLBACK (gtk_range_long_press_gesture_pressed), range);
Elliot Lee's avatar
Elliot Lee committed
852 853
}

854 855 856 857
/**
 * gtk_range_get_adjustment:
 * @range: a #GtkRange
 * 
William Jon McCann's avatar
William Jon McCann committed
858
 * Get the #GtkAdjustment which is the “model” object for #GtkRange.
859 860 861 862
 * See gtk_range_set_adjustment() for details.
 * The return value does not have a reference added, so should not
 * be unreferenced.
 * 
863
 * Returns: (transfer none): a #GtkAdjustment
864
 **/
Elliot Lee's avatar
Elliot Lee committed
865 866 867
GtkAdjustment*
gtk_range_get_adjustment (GtkRange *range)
{
868
  GtkRangePrivate *priv;
869

Elliot Lee's avatar
Elliot Lee committed
870 871
  g_return_val_if_fail (GTK_IS_RANGE (range), NULL);

872 873 874
  priv = range->priv;

  if (!priv->adjustment)
875 876
    gtk_range_set_adjustment (range, NULL);

877
  return priv->adjustment;
Elliot Lee's avatar
Elliot Lee committed
878 879
}

880 881 882 883 884
/**
 * gtk_range_set_adjustment:
 * @range: a #GtkRange
 * @adjustment: a #GtkAdjustment
 *
William Jon McCann's avatar
William Jon McCann committed
885
 * Sets the adjustment to be used as the “model” object for this range
886 887 888 889 890 891 892
 * widget. The adjustment indicates the current range value, the
 * minimum and maximum range values, the step/page increments used
 * for keybindings and scrolling, and the page size. The page size
 * is normally 0 for #GtkScale and nonzero for #GtkScrollbar, and
 * indicates the size of the visible area of the widget being scrolled.
 * The page size affects the size of the scrollbar slider.
 **/
Elliot Lee's avatar
Elliot Lee committed
893 894 895 896
void
gtk_range_set_adjustment (GtkRange      *range,
			  GtkAdjustment *adjustment)
{
897
  GtkRangePrivate *priv;
898

Elliot Lee's avatar
Elliot Lee committed
899
  g_return_if_fail (GTK_IS_RANGE (range));
900 901 902

  priv = range->priv;

903
  if (!adjustment)
Javier Jardón's avatar
Javier Jardón committed
904
    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
905 906
  else
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
Elliot Lee's avatar
Elliot Lee committed
907

908
  if (priv->adjustment != adjustment)
Elliot Lee's avatar
Elliot Lee committed
909
    {
910
      if (priv->adjustment)
911
	{
912
	  g_signal_handlers_disconnect_by_func (priv->adjustment,
Manish Singh's avatar
Manish Singh committed
913 914
						gtk_range_adjustment_changed,
						range);
915
	  g_signal_handlers_disconnect_by_func (priv->adjustment,
Manish Singh's avatar
Manish Singh committed
916 917
						gtk_range_adjustment_value_changed,
						range);
918
	  g_object_unref (priv->adjustment);
919
	}
920

921
      priv->adjustment = adjustment;
922
      g_object_ref_sink (adjustment);
923
      
Manish Singh's avatar
Manish Singh committed
924 925 926
      g_signal_connect (adjustment, "changed",
			G_CALLBACK (gtk_range_adjustment_changed),
			range);
927
      g_signal_connect (adjustment, "value-changed",
Manish Singh's avatar
Manish Singh committed
928 929
			G_CALLBACK (gtk_range_adjustment_value_changed),
			range);
930
      
931
      gtk_range_adjustment_changed (adjustment, range);
932
      g_object_notify_by_pspec (G_OBJECT (range), properties[PROP_ADJUSTMENT]);
Elliot Lee's avatar
Elliot Lee committed
933 934 935
    }
}

936
static void
937 938 939
update_stepper_state (GtkRange     *range,
                      Stepper       stepper,
                      GtkCssGadget *gadget)
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
{
  GtkRangePrivate *priv = range->priv;
  GtkStateFlags state;
  gboolean arrow_sensitive;

  state = gtk_widget_get_state_flags (GTK_WIDGET (range));

  if ((!priv->inverted && (stepper == STEPPER_A ||
                           stepper == STEPPER_C)) ||
      (priv->inverted && (stepper == STEPPER_B ||
                          stepper == STEPPER_D)))
    arrow_sensitive = priv->lower_sensitive;
  else
    arrow_sensitive = priv->upper_sensitive;

  state &= ~(GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT);

  if ((state & GTK_STATE_FLAG_INSENSITIVE) || !arrow_sensitive)
    {
      state |= GTK_STATE_FLAG_INSENSITIVE;
    }
  else
    {
      if (priv->grab_location == (MouseLocation)stepper)
        state |= GTK_STATE_FLAG_ACTIVE;
      if (priv->mouse_location == (MouseLocation)stepper)
        state |= GTK_STATE_FLAG_PRELIGHT;
    }

969
  gtk_css_gadget_set_state (gadget, state);
970 971 972 973 974 975 976
}

static void
update_steppers_state (GtkRange *range)
{
  GtkRangePrivate *priv = range->priv;

977 978 979 980 981 982 983 984
  if (priv->stepper_a_gadget)
    update_stepper_state (range, STEPPER_A, priv->stepper_a_gadget);
  if (priv->stepper_b_gadget)
    update_stepper_state (range, STEPPER_B, priv->stepper_b_gadget);
  if (priv->stepper_c_gadget)
    update_stepper_state (range, STEPPER_C, priv->stepper_c_gadget);
  if (priv->stepper_d_gadget)
    update_stepper_state (range, STEPPER_D, priv->stepper_d_gadget);
985 986
}

987 988 989 990 991 992 993 994 995 996
/**
 * gtk_range_set_inverted:
 * @range: a #GtkRange
 * @setting: %TRUE to invert the range
 *
 * Ranges normally move from lower to higher values as the
 * slider moves from top to bottom or left to right. Inverted
 * ranges have higher values at the top or on the right rather than
 * on the bottom or left.
 **/
997 998 999 1000
void
gtk_range_set_inverted (GtkRange *range,
                        gboolean  setting)
{
1001
  GtkRangePrivate *priv;
1002

1003
  g_return_if_fail (GTK_IS_RANGE (range));
1004 1005 1006

  priv = range->priv;

1007 1008
  setting = setting != FALSE;

1009
  if (setting != priv->inverted)
1010
    {
1011
      priv->inverted = setting;
1012 1013

      update_steppers_state (range);
1014
      gtk_widget_queue_resize (GTK_WIDGET (range));
1015 1016

      g_object_notify_by_pspec (G_OBJECT (range), properties[PROP_INVERTED]);
1017 1018 1019
    }
}

1020 1021 1022 1023 1024 1025
/**
 * gtk_range_get_inverted:
 * @range: a #GtkRange
 * 
 * Gets the value set by gtk_range_set_inverted().
 * 
1026
 * Returns: %TRUE if the range is inverted
1027
 **/
1028 1029 1030 1031 1032
gboolean
gtk_range_get_inverted (GtkRange *range)
{
  g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);

1033
  return range->priv->inverted;
1034 1035
}

1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
/**
 * gtk_range_set_flippable:
 * @range: a #GtkRange
 * @flippable: %TRUE to make the range flippable
 *
 * If a range is flippable, it will switch its direction if it is
 * horizontal and its direction is %GTK_TEXT_DIR_RTL.
 *
 * See gtk_widget_get_direction().
 *
 * Since: 2.18
 **/
void
gtk_range_set_flippable (GtkRange *range,
                         gboolean  flippable)
{
1052
  GtkRangePrivate *priv;
1053

1054 1055
  g_return_if_fail (GTK_IS_RANGE (range));

1056 1057
  priv = range->priv;

1058 1059
  flippable = flippable ? TRUE : FALSE;

1060
  if (flippable != priv->flippable)
1061
    {
1062
      priv->flippable = flippable;
1063

1064
      gtk_widget_queue_allocate (GTK_WIDGET (range));
1065 1066 1067 1068 1069 1070 1071 1072 1073
    }
}

/**
 * gtk_range_get_flippable:
 * @range: a #GtkRange
 *
 * Gets the value set by gtk_range_set_flippable().
 *
1074
 * Returns: %TRUE if the range is flippable
1075 1076 1077 1078 1079 1080 1081 1082
 *
 * Since: 2.18
 **/
gboolean
gtk_range_get_flippable (GtkRange *range)
{
  g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);

1083
  return range->priv->flippable;
1084 1085
}

1086 1087 1088 1089 1090
/**
 * gtk_range_set_slider_size_fixed:
 * @range: a #GtkRange
 * @size_fixed: %TRUE to make the slider size constant
 *
1091 1092
 * Sets whether the range’s slider has a fixed size, or a size that
 * depends on its adjustment’s page size.
1093 1094 1095 1096 1097 1098 1099 1100 1101
 *
 * This function is useful mainly for #GtkRange subclasses.
 *
 * Since: 2.20
 **/
void
gtk_range_set_slider_size_fixed (GtkRange *range,
                                 gboolean  size_fixed)
{
1102
  GtkRangePrivate *priv;
1103

1104 1105
  g_return_if_fail (GTK_IS_RANGE (range));

1106 1107 1108
  priv = range->priv;

  if (size_fixed != priv->slider_size_fixed)
1109
    {
1110
      priv->slider_size_fixed = size_fixed ? TRUE : FALSE;
1111

1112
      if (priv->adjustment && gtk_widget_get_mapped (GTK_WIDGET (range)))
1113
        gtk_css_gadget_queue_allocate (priv->slider_gadget);
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
    }
}

/**
 * gtk_range_get_slider_size_fixed:
 * @range: a #GtkRange
 *
 * This function is useful mainly for #GtkRange subclasses.
 *
 * See gtk_range_set_slider_size_fixed().
 *
1125
 * Returns: whether the range’s slider has a fixed size.
1126 1127 1128 1129 1130 1131 1132 1133
 *
 * Since: 2.20
 **/
gboolean
gtk_range_get_slider_size_fixed (GtkRange *range)
{
  g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);

1134
  return range->priv->slider_size_fixed;
1135 1136 1137 1138 1139
}

/**
 * gtk_range_set_min_slider_size:
 * @range: a #GtkRange
1140
 * @min_size: The slider’s minimum size
1141
 *
1142
 * Sets the minimum size of the range’s slider.
1143 1144 1145 1146 1147 1148 1149
 *
 * This function is useful mainly for #GtkRange subclasses.
 *
 * Since: 2.20
 **/
void
gtk_range_set_min_slider_size (GtkRange *range,
1150
                               gint      min_size)
1151
{
1152
  GtkRangePrivate *priv;
1153

1154 1155 1156
  g_return_if_fail (GTK_IS_RANGE (range));
  g_return_if_fail (min_size > 0);

1157 1158 1159
  priv = range->priv;

  if (min_size != priv->min_slider_size)
1160
    {
1161
      priv->min_slider_size = min_size;
1162