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
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include "gtksignal.h"
25 #define SCROLL_TIMER_LENGTH 20
26 #define SCROLL_INITIAL_DELAY 100
27 #define SCROLL_DELAY_LENGTH 300
29 #define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
32 static void gtk_range_class_init (GtkRangeClass *klass);
33 static void gtk_range_init (GtkRange *range);
34 static void gtk_range_finalize (GtkObject *object);
35 static void gtk_range_draw (GtkWidget *widget,
37 static void gtk_range_draw_focus (GtkWidget *widget);
38 static void gtk_range_unrealize (GtkWidget *widget);
39 static gint gtk_range_expose (GtkWidget *widget,
40 GdkEventExpose *event);
41 static gint gtk_range_button_press (GtkWidget *widget,
42 GdkEventButton *event);
43 static gint gtk_range_button_release (GtkWidget *widget,
44 GdkEventButton *event);
45 static gint gtk_range_motion_notify (GtkWidget *widget,
46 GdkEventMotion *event);
47 static gint gtk_range_key_press (GtkWidget *widget,
49 static gint gtk_range_enter_notify (GtkWidget *widget,
50 GdkEventCrossing *event);
51 static gint gtk_range_leave_notify (GtkWidget *widget,
52 GdkEventCrossing *event);
53 static gint gtk_range_focus_in (GtkWidget *widget,
54 GdkEventFocus *event);
55 static gint gtk_range_focus_out (GtkWidget *widget,
56 GdkEventFocus *event);
57 static void gtk_range_style_set (GtkWidget *widget,
58 GtkStyle *previous_style);
60 static void gtk_real_range_draw_trough (GtkRange *range);
61 static void gtk_real_range_draw_slider (GtkRange *range);
62 static gint gtk_real_range_timer (GtkRange *range);
63 static gint gtk_range_scroll (GtkRange *range,
66 static void gtk_range_add_timer (GtkRange *range);
67 static void gtk_range_remove_timer (GtkRange *range);
69 static void gtk_range_adjustment_changed (GtkAdjustment *adjustment,
71 static void gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
74 static void gtk_range_trough_hdims (GtkRange *range,
77 static void gtk_range_trough_vdims (GtkRange *range,
81 static GtkWidgetClass *parent_class = NULL;
85 gtk_range_get_type (void)
87 static guint range_type = 0;
91 GtkTypeInfo range_info =
95 sizeof (GtkRangeClass),
96 (GtkClassInitFunc) gtk_range_class_init,
97 (GtkObjectInitFunc) gtk_range_init,
102 range_type = gtk_type_unique (gtk_widget_get_type (), &range_info);
109 gtk_range_class_init (GtkRangeClass *class)
111 GtkObjectClass *object_class;
112 GtkWidgetClass *widget_class;
114 object_class = (GtkObjectClass*) class;
115 widget_class = (GtkWidgetClass*) class;
117 parent_class = gtk_type_class (gtk_widget_get_type ());
119 object_class->finalize = gtk_range_finalize;
121 widget_class->draw = gtk_range_draw;
122 widget_class->draw_focus = gtk_range_draw_focus;
123 widget_class->unrealize = gtk_range_unrealize;
124 widget_class->expose_event = gtk_range_expose;
125 widget_class->button_press_event = gtk_range_button_press;
126 widget_class->button_release_event = gtk_range_button_release;
127 widget_class->motion_notify_event = gtk_range_motion_notify;
128 widget_class->key_press_event = gtk_range_key_press;
129 widget_class->enter_notify_event = gtk_range_enter_notify;
130 widget_class->leave_notify_event = gtk_range_leave_notify;
131 widget_class->focus_in_event = gtk_range_focus_in;
132 widget_class->focus_out_event = gtk_range_focus_out;
133 widget_class->style_set = gtk_range_style_set;
135 class->slider_width = 11;
136 class->stepper_size = 11;
137 class->stepper_slider_spacing = 1;
138 class->min_slider_size = 7;
141 class->step_forw = 3;
142 class->step_back = 4;
143 class->draw_background = NULL;
144 class->draw_trough = gtk_real_range_draw_trough;
145 class->draw_slider = gtk_real_range_draw_slider;
146 class->draw_step_forw = NULL;
147 class->draw_step_back = NULL;
148 class->trough_click = NULL;
149 class->trough_keys = NULL;
150 class->motion = NULL;
151 class->timer = gtk_real_range_timer;
155 gtk_range_init (GtkRange *range)
157 range->trough = NULL;
158 range->slider = NULL;
159 range->step_forw = NULL;
160 range->step_back = NULL;
162 range->x_click_point = 0;
163 range->y_click_point = 0;
166 range->policy = GTK_UPDATE_CONTINUOUS;
167 range->scroll_type = GTK_SCROLL_NONE;
169 range->click_child = 0;
170 range->need_timer = FALSE;
172 range->old_value = 0.0;
173 range->old_lower = 0.0;
174 range->old_upper = 0.0;
175 range->old_page_size = 0.0;
176 range->adjustment = NULL;
180 gtk_range_get_adjustment (GtkRange *range)
182 g_return_val_if_fail (range != NULL, NULL);
183 g_return_val_if_fail (GTK_IS_RANGE (range), NULL);
185 return range->adjustment;
189 gtk_range_set_update_policy (GtkRange *range,
190 GtkUpdateType policy)
192 g_return_if_fail (range != NULL);
193 g_return_if_fail (GTK_IS_RANGE (range));
195 range->policy = policy;
199 gtk_range_set_adjustment (GtkRange *range,
200 GtkAdjustment *adjustment)
202 g_return_if_fail (range != NULL);
203 g_return_if_fail (GTK_IS_RANGE (range));
205 if (range->adjustment != adjustment)
207 if (range->adjustment)
209 gtk_signal_disconnect_by_data (GTK_OBJECT (range->adjustment),
211 gtk_object_unref (GTK_OBJECT (range->adjustment));
213 range->adjustment = adjustment;
216 gtk_object_ref (GTK_OBJECT (adjustment));
217 gtk_object_sink (GTK_OBJECT (adjustment));
219 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
220 (GtkSignalFunc) gtk_range_adjustment_changed,
222 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
223 (GtkSignalFunc) gtk_range_adjustment_value_changed,
226 range->old_value = adjustment->value;
227 range->old_lower = adjustment->lower;
228 range->old_upper = adjustment->upper;
229 range->old_page_size = adjustment->page_size;
231 gtk_range_adjustment_changed (adjustment, (gpointer) range);
237 gtk_range_draw_background (GtkRange *range)
239 g_return_if_fail (range != NULL);
240 g_return_if_fail (GTK_IS_RANGE (range));
242 if (range->trough && RANGE_CLASS (range)->draw_background)
243 (* RANGE_CLASS (range)->draw_background) (range);
247 gtk_range_draw_trough (GtkRange *range)
249 g_return_if_fail (range != NULL);
250 g_return_if_fail (GTK_IS_RANGE (range));
252 if (range->trough && RANGE_CLASS (range)->draw_trough)
253 (* RANGE_CLASS (range)->draw_trough) (range);
257 gtk_range_draw_slider (GtkRange *range)
259 g_return_if_fail (range != NULL);
260 g_return_if_fail (GTK_IS_RANGE (range));
262 if (range->slider && RANGE_CLASS (range)->draw_slider)
263 (* RANGE_CLASS (range)->draw_slider) (range);
267 gtk_range_draw_step_forw (GtkRange *range)
269 g_return_if_fail (range != NULL);
270 g_return_if_fail (GTK_IS_RANGE (range));
272 if (range->step_forw && RANGE_CLASS (range)->draw_step_forw)
273 (* RANGE_CLASS (range)->draw_step_forw) (range);
277 gtk_range_draw_step_back (GtkRange *range)
279 g_return_if_fail (range != NULL);
280 g_return_if_fail (GTK_IS_RANGE (range));
282 if (range->step_back && RANGE_CLASS (range)->draw_step_back)
283 (* RANGE_CLASS (range)->draw_step_back) (range);
287 gtk_range_slider_update (GtkRange *range)
289 g_return_if_fail (range != NULL);
290 g_return_if_fail (GTK_IS_RANGE (range));
292 if (RANGE_CLASS (range)->slider_update)
293 (* RANGE_CLASS (range)->slider_update) (range);
297 gtk_range_trough_click (GtkRange *range,
302 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
303 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
305 if (RANGE_CLASS (range)->trough_click)
306 return (* RANGE_CLASS (range)->trough_click) (range, x, y, jump_perc);
308 return GTK_TROUGH_NONE;
312 gtk_range_default_hslider_update (GtkRange *range)
318 g_return_if_fail (range != NULL);
319 g_return_if_fail (GTK_IS_RANGE (range));
321 if (GTK_WIDGET_REALIZED (range))
323 gtk_range_trough_hdims (range, &left, &right);
326 if (range->adjustment->value < range->adjustment->lower)
328 range->adjustment->value = range->adjustment->lower;
329 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
331 else if (range->adjustment->value > range->adjustment->upper)
333 range->adjustment->value = range->adjustment->upper;
334 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
337 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
338 x += ((right - left) * (range->adjustment->value - range->adjustment->lower) /
339 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
346 gdk_window_move (range->slider, x, GTK_WIDGET (range)->style->klass->ythickness);
351 gtk_range_default_vslider_update (GtkRange *range)
357 g_return_if_fail (range != NULL);
358 g_return_if_fail (GTK_IS_RANGE (range));
360 if (GTK_WIDGET_REALIZED (range))
362 gtk_range_trough_vdims (range, &top, &bottom);
365 if (range->adjustment->value < range->adjustment->lower)
367 range->adjustment->value = range->adjustment->lower;
368 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
370 else if (range->adjustment->value > range->adjustment->upper)
372 range->adjustment->value = range->adjustment->upper;
373 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
376 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
377 y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) /
378 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
385 gdk_window_move (range->slider, GTK_WIDGET (range)->style->klass->xthickness, y);
390 gtk_range_default_htrough_click (GtkRange *range,
402 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
403 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
405 ythickness = GTK_WIDGET (range)->style->klass->ythickness;
407 gtk_range_trough_hdims (range, &left, &right);
408 gdk_window_get_size (range->slider, &slider_length, NULL);
409 right += slider_length;
411 if ((x > left) && (y > ythickness))
413 gdk_window_get_size (range->trough, &trough_width, &trough_height);
415 if ((x < right) && (y < (trough_height - ythickness)))
419 *jump_perc = ((gdouble) (x - left)) / ((gdouble) (right - left));
420 return GTK_TROUGH_JUMP;
423 gdk_window_get_position (range->slider, &slider_x, NULL);
426 return GTK_TROUGH_START;
428 return GTK_TROUGH_END;
432 return GTK_TROUGH_NONE;
436 gtk_range_default_vtrough_click (GtkRange *range,
448 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
449 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
451 xthickness = GTK_WIDGET (range)->style->klass->xthickness;
453 gtk_range_trough_vdims (range, &top, &bottom);
454 gdk_window_get_size (range->slider, NULL, &slider_length);
455 bottom += slider_length;
457 if ((x > xthickness) && (y > top))
459 gdk_window_get_size (range->trough, &trough_width, &trough_height);
461 if ((x < (trough_width - xthickness) && (y < bottom)))
465 *jump_perc = ((gdouble) (y - top)) / ((gdouble) (bottom - top));
467 return GTK_TROUGH_JUMP;
470 gdk_window_get_position (range->slider, NULL, &slider_y);
473 return GTK_TROUGH_START;
475 return GTK_TROUGH_END;
479 return GTK_TROUGH_NONE;
483 gtk_range_default_hmotion (GtkRange *range,
489 gint slider_x, slider_y;
492 g_return_if_fail (range != NULL);
493 g_return_if_fail (GTK_IS_RANGE (range));
495 range = GTK_RANGE (range);
497 gdk_window_get_position (range->slider, &slider_x, &slider_y);
498 gtk_range_trough_hdims (range, &left, &right);
503 new_pos = slider_x + xdelta;
507 else if (new_pos > right)
510 old_value = range->adjustment->value;
511 range->adjustment->value = ((range->adjustment->upper -
512 range->adjustment->lower -
513 range->adjustment->page_size) *
514 (new_pos - left) / (right - left) +
515 range->adjustment->lower);
517 if (range->digits >= 0)
521 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
522 sscanf (buffer, "%f", &range->adjustment->value);
525 if (old_value != range->adjustment->value)
527 if (range->policy == GTK_UPDATE_CONTINUOUS)
529 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
533 gtk_range_slider_update (range);
534 gtk_range_draw_background (range);
536 if (range->policy == GTK_UPDATE_DELAYED)
538 gtk_range_remove_timer (range);
539 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
540 (GtkFunction) RANGE_CLASS (range)->timer,
548 gtk_range_default_vmotion (GtkRange *range,
554 gint slider_x, slider_y;
557 g_return_if_fail (range != NULL);
558 g_return_if_fail (GTK_IS_RANGE (range));
560 range = GTK_RANGE (range);
562 gdk_window_get_position (range->slider, &slider_x, &slider_y);
563 gtk_range_trough_vdims (range, &top, &bottom);
568 new_pos = slider_y + ydelta;
572 else if (new_pos > bottom)
575 old_value = range->adjustment->value;
576 range->adjustment->value = ((range->adjustment->upper -
577 range->adjustment->lower -
578 range->adjustment->page_size) *
579 (new_pos - top) / (bottom - top) +
580 range->adjustment->lower);
582 if (range->digits >= 0)
586 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
587 sscanf (buffer, "%f", &range->adjustment->value);
590 if (old_value != range->adjustment->value)
592 if (range->policy == GTK_UPDATE_CONTINUOUS)
594 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
598 gtk_range_slider_update (range);
599 gtk_range_draw_background (range);
601 if (range->policy == GTK_UPDATE_DELAYED)
603 gtk_range_remove_timer (range);
604 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
605 (GtkFunction) RANGE_CLASS (range)->timer,
614 gtk_range_finalize (GtkObject *object)
618 g_return_if_fail (object != NULL);
619 g_return_if_fail (GTK_IS_RANGE (object));
621 range = GTK_RANGE (object);
623 if (range->adjustment)
624 gtk_object_unref (GTK_OBJECT (range->adjustment));
626 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
630 gtk_range_draw (GtkWidget *widget,
635 g_return_if_fail (widget != NULL);
636 g_return_if_fail (GTK_IS_RANGE (widget));
637 g_return_if_fail (area != NULL);
639 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
641 range = GTK_RANGE (widget);
643 gtk_range_draw_background (range);
644 gtk_range_draw_trough (range);
645 gtk_range_draw_slider (range);
646 gtk_range_draw_step_forw (range);
647 gtk_range_draw_step_back (range);
652 gtk_range_draw_focus (GtkWidget *widget)
654 g_return_if_fail (widget != NULL);
655 g_return_if_fail (GTK_IS_RANGE (widget));
657 if (GTK_WIDGET_DRAWABLE (widget))
658 gtk_range_draw_trough (GTK_RANGE (widget));
662 gtk_range_unrealize (GtkWidget *widget)
666 g_return_if_fail (widget != NULL);
667 g_return_if_fail (GTK_IS_RANGE (widget));
669 range = GTK_RANGE (widget);
673 gdk_window_set_user_data (range->slider, NULL);
674 gdk_window_destroy (range->slider);
675 range->slider = NULL;
679 gdk_window_set_user_data (range->trough, NULL);
680 gdk_window_destroy (range->trough);
681 range->trough = NULL;
683 if (range->step_forw)
685 gdk_window_set_user_data (range->step_forw, NULL);
686 gdk_window_destroy (range->step_forw);
687 range->step_forw = NULL;
689 if (range->step_back)
691 gdk_window_set_user_data (range->step_back, NULL);
692 gdk_window_destroy (range->step_back);
693 range->step_back = NULL;
696 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
697 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
701 gtk_range_expose (GtkWidget *widget,
702 GdkEventExpose *event)
706 g_return_val_if_fail (widget != NULL, FALSE);
707 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
708 g_return_val_if_fail (event != NULL, FALSE);
710 range = GTK_RANGE (widget);
712 if (event->window == range->trough)
714 /* Don't redraw if we are only exposing the literal trough region.
715 * this may not work correctly if someone overrides the default
716 * trough-drawing handler. (Probably should really pass another
717 * argument - the redrawn area to all the drawing functions)
720 gint xt = widget->style->klass->xthickness;
721 gint yt = widget->style->klass->ythickness;
723 if (!((event->area.x >= xt) &&
724 (event->area.y >= yt) &&
725 (event->area.x + event->area.width <=
726 widget->allocation.width - xt) &&
727 (event->area.y + event->area.height <=
728 widget->allocation.height - xt)))
729 gtk_range_draw_trough (range);
731 else if (event->window == widget->window)
733 gtk_range_draw_background (range);
735 else if (event->window == range->slider)
737 gtk_range_draw_slider (range);
739 else if (event->window == range->step_forw)
741 gtk_range_draw_step_forw (range);
743 else if (event->window == range->step_back)
745 gtk_range_draw_step_back (range);
751 gtk_range_button_press (GtkWidget *widget,
752 GdkEventButton *event)
758 g_return_val_if_fail (widget != NULL, FALSE);
759 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
760 g_return_val_if_fail (event != NULL, FALSE);
762 if (!GTK_WIDGET_HAS_FOCUS (widget))
763 gtk_widget_grab_focus (widget);
766 range = GTK_RANGE (widget);
767 if (range->button == 0)
769 gtk_grab_add (widget);
771 range->button = event->button;
772 range->x_click_point = event->x;
773 range->y_click_point = event->y;
775 if (event->window == range->trough)
777 range->click_child = RANGE_CLASS (range)->trough;
779 if (range->button == 2)
780 trough_part = gtk_range_trough_click (range, event->x, event->y, &jump_perc);
782 trough_part = gtk_range_trough_click (range, event->x, event->y, NULL);
784 range->scroll_type = GTK_SCROLL_NONE;
785 if (trough_part == GTK_TROUGH_START)
786 range->scroll_type = GTK_SCROLL_PAGE_BACKWARD;
787 else if (trough_part == GTK_TROUGH_END)
788 range->scroll_type = GTK_SCROLL_PAGE_FORWARD;
789 else if (trough_part == GTK_TROUGH_JUMP &&
790 jump_perc >= 0 && jump_perc <= 1)
791 range->scroll_type = GTK_SCROLL_JUMP;
793 if (range->scroll_type != GTK_SCROLL_NONE)
795 gtk_range_scroll (range, jump_perc);
796 gtk_range_add_timer (range);
799 else if (event->window == range->slider)
801 range->click_child = RANGE_CLASS (range)->slider;
802 range->scroll_type = GTK_SCROLL_NONE;
804 else if (event->window == range->step_forw)
806 range->click_child = RANGE_CLASS (range)->step_forw;
807 range->scroll_type = GTK_SCROLL_STEP_FORWARD;
809 gtk_range_scroll (range, -1);
810 gtk_range_add_timer (range);
811 gtk_range_draw_step_forw (range);
813 else if (event->window == range->step_back)
815 range->click_child = RANGE_CLASS (range)->step_back;
816 range->scroll_type = GTK_SCROLL_STEP_BACKWARD;
818 gtk_range_scroll (range, -1);
819 gtk_range_add_timer (range);
820 gtk_range_draw_step_back (range);
828 gtk_range_button_release (GtkWidget *widget,
829 GdkEventButton *event)
833 g_return_val_if_fail (widget != NULL, FALSE);
834 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
835 g_return_val_if_fail (event != NULL, FALSE);
837 range = GTK_RANGE (widget);
839 if (range->button == event->button)
841 gtk_grab_remove (widget);
844 range->x_click_point = -1;
845 range->y_click_point = -1;
847 if (range->click_child == RANGE_CLASS (range)->slider)
849 if (range->policy == GTK_UPDATE_DELAYED)
850 gtk_range_remove_timer (range);
852 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
853 (range->old_value != range->adjustment->value))
854 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
856 else if ((range->click_child == RANGE_CLASS (range)->trough) ||
857 (range->click_child == RANGE_CLASS (range)->step_forw) ||
858 (range->click_child == RANGE_CLASS (range)->step_back))
860 gtk_range_remove_timer (range);
862 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
863 (range->old_value != range->adjustment->value))
864 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
866 if (range->click_child == RANGE_CLASS (range)->step_forw)
868 range->click_child = 0;
869 gtk_range_draw_step_forw (range);
871 else if (range->click_child == RANGE_CLASS (range)->step_back)
873 range->click_child = 0;
874 gtk_range_draw_step_back (range);
878 range->click_child = 0;
885 gtk_range_motion_notify (GtkWidget *widget,
886 GdkEventMotion *event)
889 GdkModifierType mods;
892 g_return_val_if_fail (widget != NULL, FALSE);
893 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
894 g_return_val_if_fail (event != NULL, FALSE);
896 range = GTK_RANGE (widget);
898 if (range->click_child == RANGE_CLASS (range)->slider)
903 if (event->is_hint || (event->window != range->slider))
904 gdk_window_get_pointer (range->slider, &x, &y, &mods);
906 switch (range->button)
909 mask = GDK_BUTTON1_MASK;
912 mask = GDK_BUTTON2_MASK;
915 mask = GDK_BUTTON3_MASK;
924 if (RANGE_CLASS (range)->motion)
925 (* RANGE_CLASS (range)->motion) (range, x - range->x_click_point, y - range->y_click_point);
933 gtk_range_key_press (GtkWidget *widget,
938 GtkScrollType scroll = GTK_SCROLL_NONE;
939 GtkTroughType pos = GTK_TROUGH_NONE;
941 g_return_val_if_fail (widget != NULL, FALSE);
942 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
943 g_return_val_if_fail (event != NULL, FALSE);
945 range = GTK_RANGE (widget);
948 if (RANGE_CLASS (range)->trough_keys)
949 return_val = (* RANGE_CLASS (range)->trough_keys) (range, event, &scroll, &pos);
953 if (scroll != GTK_SCROLL_NONE)
955 range->scroll_type = scroll;
956 gtk_range_scroll (range, -1);
957 if (range->old_value != range->adjustment->value)
959 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
960 switch (range->scroll_type)
962 case GTK_SCROLL_STEP_BACKWARD:
963 gtk_range_draw_step_back (range);
965 case GTK_SCROLL_STEP_FORWARD:
966 gtk_range_draw_step_forw (range);
971 if (pos != GTK_TROUGH_NONE)
973 if (pos == GTK_TROUGH_START)
974 range->adjustment->value = range->adjustment->lower;
975 else if (pos == GTK_TROUGH_END)
976 range->adjustment->value =
977 range->adjustment->upper - range->adjustment->page_size;
979 if (range->old_value != range->adjustment->value)
981 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment),
984 gtk_range_slider_update (range);
985 gtk_range_draw_background (range);
993 gtk_range_enter_notify (GtkWidget *widget,
994 GdkEventCrossing *event)
998 g_return_val_if_fail (widget != NULL, FALSE);
999 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1000 g_return_val_if_fail (event != NULL, FALSE);
1002 range = GTK_RANGE (widget);
1004 if (event->window == range->trough)
1006 range->in_child = RANGE_CLASS (range)->trough;
1008 else if (event->window == range->slider)
1010 range->in_child = RANGE_CLASS (range)->slider;
1012 if ((range->click_child == 0) ||
1013 (range->click_child == RANGE_CLASS (range)->trough))
1014 gtk_range_draw_slider (range);
1016 else if (event->window == range->step_forw)
1018 range->in_child = RANGE_CLASS (range)->step_forw;
1020 if ((range->click_child == 0) ||
1021 (range->click_child == RANGE_CLASS (range)->trough))
1022 gtk_range_draw_step_forw (range);
1024 else if (event->window == range->step_back)
1026 range->in_child = RANGE_CLASS (range)->step_back;
1028 if ((range->click_child == 0) ||
1029 (range->click_child == RANGE_CLASS (range)->trough))
1030 gtk_range_draw_step_back (range);
1037 gtk_range_leave_notify (GtkWidget *widget,
1038 GdkEventCrossing *event)
1042 g_return_val_if_fail (widget != NULL, FALSE);
1043 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1044 g_return_val_if_fail (event != NULL, FALSE);
1046 range = GTK_RANGE (widget);
1048 range->in_child = 0;
1050 if (event->window == range->trough)
1053 else if (event->window == range->slider)
1055 if ((range->click_child == 0) ||
1056 (range->click_child == RANGE_CLASS (range)->trough))
1057 gtk_range_draw_slider (range);
1059 else if (event->window == range->step_forw)
1061 if ((range->click_child == 0) ||
1062 (range->click_child == RANGE_CLASS (range)->trough))
1063 gtk_range_draw_step_forw (range);
1065 else if (event->window == range->step_back)
1067 if ((range->click_child == 0) ||
1068 (range->click_child == RANGE_CLASS (range)->trough))
1069 gtk_range_draw_step_back (range);
1076 gtk_range_focus_in (GtkWidget *widget,
1077 GdkEventFocus *event)
1079 g_return_val_if_fail (widget != NULL, FALSE);
1080 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1081 g_return_val_if_fail (event != NULL, FALSE);
1083 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1084 gtk_widget_draw_focus (widget);
1090 gtk_range_focus_out (GtkWidget *widget,
1091 GdkEventFocus *event)
1093 g_return_val_if_fail (widget != NULL, FALSE);
1094 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1095 g_return_val_if_fail (event != NULL, FALSE);
1097 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1098 gtk_widget_draw_focus (widget);
1104 gtk_real_range_draw_trough (GtkRange *range)
1106 g_return_if_fail (range != NULL);
1107 g_return_if_fail (GTK_IS_RANGE (range));
1111 gtk_draw_shadow (GTK_WIDGET (range)->style, range->trough,
1112 GTK_STATE_NORMAL, GTK_SHADOW_IN,
1115 if (GTK_WIDGET_HAS_FOCUS (range))
1116 gdk_draw_rectangle (GTK_WIDGET (range)->window,
1117 GTK_WIDGET (range)->style->black_gc,
1119 GTK_WIDGET (range)->allocation.width - 1,
1120 GTK_WIDGET (range)->allocation.height - 1);
1121 else if (range->trough != GTK_WIDGET (range)->window)
1122 gdk_draw_rectangle (GTK_WIDGET (range)->window,
1123 GTK_WIDGET (range)->style->bg_gc[GTK_STATE_NORMAL],
1125 GTK_WIDGET (range)->allocation.width - 1,
1126 GTK_WIDGET (range)->allocation.height - 1);
1131 gtk_real_range_draw_slider (GtkRange *range)
1133 GtkStateType state_type;
1135 g_return_if_fail (range != NULL);
1136 g_return_if_fail (GTK_IS_RANGE (range));
1140 if ((range->in_child == RANGE_CLASS (range)->slider) ||
1141 (range->click_child == RANGE_CLASS (range)->slider))
1142 state_type = GTK_STATE_PRELIGHT;
1144 state_type = GTK_STATE_NORMAL;
1146 gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
1147 gdk_window_clear (range->slider);
1149 gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
1150 state_type, GTK_SHADOW_OUT,
1156 gtk_real_range_timer (GtkRange *range)
1160 g_return_val_if_fail (range != NULL, FALSE);
1161 g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
1164 if (range->click_child == RANGE_CLASS (range)->slider)
1166 if (range->policy == GTK_UPDATE_DELAYED)
1167 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
1172 GdkModifierType mods, mask;
1177 if (range->need_timer)
1178 range->timer = gtk_timeout_add (SCROLL_TIMER_LENGTH,
1179 (GtkFunction) RANGE_CLASS (range)->timer,
1183 range->need_timer = FALSE;
1186 switch (range->button)
1189 mask = GDK_BUTTON1_MASK;
1192 mask = GDK_BUTTON2_MASK;
1195 mask = GDK_BUTTON3_MASK;
1202 gdk_window_get_pointer (range->slider, NULL, NULL, &mods);
1205 return_val = gtk_range_scroll (range, -1);
1212 gtk_range_scroll (GtkRange *range,
1218 g_return_val_if_fail (range != NULL, FALSE);
1219 g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
1221 new_value = range->adjustment->value;
1224 switch (range->scroll_type)
1226 case GTK_SCROLL_NONE:
1229 case GTK_SCROLL_JUMP:
1230 if (jump_perc >= 0 && jump_perc <= 1)
1232 new_value = (range->adjustment->lower +
1233 (range->adjustment->upper - range->adjustment->page_size -
1234 range->adjustment->lower) * jump_perc);
1238 case GTK_SCROLL_STEP_BACKWARD:
1239 new_value -= range->adjustment->step_increment;
1240 if (new_value <= range->adjustment->lower)
1242 new_value = range->adjustment->lower;
1248 case GTK_SCROLL_STEP_FORWARD:
1249 new_value += range->adjustment->step_increment;
1250 if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
1252 new_value = range->adjustment->upper - range->adjustment->page_size;
1258 case GTK_SCROLL_PAGE_BACKWARD:
1259 new_value -= range->adjustment->page_increment;
1260 if (new_value <= range->adjustment->lower)
1262 new_value = range->adjustment->lower;
1268 case GTK_SCROLL_PAGE_FORWARD:
1269 new_value += range->adjustment->page_increment;
1270 if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
1272 new_value = range->adjustment->upper - range->adjustment->page_size;
1279 if (new_value != range->adjustment->value)
1281 range->adjustment->value = new_value;
1283 if ((range->policy == GTK_UPDATE_CONTINUOUS) ||
1284 (!return_val && (range->policy == GTK_UPDATE_DELAYED)))
1286 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
1290 gtk_range_slider_update (range);
1291 gtk_range_draw_background (range);
1300 gtk_range_add_timer (GtkRange *range)
1302 g_return_if_fail (range != NULL);
1303 g_return_if_fail (GTK_IS_RANGE (range));
1307 range->need_timer = TRUE;
1308 range->timer = gtk_timeout_add (SCROLL_INITIAL_DELAY,
1309 (GtkFunction) RANGE_CLASS (range)->timer,
1315 gtk_range_remove_timer (GtkRange *range)
1317 g_return_if_fail (range != NULL);
1318 g_return_if_fail (GTK_IS_RANGE (range));
1322 gtk_timeout_remove (range->timer);
1325 range->need_timer = FALSE;
1329 gtk_range_adjustment_changed (GtkAdjustment *adjustment,
1334 g_return_if_fail (adjustment != NULL);
1335 g_return_if_fail (data != NULL);
1337 range = GTK_RANGE (data);
1339 if (((range->old_lower != adjustment->lower) ||
1340 (range->old_upper != adjustment->upper) ||
1341 (range->old_page_size != adjustment->page_size)) &&
1342 (range->old_value == adjustment->value))
1344 if ((adjustment->lower == adjustment->upper) ||
1345 (range->old_lower == (range->old_upper - range->old_page_size)))
1347 adjustment->value = adjustment->lower;
1348 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed");
1352 if ((range->old_value != adjustment->value) ||
1353 (range->old_lower != adjustment->lower) ||
1354 (range->old_upper != adjustment->upper) ||
1355 (range->old_page_size != adjustment->page_size))
1357 gtk_range_slider_update (range);
1358 gtk_range_draw_background (range);
1360 range->old_value = adjustment->value;
1361 range->old_lower = adjustment->lower;
1362 range->old_upper = adjustment->upper;
1363 range->old_page_size = adjustment->page_size;
1368 gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
1373 g_return_if_fail (adjustment != NULL);
1374 g_return_if_fail (data != NULL);
1376 range = GTK_RANGE (data);
1378 if (range->old_value != adjustment->value)
1380 gtk_range_slider_update (range);
1381 gtk_range_draw_background (range);
1383 range->old_value = adjustment->value;
1389 gtk_range_trough_hdims (GtkRange *range,
1399 g_return_if_fail (range != NULL);
1401 gdk_window_get_size (range->trough, &trough_width, NULL);
1402 gdk_window_get_size (range->slider, &slider_length, NULL);
1404 tleft = GTK_WIDGET (range)->style->klass->xthickness;
1405 tright = trough_width - slider_length - GTK_WIDGET (range)->style->klass->xthickness;
1407 if (range->step_back)
1409 gdk_window_get_size (range->step_back, &tmp_width, NULL);
1410 tleft += (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
1413 if (range->step_forw)
1415 gdk_window_get_size (range->step_forw, &tmp_width, NULL);
1416 tright -= (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
1426 gtk_range_trough_vdims (GtkRange *range,
1436 g_return_if_fail (range != NULL);
1438 gdk_window_get_size (range->trough, NULL, &trough_height);
1439 gdk_window_get_size (range->slider, NULL, &slider_length);
1441 ttop = GTK_WIDGET (range)->style->klass->ythickness;
1442 tbottom = trough_height - slider_length - GTK_WIDGET (range)->style->klass->ythickness;
1444 if (range->step_back)
1446 gdk_window_get_size (range->step_back, NULL, &tmp_height);
1447 ttop += (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
1450 if (range->step_forw)
1452 gdk_window_get_size (range->step_forw, NULL, &tmp_height);
1453 tbottom -= (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
1463 gtk_range_style_set (GtkWidget *widget,
1464 GtkStyle *previous_style)
1468 g_return_if_fail (widget != NULL);
1469 g_return_if_fail (GTK_IS_RANGE (widget));
1471 range = GTK_RANGE (widget);
1473 if (GTK_WIDGET_REALIZED (widget) &&
1474 !GTK_WIDGET_NO_WINDOW (widget))
1478 gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
1479 if (GTK_WIDGET_DRAWABLE (widget))
1480 gdk_window_clear (range->trough);
1482 /* The draw will take care of the slider */
1484 if (range->step_forw)
1486 gtk_style_set_background (widget->style, range->step_forw, GTK_STATE_ACTIVE);
1487 if (GTK_WIDGET_DRAWABLE (widget))
1488 gdk_window_clear (range->step_forw);
1490 if (range->step_back)
1492 gtk_style_set_background (widget->style, range->step_back, GTK_STATE_ACTIVE);
1493 if (GTK_WIDGET_DRAWABLE (widget))
1494 gdk_window_clear (range->step_back);