1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtksignal.h"
24 #define SCROLL_TIMER_LENGTH 20
25 #define SCROLL_INITIAL_DELAY 100
26 #define SCROLL_DELAY_LENGTH 300
28 #define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
31 static void gtk_range_class_init (GtkRangeClass *klass);
32 static void gtk_range_init (GtkRange *range);
33 static void gtk_range_finalize (GtkObject *object);
34 static void gtk_range_draw (GtkWidget *widget,
36 static void gtk_range_draw_focus (GtkWidget *widget);
37 static void gtk_range_unrealize (GtkWidget *widget);
38 static gint gtk_range_expose (GtkWidget *widget,
39 GdkEventExpose *event);
40 static gint gtk_range_button_press (GtkWidget *widget,
41 GdkEventButton *event);
42 static gint gtk_range_button_release (GtkWidget *widget,
43 GdkEventButton *event);
44 static gint gtk_range_motion_notify (GtkWidget *widget,
45 GdkEventMotion *event);
46 static gint gtk_range_key_press (GtkWidget *widget,
48 static gint gtk_range_enter_notify (GtkWidget *widget,
49 GdkEventCrossing *event);
50 static gint gtk_range_leave_notify (GtkWidget *widget,
51 GdkEventCrossing *event);
52 static gint gtk_range_focus_in (GtkWidget *widget,
53 GdkEventFocus *event);
54 static gint gtk_range_focus_out (GtkWidget *widget,
55 GdkEventFocus *event);
56 static void gtk_real_range_draw_trough (GtkRange *range);
57 static void gtk_real_range_draw_slider (GtkRange *range);
58 static gint gtk_real_range_timer (GtkRange *range);
59 static gint gtk_range_scroll (GtkRange *range);
61 static void gtk_range_add_timer (GtkRange *range);
62 static void gtk_range_remove_timer (GtkRange *range);
64 static void gtk_range_adjustment_changed (GtkAdjustment *adjustment,
66 static void gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
69 static void gtk_range_trough_hdims (GtkRange *range,
72 static void gtk_range_trough_vdims (GtkRange *range,
76 static GtkWidgetClass *parent_class = NULL;
82 static guint range_type = 0;
86 GtkTypeInfo range_info =
90 sizeof (GtkRangeClass),
91 (GtkClassInitFunc) gtk_range_class_init,
92 (GtkObjectInitFunc) gtk_range_init,
97 range_type = gtk_type_unique (gtk_widget_get_type (), &range_info);
104 gtk_range_class_init (GtkRangeClass *class)
106 GtkObjectClass *object_class;
107 GtkWidgetClass *widget_class;
109 object_class = (GtkObjectClass*) class;
110 widget_class = (GtkWidgetClass*) class;
112 parent_class = gtk_type_class (gtk_widget_get_type ());
114 object_class->finalize = gtk_range_finalize;
116 widget_class->draw = gtk_range_draw;
117 widget_class->draw_focus = gtk_range_draw_focus;
118 widget_class->unrealize = gtk_range_unrealize;
119 widget_class->expose_event = gtk_range_expose;
120 widget_class->button_press_event = gtk_range_button_press;
121 widget_class->button_release_event = gtk_range_button_release;
122 widget_class->motion_notify_event = gtk_range_motion_notify;
123 widget_class->key_press_event = gtk_range_key_press;
124 widget_class->enter_notify_event = gtk_range_enter_notify;
125 widget_class->leave_notify_event = gtk_range_leave_notify;
126 widget_class->focus_in_event = gtk_range_focus_in;
127 widget_class->focus_out_event = gtk_range_focus_out;
129 class->slider_width = 11;
130 class->stepper_size = 11;
131 class->stepper_slider_spacing = 1;
132 class->min_slider_size = 7;
135 class->step_forw = 3;
136 class->step_back = 4;
137 class->draw_background = NULL;
138 class->draw_trough = gtk_real_range_draw_trough;
139 class->draw_slider = gtk_real_range_draw_slider;
140 class->draw_step_forw = NULL;
141 class->draw_step_back = NULL;
142 class->trough_click = NULL;
143 class->trough_keys = NULL;
144 class->motion = NULL;
145 class->timer = gtk_real_range_timer;
149 gtk_range_init (GtkRange *range)
151 range->trough = NULL;
152 range->slider = NULL;
153 range->step_forw = NULL;
154 range->step_back = NULL;
156 range->x_click_point = 0;
157 range->y_click_point = 0;
160 range->policy = GTK_UPDATE_CONTINUOUS;
161 range->scroll_type = GTK_SCROLL_NONE;
163 range->click_child = 0;
164 range->need_timer = FALSE;
166 range->old_value = 0.0;
167 range->old_lower = 0.0;
168 range->old_upper = 0.0;
169 range->old_page_size = 0.0;
170 range->adjustment = NULL;
174 gtk_range_get_adjustment (GtkRange *range)
176 g_return_val_if_fail (range != NULL, NULL);
177 g_return_val_if_fail (GTK_IS_RANGE (range), NULL);
179 return range->adjustment;
183 gtk_range_set_update_policy (GtkRange *range,
184 GtkUpdateType policy)
186 g_return_if_fail (range != NULL);
187 g_return_if_fail (GTK_IS_RANGE (range));
189 range->policy = policy;
193 gtk_range_set_adjustment (GtkRange *range,
194 GtkAdjustment *adjustment)
196 g_return_if_fail (range != NULL);
197 g_return_if_fail (GTK_IS_RANGE (range));
199 if (range->adjustment != adjustment)
201 if (range->adjustment)
203 gtk_signal_disconnect_by_data (GTK_OBJECT (range->adjustment),
205 gtk_object_unref (GTK_OBJECT (range->adjustment));
207 range->adjustment = adjustment;
210 gtk_object_ref (GTK_OBJECT (adjustment));
211 gtk_object_sink (GTK_OBJECT (adjustment));
213 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
214 (GtkSignalFunc) gtk_range_adjustment_changed,
216 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
217 (GtkSignalFunc) gtk_range_adjustment_value_changed,
220 range->old_value = adjustment->value;
221 range->old_lower = adjustment->lower;
222 range->old_upper = adjustment->upper;
223 range->old_page_size = adjustment->page_size;
225 gtk_range_adjustment_changed (adjustment, (gpointer) range);
231 gtk_range_draw_background (GtkRange *range)
233 g_return_if_fail (range != NULL);
234 g_return_if_fail (GTK_IS_RANGE (range));
236 if (range->trough && RANGE_CLASS (range)->draw_background)
237 (* RANGE_CLASS (range)->draw_background) (range);
241 gtk_range_draw_trough (GtkRange *range)
243 g_return_if_fail (range != NULL);
244 g_return_if_fail (GTK_IS_RANGE (range));
246 if (range->trough && RANGE_CLASS (range)->draw_trough)
247 (* RANGE_CLASS (range)->draw_trough) (range);
251 gtk_range_draw_slider (GtkRange *range)
253 g_return_if_fail (range != NULL);
254 g_return_if_fail (GTK_IS_RANGE (range));
256 if (range->slider && RANGE_CLASS (range)->draw_slider)
257 (* RANGE_CLASS (range)->draw_slider) (range);
261 gtk_range_draw_step_forw (GtkRange *range)
263 g_return_if_fail (range != NULL);
264 g_return_if_fail (GTK_IS_RANGE (range));
266 if (range->step_forw && RANGE_CLASS (range)->draw_step_forw)
267 (* RANGE_CLASS (range)->draw_step_forw) (range);
271 gtk_range_draw_step_back (GtkRange *range)
273 g_return_if_fail (range != NULL);
274 g_return_if_fail (GTK_IS_RANGE (range));
276 if (range->step_back && RANGE_CLASS (range)->draw_step_back)
277 (* RANGE_CLASS (range)->draw_step_back) (range);
281 gtk_range_slider_update (GtkRange *range)
283 g_return_if_fail (range != NULL);
284 g_return_if_fail (GTK_IS_RANGE (range));
286 if (RANGE_CLASS (range)->slider_update)
287 (* RANGE_CLASS (range)->slider_update) (range);
291 gtk_range_trough_click (GtkRange *range,
295 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
296 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
298 if (RANGE_CLASS (range)->trough_click)
299 return (* RANGE_CLASS (range)->trough_click) (range, x, y);
301 return GTK_TROUGH_NONE;
305 gtk_range_default_hslider_update (GtkRange *range)
311 g_return_if_fail (range != NULL);
312 g_return_if_fail (GTK_IS_RANGE (range));
314 if (GTK_WIDGET_REALIZED (range))
316 gtk_range_trough_hdims (range, &left, &right);
319 if (range->adjustment->value < range->adjustment->lower)
321 range->adjustment->value = range->adjustment->lower;
322 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
324 else if (range->adjustment->value > range->adjustment->upper)
326 range->adjustment->value = range->adjustment->upper;
327 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
330 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
331 x += ((right - left) * (range->adjustment->value - range->adjustment->lower) /
332 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
339 gdk_window_move (range->slider, x, GTK_WIDGET (range)->style->klass->ythickness);
344 gtk_range_default_vslider_update (GtkRange *range)
350 g_return_if_fail (range != NULL);
351 g_return_if_fail (GTK_IS_RANGE (range));
353 if (GTK_WIDGET_REALIZED (range))
355 gtk_range_trough_vdims (range, &top, &bottom);
358 if (range->adjustment->value < range->adjustment->lower)
360 range->adjustment->value = range->adjustment->lower;
361 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
363 else if (range->adjustment->value > range->adjustment->upper)
365 range->adjustment->value = range->adjustment->upper;
366 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
369 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
370 y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) /
371 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
378 gdk_window_move (range->slider, GTK_WIDGET (range)->style->klass->xthickness, y);
383 gtk_range_default_htrough_click (GtkRange *range,
393 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
394 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
396 xthickness = GTK_WIDGET (range)->style->klass->xthickness;
397 ythickness = GTK_WIDGET (range)->style->klass->ythickness;
399 if ((x > xthickness) && (y > ythickness))
401 gdk_window_get_size (range->trough, &trough_width, &trough_height);
403 if ((x < (trough_width - xthickness) && (y < (trough_height - ythickness))))
405 gdk_window_get_position (range->slider, &slider_x, NULL);
408 return GTK_TROUGH_START;
410 return GTK_TROUGH_END;
414 return GTK_TROUGH_NONE;
418 gtk_range_default_vtrough_click (GtkRange *range,
428 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
429 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
431 xthickness = GTK_WIDGET (range)->style->klass->xthickness;
432 ythickness = GTK_WIDGET (range)->style->klass->ythickness;
434 if ((x > xthickness) && (y > ythickness))
436 gdk_window_get_size (range->trough, &trough_width, &trough_height);
438 if ((x < (trough_width - xthickness) && (y < (trough_height - ythickness))))
440 gdk_window_get_position (range->slider, NULL, &slider_y);
443 return GTK_TROUGH_START;
445 return GTK_TROUGH_END;
449 return GTK_TROUGH_NONE;
453 gtk_range_default_hmotion (GtkRange *range,
459 gint slider_x, slider_y;
462 g_return_if_fail (range != NULL);
463 g_return_if_fail (GTK_IS_RANGE (range));
465 range = GTK_RANGE (range);
467 gdk_window_get_position (range->slider, &slider_x, &slider_y);
468 gtk_range_trough_hdims (range, &left, &right);
473 new_pos = slider_x + xdelta;
477 else if (new_pos > right)
480 old_value = range->adjustment->value;
481 range->adjustment->value = ((range->adjustment->upper -
482 range->adjustment->lower -
483 range->adjustment->page_size) *
484 (new_pos - left) / (right - left) +
485 range->adjustment->lower);
487 if (range->digits >= 0)
491 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
492 sscanf (buffer, "%f", &range->adjustment->value);
495 if (old_value != range->adjustment->value)
497 if (range->policy == GTK_UPDATE_CONTINUOUS)
499 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
503 gtk_range_slider_update (range);
504 gtk_range_draw_background (range);
506 if (range->policy == GTK_UPDATE_DELAYED)
508 gtk_range_remove_timer (range);
509 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
510 (GtkFunction) RANGE_CLASS (range)->timer,
518 gtk_range_default_vmotion (GtkRange *range,
524 gint slider_x, slider_y;
527 g_return_if_fail (range != NULL);
528 g_return_if_fail (GTK_IS_RANGE (range));
530 range = GTK_RANGE (range);
532 gdk_window_get_position (range->slider, &slider_x, &slider_y);
533 gtk_range_trough_vdims (range, &top, &bottom);
538 new_pos = slider_y + ydelta;
542 else if (new_pos > bottom)
545 old_value = range->adjustment->value;
546 range->adjustment->value = ((range->adjustment->upper -
547 range->adjustment->lower -
548 range->adjustment->page_size) *
549 (new_pos - top) / (bottom - top) +
550 range->adjustment->lower);
552 if (range->digits >= 0)
556 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
557 sscanf (buffer, "%f", &range->adjustment->value);
560 if (old_value != range->adjustment->value)
562 if (range->policy == GTK_UPDATE_CONTINUOUS)
564 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
568 gtk_range_slider_update (range);
569 gtk_range_draw_background (range);
571 if (range->policy == GTK_UPDATE_DELAYED)
573 gtk_range_remove_timer (range);
574 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
575 (GtkFunction) RANGE_CLASS (range)->timer,
584 gtk_range_finalize (GtkObject *object)
588 g_return_if_fail (object != NULL);
589 g_return_if_fail (GTK_IS_RANGE (object));
591 range = GTK_RANGE (object);
593 if (range->adjustment)
594 gtk_object_unref (GTK_OBJECT (range->adjustment));
596 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
600 gtk_range_draw (GtkWidget *widget,
605 g_return_if_fail (widget != NULL);
606 g_return_if_fail (GTK_IS_RANGE (widget));
607 g_return_if_fail (area != NULL);
609 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
611 range = GTK_RANGE (widget);
613 gtk_range_draw_background (range);
614 gtk_range_draw_trough (range);
615 gtk_range_draw_slider (range);
616 gtk_range_draw_step_forw (range);
617 gtk_range_draw_step_back (range);
622 gtk_range_draw_focus (GtkWidget *widget)
624 g_return_if_fail (widget != NULL);
625 g_return_if_fail (GTK_IS_RANGE (widget));
627 if (GTK_WIDGET_DRAWABLE (widget))
628 gtk_range_draw_trough (GTK_RANGE (widget));
632 gtk_range_unrealize (GtkWidget *widget)
636 g_return_if_fail (widget != NULL);
637 g_return_if_fail (GTK_IS_RANGE (widget));
639 range = GTK_RANGE (widget);
643 gdk_window_set_user_data (range->slider, NULL);
644 gdk_window_destroy (range->slider);
645 range->slider = NULL;
649 gdk_window_set_user_data (range->trough, NULL);
650 gdk_window_destroy (range->trough);
651 range->trough = NULL;
653 if (range->step_forw)
655 gdk_window_set_user_data (range->step_forw, NULL);
656 gdk_window_destroy (range->step_forw);
657 range->step_forw = NULL;
659 if (range->step_back)
661 gdk_window_set_user_data (range->step_back, NULL);
662 gdk_window_destroy (range->step_back);
663 range->step_back = NULL;
666 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
667 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
671 gtk_range_expose (GtkWidget *widget,
672 GdkEventExpose *event)
676 g_return_val_if_fail (widget != NULL, FALSE);
677 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
678 g_return_val_if_fail (event != NULL, FALSE);
680 range = GTK_RANGE (widget);
682 if (event->window == range->trough)
684 /* Don't redraw if we are only exposing the literal trough region.
685 * this may not work correctly if someone overrides the default
686 * trough-drawing handler. (Probably should really pass another
687 * argument - the redrawn area to all the drawing functions)
690 gint xt = widget->style->klass->xthickness;
691 gint yt = widget->style->klass->ythickness;
693 if (!((event->area.x >= xt) &&
694 (event->area.y >= yt) &&
695 (event->area.x + event->area.width <=
696 widget->allocation.width - xt) &&
697 (event->area.y + event->area.height <=
698 widget->allocation.height - xt)))
699 gtk_range_draw_trough (range);
701 else if (event->window == widget->window)
703 gtk_range_draw_background (range);
705 else if (event->window == range->slider)
707 gtk_range_draw_slider (range);
709 else if (event->window == range->step_forw)
711 gtk_range_draw_step_forw (range);
713 else if (event->window == range->step_back)
715 gtk_range_draw_step_back (range);
721 gtk_range_button_press (GtkWidget *widget,
722 GdkEventButton *event)
727 g_return_val_if_fail (widget != NULL, FALSE);
728 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
729 g_return_val_if_fail (event != NULL, FALSE);
731 if (!GTK_WIDGET_HAS_FOCUS (widget))
732 gtk_widget_grab_focus (widget);
734 range = GTK_RANGE (widget);
737 gtk_grab_add (widget);
739 range->button = event->button;
740 range->x_click_point = event->x;
741 range->y_click_point = event->y;
743 if (event->window == range->trough)
745 range->click_child = RANGE_CLASS (range)->trough;
747 trough_part = gtk_range_trough_click (range, event->x, event->y);
749 range->scroll_type = GTK_SCROLL_NONE;
750 if (trough_part == GTK_TROUGH_START)
751 range->scroll_type = GTK_SCROLL_PAGE_BACKWARD;
752 else if (trough_part == GTK_TROUGH_END)
753 range->scroll_type = GTK_SCROLL_PAGE_FORWARD;
755 if (range->scroll_type != GTK_SCROLL_NONE)
757 gtk_range_scroll (range);
758 gtk_range_add_timer (range);
761 else if (event->window == range->slider)
763 range->click_child = RANGE_CLASS (range)->slider;
764 range->scroll_type = GTK_SCROLL_NONE;
766 else if (event->window == range->step_forw)
768 range->click_child = RANGE_CLASS (range)->step_forw;
769 range->scroll_type = GTK_SCROLL_STEP_FORWARD;
771 gtk_range_scroll (range);
772 gtk_range_add_timer (range);
773 gtk_range_draw_step_forw (range);
775 else if (event->window == range->step_back)
777 range->click_child = RANGE_CLASS (range)->step_back;
778 range->scroll_type = GTK_SCROLL_STEP_BACKWARD;
780 gtk_range_scroll (range);
781 gtk_range_add_timer (range);
782 gtk_range_draw_step_back (range);
790 gtk_range_button_release (GtkWidget *widget,
791 GdkEventButton *event)
795 g_return_val_if_fail (widget != NULL, FALSE);
796 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
797 g_return_val_if_fail (event != NULL, FALSE);
799 range = GTK_RANGE (widget);
801 if (range->button == event->button)
803 gtk_grab_remove (widget);
806 range->x_click_point = -1;
807 range->y_click_point = -1;
809 if (range->click_child == RANGE_CLASS (range)->slider)
811 if (range->policy == GTK_UPDATE_DELAYED)
812 gtk_range_remove_timer (range);
814 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
815 (range->old_value != range->adjustment->value))
816 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
818 else if ((range->click_child == RANGE_CLASS (range)->trough) ||
819 (range->click_child == RANGE_CLASS (range)->step_forw) ||
820 (range->click_child == RANGE_CLASS (range)->step_back))
822 gtk_range_remove_timer (range);
824 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
825 (range->old_value != range->adjustment->value))
826 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
828 if (range->click_child == RANGE_CLASS (range)->step_forw)
830 range->click_child = 0;
831 gtk_range_draw_step_forw (range);
833 else if (range->click_child == RANGE_CLASS (range)->step_back)
835 range->click_child = 0;
836 gtk_range_draw_step_back (range);
840 range->click_child = 0;
847 gtk_range_motion_notify (GtkWidget *widget,
848 GdkEventMotion *event)
851 GdkModifierType mods;
854 g_return_val_if_fail (widget != NULL, FALSE);
855 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
856 g_return_val_if_fail (event != NULL, FALSE);
858 range = GTK_RANGE (widget);
860 if (range->click_child == RANGE_CLASS (range)->slider)
865 if (event->is_hint || (event->window != range->slider))
866 gdk_window_get_pointer (range->slider, &x, &y, &mods);
868 switch (range->button)
871 mask = GDK_BUTTON1_MASK;
874 mask = GDK_BUTTON2_MASK;
877 mask = GDK_BUTTON3_MASK;
886 if (RANGE_CLASS (range)->motion)
887 (* RANGE_CLASS (range)->motion) (range, x - range->x_click_point, y - range->y_click_point);
895 gtk_range_key_press (GtkWidget *widget,
900 GtkScrollType scroll = GTK_SCROLL_NONE;
901 GtkTroughType pos = GTK_TROUGH_NONE;
903 g_return_val_if_fail (widget != NULL, FALSE);
904 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
905 g_return_val_if_fail (event != NULL, FALSE);
907 range = GTK_RANGE (widget);
910 if (RANGE_CLASS (range)->trough_keys)
911 return_val = (* RANGE_CLASS (range)->trough_keys) (range, event, &scroll, &pos);
915 if (scroll != GTK_SCROLL_NONE)
917 range->scroll_type = scroll;
918 gtk_range_scroll (range);
919 if (range->old_value != range->adjustment->value)
921 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
922 switch (range->scroll_type)
924 case GTK_SCROLL_STEP_BACKWARD:
925 gtk_range_draw_step_back (range);
927 case GTK_SCROLL_STEP_FORWARD:
928 gtk_range_draw_step_forw (range);
933 if (pos != GTK_TROUGH_NONE)
935 if (pos == GTK_TROUGH_START)
936 range->adjustment->value = range->adjustment->lower;
938 range->adjustment->value =
939 range->adjustment->upper - range->adjustment->page_size;
941 if (range->old_value != range->adjustment->value)
943 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment),
946 gtk_range_slider_update (range);
947 gtk_range_draw_background (range);
955 gtk_range_enter_notify (GtkWidget *widget,
956 GdkEventCrossing *event)
960 g_return_val_if_fail (widget != NULL, FALSE);
961 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
962 g_return_val_if_fail (event != NULL, FALSE);
964 range = GTK_RANGE (widget);
966 if (event->window == range->trough)
968 range->in_child = RANGE_CLASS (range)->trough;
970 else if (event->window == range->slider)
972 range->in_child = RANGE_CLASS (range)->slider;
974 if ((range->click_child == 0) ||
975 (range->click_child == RANGE_CLASS (range)->trough))
976 gtk_range_draw_slider (range);
978 else if (event->window == range->step_forw)
980 range->in_child = RANGE_CLASS (range)->step_forw;
982 if ((range->click_child == 0) ||
983 (range->click_child == RANGE_CLASS (range)->trough))
984 gtk_range_draw_step_forw (range);
986 else if (event->window == range->step_back)
988 range->in_child = RANGE_CLASS (range)->step_back;
990 if ((range->click_child == 0) ||
991 (range->click_child == RANGE_CLASS (range)->trough))
992 gtk_range_draw_step_back (range);
999 gtk_range_leave_notify (GtkWidget *widget,
1000 GdkEventCrossing *event)
1004 g_return_val_if_fail (widget != NULL, FALSE);
1005 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1006 g_return_val_if_fail (event != NULL, FALSE);
1008 range = GTK_RANGE (widget);
1010 range->in_child = 0;
1012 if (event->window == range->trough)
1015 else if (event->window == range->slider)
1017 if ((range->click_child == 0) ||
1018 (range->click_child == RANGE_CLASS (range)->trough))
1019 gtk_range_draw_slider (range);
1021 else if (event->window == range->step_forw)
1023 if ((range->click_child == 0) ||
1024 (range->click_child == RANGE_CLASS (range)->trough))
1025 gtk_range_draw_step_forw (range);
1027 else if (event->window == range->step_back)
1029 if ((range->click_child == 0) ||
1030 (range->click_child == RANGE_CLASS (range)->trough))
1031 gtk_range_draw_step_back (range);
1038 gtk_range_focus_in (GtkWidget *widget,
1039 GdkEventFocus *event)
1041 g_return_val_if_fail (widget != NULL, FALSE);
1042 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1043 g_return_val_if_fail (event != NULL, FALSE);
1045 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1046 gtk_widget_draw_focus (widget);
1052 gtk_range_focus_out (GtkWidget *widget,
1053 GdkEventFocus *event)
1055 g_return_val_if_fail (widget != NULL, FALSE);
1056 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1057 g_return_val_if_fail (event != NULL, FALSE);
1059 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1060 gtk_widget_draw_focus (widget);
1066 gtk_real_range_draw_trough (GtkRange *range)
1068 g_return_if_fail (range != NULL);
1069 g_return_if_fail (GTK_IS_RANGE (range));
1073 gtk_draw_shadow (GTK_WIDGET (range)->style, range->trough,
1074 GTK_STATE_NORMAL, GTK_SHADOW_IN,
1077 if (GTK_WIDGET_HAS_FOCUS (range))
1078 gdk_draw_rectangle (GTK_WIDGET (range)->window,
1079 GTK_WIDGET (range)->style->black_gc,
1081 GTK_WIDGET (range)->allocation.width - 1,
1082 GTK_WIDGET (range)->allocation.height - 1);
1083 else if (range->trough != GTK_WIDGET (range)->window)
1084 gdk_draw_rectangle (GTK_WIDGET (range)->window,
1085 GTK_WIDGET (range)->style->bg_gc[GTK_STATE_NORMAL],
1087 GTK_WIDGET (range)->allocation.width - 1,
1088 GTK_WIDGET (range)->allocation.height - 1);
1093 gtk_real_range_draw_slider (GtkRange *range)
1095 GtkStateType state_type;
1097 g_return_if_fail (range != NULL);
1098 g_return_if_fail (GTK_IS_RANGE (range));
1102 if ((range->in_child == RANGE_CLASS (range)->slider) ||
1103 (range->click_child == RANGE_CLASS (range)->slider))
1104 state_type = GTK_STATE_PRELIGHT;
1106 state_type = GTK_STATE_NORMAL;
1108 gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
1109 gdk_window_clear (range->slider);
1111 gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
1112 state_type, GTK_SHADOW_OUT,
1118 gtk_real_range_timer (GtkRange *range)
1122 g_return_val_if_fail (range != NULL, FALSE);
1123 g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
1126 if (range->click_child == RANGE_CLASS (range)->slider)
1128 if (range->policy == GTK_UPDATE_DELAYED)
1129 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
1137 if (range->need_timer)
1138 range->timer = gtk_timeout_add (SCROLL_TIMER_LENGTH,
1139 (GtkFunction) RANGE_CLASS (range)->timer,
1143 range->need_timer = FALSE;
1146 if (gtk_range_scroll (range))
1154 gtk_range_scroll (GtkRange *range)
1159 g_return_val_if_fail (range != NULL, FALSE);
1160 g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
1162 new_value = range->adjustment->value;
1165 switch (range->scroll_type)
1167 case GTK_SCROLL_NONE:
1170 case GTK_SCROLL_STEP_BACKWARD:
1171 new_value -= range->adjustment->step_increment;
1172 if (new_value <= range->adjustment->lower)
1174 new_value = range->adjustment->lower;
1180 case GTK_SCROLL_STEP_FORWARD:
1181 new_value += range->adjustment->step_increment;
1182 if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
1184 new_value = range->adjustment->upper - range->adjustment->page_size;
1190 case GTK_SCROLL_PAGE_BACKWARD:
1191 new_value -= range->adjustment->page_increment;
1192 if (new_value <= range->adjustment->lower)
1194 new_value = range->adjustment->lower;
1200 case GTK_SCROLL_PAGE_FORWARD:
1201 new_value += range->adjustment->page_increment;
1202 if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
1204 new_value = range->adjustment->upper - range->adjustment->page_size;
1211 if (new_value != range->adjustment->value)
1213 range->adjustment->value = new_value;
1215 if ((range->policy == GTK_UPDATE_CONTINUOUS) ||
1216 (!return_val && (range->policy == GTK_UPDATE_DELAYED)))
1218 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
1222 gtk_range_slider_update (range);
1223 gtk_range_draw_background (range);
1232 gtk_range_add_timer (GtkRange *range)
1234 g_return_if_fail (range != NULL);
1235 g_return_if_fail (GTK_IS_RANGE (range));
1239 range->need_timer = TRUE;
1240 range->timer = gtk_timeout_add (SCROLL_INITIAL_DELAY,
1241 (GtkFunction) RANGE_CLASS (range)->timer,
1247 gtk_range_remove_timer (GtkRange *range)
1249 g_return_if_fail (range != NULL);
1250 g_return_if_fail (GTK_IS_RANGE (range));
1254 gtk_timeout_remove (range->timer);
1257 range->need_timer = FALSE;
1261 gtk_range_adjustment_changed (GtkAdjustment *adjustment,
1266 g_return_if_fail (adjustment != NULL);
1267 g_return_if_fail (data != NULL);
1269 range = GTK_RANGE (data);
1271 if (((range->old_lower != adjustment->lower) ||
1272 (range->old_upper != adjustment->upper) ||
1273 (range->old_page_size != adjustment->page_size)) &&
1274 (range->old_value == adjustment->value))
1276 if ((adjustment->lower == adjustment->upper) ||
1277 (range->old_lower == (range->old_upper - range->old_page_size)))
1279 adjustment->value = adjustment->lower;
1280 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed");
1284 if ((range->old_value != adjustment->value) ||
1285 (range->old_lower != adjustment->lower) ||
1286 (range->old_upper != adjustment->upper) ||
1287 (range->old_page_size != adjustment->page_size))
1289 gtk_range_slider_update (range);
1290 gtk_range_draw_background (range);
1292 range->old_value = adjustment->value;
1293 range->old_lower = adjustment->lower;
1294 range->old_upper = adjustment->upper;
1295 range->old_page_size = adjustment->page_size;
1300 gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
1305 g_return_if_fail (adjustment != NULL);
1306 g_return_if_fail (data != NULL);
1308 range = GTK_RANGE (data);
1310 if (range->old_value != adjustment->value)
1312 gtk_range_slider_update (range);
1313 gtk_range_draw_background (range);
1315 range->old_value = adjustment->value;
1321 gtk_range_trough_hdims (GtkRange *range,
1331 g_return_if_fail (range != NULL);
1333 gdk_window_get_size (range->trough, &trough_width, NULL);
1334 gdk_window_get_size (range->slider, &slider_length, NULL);
1336 tleft = GTK_WIDGET (range)->style->klass->xthickness;
1337 tright = trough_width - slider_length - GTK_WIDGET (range)->style->klass->xthickness;
1339 if (range->step_back)
1341 gdk_window_get_size (range->step_back, &tmp_width, NULL);
1342 tleft += (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
1345 if (range->step_forw)
1347 gdk_window_get_size (range->step_forw, &tmp_width, NULL);
1348 tright -= (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
1358 gtk_range_trough_vdims (GtkRange *range,
1368 g_return_if_fail (range != NULL);
1370 gdk_window_get_size (range->trough, NULL, &trough_height);
1371 gdk_window_get_size (range->slider, NULL, &slider_length);
1373 ttop = GTK_WIDGET (range)->style->klass->ythickness;
1374 tbottom = trough_height - slider_length - GTK_WIDGET (range)->style->klass->ythickness;
1376 if (range->step_back)
1378 gdk_window_get_size (range->step_back, NULL, &tmp_height);
1379 ttop += (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
1382 if (range->step_forw)
1384 gdk_window_get_size (range->step_forw, NULL, &tmp_height);
1385 tbottom -= (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);