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,
98 /* reserved_1 */ NULL,
99 /* reserved_2 */ NULL,
100 (GtkClassInitFunc) NULL,
103 range_type = gtk_type_unique (gtk_widget_get_type (), &range_info);
110 gtk_range_class_init (GtkRangeClass *class)
112 GtkObjectClass *object_class;
113 GtkWidgetClass *widget_class;
115 object_class = (GtkObjectClass*) class;
116 widget_class = (GtkWidgetClass*) class;
118 parent_class = gtk_type_class (gtk_widget_get_type ());
120 object_class->finalize = gtk_range_finalize;
122 widget_class->draw = gtk_range_draw;
123 widget_class->draw_focus = gtk_range_draw_focus;
124 widget_class->unrealize = gtk_range_unrealize;
125 widget_class->expose_event = gtk_range_expose;
126 widget_class->button_press_event = gtk_range_button_press;
127 widget_class->button_release_event = gtk_range_button_release;
128 widget_class->motion_notify_event = gtk_range_motion_notify;
129 widget_class->key_press_event = gtk_range_key_press;
130 widget_class->enter_notify_event = gtk_range_enter_notify;
131 widget_class->leave_notify_event = gtk_range_leave_notify;
132 widget_class->focus_in_event = gtk_range_focus_in;
133 widget_class->focus_out_event = gtk_range_focus_out;
134 widget_class->style_set = gtk_range_style_set;
136 class->slider_width = 11;
137 class->stepper_size = 11;
138 class->stepper_slider_spacing = 1;
139 class->min_slider_size = 7;
142 class->step_forw = 3;
143 class->step_back = 4;
144 class->draw_background = NULL;
145 class->clear_background = NULL;
146 class->draw_trough = gtk_real_range_draw_trough;
147 class->draw_slider = gtk_real_range_draw_slider;
148 class->draw_step_forw = NULL;
149 class->draw_step_back = NULL;
150 class->trough_click = NULL;
151 class->trough_keys = NULL;
152 class->motion = NULL;
153 class->timer = gtk_real_range_timer;
157 gtk_range_init (GtkRange *range)
159 range->trough = NULL;
160 range->slider = NULL;
161 range->step_forw = NULL;
162 range->step_back = NULL;
164 range->x_click_point = 0;
165 range->y_click_point = 0;
168 range->policy = GTK_UPDATE_CONTINUOUS;
169 range->scroll_type = GTK_SCROLL_NONE;
171 range->click_child = 0;
172 range->need_timer = FALSE;
174 range->old_value = 0.0;
175 range->old_lower = 0.0;
176 range->old_upper = 0.0;
177 range->old_page_size = 0.0;
178 range->adjustment = NULL;
182 gtk_range_get_adjustment (GtkRange *range)
184 g_return_val_if_fail (range != NULL, NULL);
185 g_return_val_if_fail (GTK_IS_RANGE (range), NULL);
187 return range->adjustment;
191 gtk_range_set_update_policy (GtkRange *range,
192 GtkUpdateType policy)
194 g_return_if_fail (range != NULL);
195 g_return_if_fail (GTK_IS_RANGE (range));
197 range->policy = policy;
201 gtk_range_set_adjustment (GtkRange *range,
202 GtkAdjustment *adjustment)
204 g_return_if_fail (range != NULL);
205 g_return_if_fail (GTK_IS_RANGE (range));
207 if (range->adjustment != adjustment)
209 if (range->adjustment)
211 gtk_signal_disconnect_by_data (GTK_OBJECT (range->adjustment),
213 gtk_object_unref (GTK_OBJECT (range->adjustment));
215 range->adjustment = adjustment;
218 gtk_object_ref (GTK_OBJECT (adjustment));
219 gtk_object_sink (GTK_OBJECT (adjustment));
221 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
222 (GtkSignalFunc) gtk_range_adjustment_changed,
224 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
225 (GtkSignalFunc) gtk_range_adjustment_value_changed,
228 range->old_value = adjustment->value;
229 range->old_lower = adjustment->lower;
230 range->old_upper = adjustment->upper;
231 range->old_page_size = adjustment->page_size;
233 gtk_range_adjustment_changed (adjustment, (gpointer) range);
239 gtk_range_draw_background (GtkRange *range)
241 g_return_if_fail (range != NULL);
242 g_return_if_fail (GTK_IS_RANGE (range));
244 if (range->trough && RANGE_CLASS (range)->draw_background)
245 (* RANGE_CLASS (range)->draw_background) (range);
249 gtk_range_clear_background (GtkRange *range)
251 g_return_if_fail (range != NULL);
252 g_return_if_fail (GTK_IS_RANGE (range));
254 if (range->trough && RANGE_CLASS (range)->clear_background)
255 (* RANGE_CLASS (range)->clear_background) (range);
259 gtk_range_draw_trough (GtkRange *range)
261 g_return_if_fail (range != NULL);
262 g_return_if_fail (GTK_IS_RANGE (range));
264 if (range->trough && RANGE_CLASS (range)->draw_trough)
265 (* RANGE_CLASS (range)->draw_trough) (range);
269 gtk_range_draw_slider (GtkRange *range)
271 g_return_if_fail (range != NULL);
272 g_return_if_fail (GTK_IS_RANGE (range));
274 if (range->slider && RANGE_CLASS (range)->draw_slider)
275 (* RANGE_CLASS (range)->draw_slider) (range);
279 gtk_range_draw_step_forw (GtkRange *range)
281 g_return_if_fail (range != NULL);
282 g_return_if_fail (GTK_IS_RANGE (range));
284 if (range->step_forw && RANGE_CLASS (range)->draw_step_forw)
285 (* RANGE_CLASS (range)->draw_step_forw) (range);
289 gtk_range_draw_step_back (GtkRange *range)
291 g_return_if_fail (range != NULL);
292 g_return_if_fail (GTK_IS_RANGE (range));
294 if (range->step_back && RANGE_CLASS (range)->draw_step_back)
295 (* RANGE_CLASS (range)->draw_step_back) (range);
299 gtk_range_slider_update (GtkRange *range)
301 g_return_if_fail (range != NULL);
302 g_return_if_fail (GTK_IS_RANGE (range));
304 if (RANGE_CLASS (range)->slider_update)
305 (* RANGE_CLASS (range)->slider_update) (range);
309 gtk_range_trough_click (GtkRange *range,
314 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
315 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
317 if (RANGE_CLASS (range)->trough_click)
318 return (* RANGE_CLASS (range)->trough_click) (range, x, y, jump_perc);
320 return GTK_TROUGH_NONE;
324 gtk_range_default_hslider_update (GtkRange *range)
330 g_return_if_fail (range != NULL);
331 g_return_if_fail (GTK_IS_RANGE (range));
333 if (GTK_WIDGET_REALIZED (range))
335 gtk_range_trough_hdims (range, &left, &right);
338 if (range->adjustment->value < range->adjustment->lower)
340 range->adjustment->value = range->adjustment->lower;
341 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
343 else if (range->adjustment->value > range->adjustment->upper)
345 range->adjustment->value = range->adjustment->upper;
346 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
349 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
350 x += ((right - left) * (range->adjustment->value - range->adjustment->lower) /
351 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
358 gdk_window_move (range->slider, x, GTK_WIDGET (range)->style->klass->ythickness);
363 gtk_range_default_vslider_update (GtkRange *range)
369 g_return_if_fail (range != NULL);
370 g_return_if_fail (GTK_IS_RANGE (range));
372 if (GTK_WIDGET_REALIZED (range))
374 gtk_range_trough_vdims (range, &top, &bottom);
377 if (range->adjustment->value < range->adjustment->lower)
379 range->adjustment->value = range->adjustment->lower;
380 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
382 else if (range->adjustment->value > range->adjustment->upper)
384 range->adjustment->value = range->adjustment->upper;
385 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
388 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
389 y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) /
390 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
397 gdk_window_move (range->slider, GTK_WIDGET (range)->style->klass->xthickness, y);
402 gtk_range_default_htrough_click (GtkRange *range,
414 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
415 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
417 ythickness = GTK_WIDGET (range)->style->klass->ythickness;
419 gtk_range_trough_hdims (range, &left, &right);
420 gdk_window_get_size (range->slider, &slider_length, NULL);
421 right += slider_length;
423 if ((x > left) && (y > ythickness))
425 gdk_window_get_size (range->trough, &trough_width, &trough_height);
427 if ((x < right) && (y < (trough_height - ythickness)))
431 *jump_perc = ((gdouble) (x - left)) / ((gdouble) (right - left));
432 return GTK_TROUGH_JUMP;
435 gdk_window_get_position (range->slider, &slider_x, NULL);
438 return GTK_TROUGH_START;
440 return GTK_TROUGH_END;
444 return GTK_TROUGH_NONE;
448 gtk_range_default_vtrough_click (GtkRange *range,
460 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
461 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
463 xthickness = GTK_WIDGET (range)->style->klass->xthickness;
465 gtk_range_trough_vdims (range, &top, &bottom);
466 gdk_window_get_size (range->slider, NULL, &slider_length);
467 bottom += slider_length;
469 if ((x > xthickness) && (y > top))
471 gdk_window_get_size (range->trough, &trough_width, &trough_height);
473 if ((x < (trough_width - xthickness) && (y < bottom)))
477 *jump_perc = ((gdouble) (y - top)) / ((gdouble) (bottom - top));
479 return GTK_TROUGH_JUMP;
482 gdk_window_get_position (range->slider, NULL, &slider_y);
485 return GTK_TROUGH_START;
487 return GTK_TROUGH_END;
491 return GTK_TROUGH_NONE;
495 gtk_range_default_hmotion (GtkRange *range,
501 gint slider_x, slider_y;
504 g_return_if_fail (range != NULL);
505 g_return_if_fail (GTK_IS_RANGE (range));
507 range = GTK_RANGE (range);
509 gdk_window_get_position (range->slider, &slider_x, &slider_y);
510 gtk_range_trough_hdims (range, &left, &right);
515 new_pos = slider_x + xdelta;
519 else if (new_pos > right)
522 old_value = range->adjustment->value;
523 range->adjustment->value = ((range->adjustment->upper -
524 range->adjustment->lower -
525 range->adjustment->page_size) *
526 (new_pos - left) / (right - left) +
527 range->adjustment->lower);
529 if (range->digits >= 0)
533 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
534 sscanf (buffer, "%f", &range->adjustment->value);
537 if (old_value != range->adjustment->value)
539 if (range->policy == GTK_UPDATE_CONTINUOUS)
541 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
545 gtk_range_slider_update (range);
546 gtk_range_clear_background (range);
548 if (range->policy == GTK_UPDATE_DELAYED)
550 gtk_range_remove_timer (range);
551 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
552 (GtkFunction) RANGE_CLASS (range)->timer,
560 gtk_range_default_vmotion (GtkRange *range,
566 gint slider_x, slider_y;
569 g_return_if_fail (range != NULL);
570 g_return_if_fail (GTK_IS_RANGE (range));
572 range = GTK_RANGE (range);
574 gdk_window_get_position (range->slider, &slider_x, &slider_y);
575 gtk_range_trough_vdims (range, &top, &bottom);
580 new_pos = slider_y + ydelta;
584 else if (new_pos > bottom)
587 old_value = range->adjustment->value;
588 range->adjustment->value = ((range->adjustment->upper -
589 range->adjustment->lower -
590 range->adjustment->page_size) *
591 (new_pos - top) / (bottom - top) +
592 range->adjustment->lower);
594 if (range->digits >= 0)
598 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
599 sscanf (buffer, "%f", &range->adjustment->value);
602 if (old_value != range->adjustment->value)
604 if (range->policy == GTK_UPDATE_CONTINUOUS)
606 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
610 gtk_range_slider_update (range);
611 gtk_range_clear_background (range);
613 if (range->policy == GTK_UPDATE_DELAYED)
615 gtk_range_remove_timer (range);
616 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
617 (GtkFunction) RANGE_CLASS (range)->timer,
626 gtk_range_finalize (GtkObject *object)
630 g_return_if_fail (object != NULL);
631 g_return_if_fail (GTK_IS_RANGE (object));
633 range = GTK_RANGE (object);
635 if (range->adjustment)
636 gtk_object_unref (GTK_OBJECT (range->adjustment));
638 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
642 gtk_range_draw (GtkWidget *widget,
647 g_return_if_fail (widget != NULL);
648 g_return_if_fail (GTK_IS_RANGE (widget));
649 g_return_if_fail (area != NULL);
651 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
653 range = GTK_RANGE (widget);
655 gtk_range_draw_background (range);
656 gtk_range_draw_trough (range);
657 gtk_range_draw_slider (range);
658 gtk_range_draw_step_forw (range);
659 gtk_range_draw_step_back (range);
664 gtk_range_draw_focus (GtkWidget *widget)
666 g_return_if_fail (widget != NULL);
667 g_return_if_fail (GTK_IS_RANGE (widget));
669 if (GTK_WIDGET_DRAWABLE (widget))
670 gtk_range_draw_trough (GTK_RANGE (widget));
674 gtk_range_unrealize (GtkWidget *widget)
678 g_return_if_fail (widget != NULL);
679 g_return_if_fail (GTK_IS_RANGE (widget));
681 range = GTK_RANGE (widget);
685 gdk_window_set_user_data (range->slider, NULL);
686 gdk_window_destroy (range->slider);
687 range->slider = NULL;
691 gdk_window_set_user_data (range->trough, NULL);
692 gdk_window_destroy (range->trough);
693 range->trough = NULL;
695 if (range->step_forw)
697 gdk_window_set_user_data (range->step_forw, NULL);
698 gdk_window_destroy (range->step_forw);
699 range->step_forw = NULL;
701 if (range->step_back)
703 gdk_window_set_user_data (range->step_back, NULL);
704 gdk_window_destroy (range->step_back);
705 range->step_back = NULL;
708 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
709 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
713 gtk_range_expose (GtkWidget *widget,
714 GdkEventExpose *event)
718 g_return_val_if_fail (widget != NULL, FALSE);
719 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
720 g_return_val_if_fail (event != NULL, FALSE);
722 range = GTK_RANGE (widget);
724 if (event->window == range->trough)
726 /* Don't redraw if we are only exposing the literal trough region.
727 * this may not work correctly if someone overrides the default
728 * trough-drawing handler. (Probably should really pass another
729 * argument - the redrawn area to all the drawing functions)
731 gint xt = widget->style->klass->xthickness;
732 gint yt = widget->style->klass->ythickness;
734 if (!((event->area.x >= xt) &&
735 (event->area.y >= yt) &&
736 (event->area.x + event->area.width <=
737 widget->allocation.width - xt) &&
738 (event->area.y + event->area.height <=
739 widget->allocation.height - xt)))
740 gtk_range_draw_trough (range);
742 else if (event->window == widget->window)
744 gtk_range_draw_background (range);
746 else if (event->window == range->slider)
748 gtk_range_draw_slider (range);
750 else if (event->window == range->step_forw)
752 gtk_range_draw_step_forw (range);
754 else if (event->window == range->step_back)
756 gtk_range_draw_step_back (range);
762 gtk_range_button_press (GtkWidget *widget,
763 GdkEventButton *event)
769 g_return_val_if_fail (widget != NULL, FALSE);
770 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
771 g_return_val_if_fail (event != NULL, FALSE);
773 if (!GTK_WIDGET_HAS_FOCUS (widget))
774 gtk_widget_grab_focus (widget);
777 range = GTK_RANGE (widget);
778 if (range->button == 0)
780 gtk_grab_add (widget);
782 range->button = event->button;
783 range->x_click_point = event->x;
784 range->y_click_point = event->y;
786 if (event->window == range->trough)
788 range->click_child = RANGE_CLASS (range)->trough;
790 if (range->button == 2)
791 trough_part = gtk_range_trough_click (range, event->x, event->y, &jump_perc);
793 trough_part = gtk_range_trough_click (range, event->x, event->y, NULL);
795 range->scroll_type = GTK_SCROLL_NONE;
796 if (trough_part == GTK_TROUGH_START)
797 range->scroll_type = GTK_SCROLL_PAGE_BACKWARD;
798 else if (trough_part == GTK_TROUGH_END)
799 range->scroll_type = GTK_SCROLL_PAGE_FORWARD;
800 else if (trough_part == GTK_TROUGH_JUMP &&
801 jump_perc >= 0 && jump_perc <= 1)
802 range->scroll_type = GTK_SCROLL_JUMP;
804 if (range->scroll_type != GTK_SCROLL_NONE)
806 gtk_range_scroll (range, jump_perc);
807 gtk_range_add_timer (range);
810 else if (event->window == range->slider)
812 range->click_child = RANGE_CLASS (range)->slider;
813 range->scroll_type = GTK_SCROLL_NONE;
815 else if (event->window == range->step_forw)
817 range->click_child = RANGE_CLASS (range)->step_forw;
818 range->scroll_type = GTK_SCROLL_STEP_FORWARD;
820 gtk_range_scroll (range, -1);
821 gtk_range_add_timer (range);
822 gtk_range_draw_step_forw (range);
824 else if (event->window == range->step_back)
826 range->click_child = RANGE_CLASS (range)->step_back;
827 range->scroll_type = GTK_SCROLL_STEP_BACKWARD;
829 gtk_range_scroll (range, -1);
830 gtk_range_add_timer (range);
831 gtk_range_draw_step_back (range);
839 gtk_range_button_release (GtkWidget *widget,
840 GdkEventButton *event)
844 g_return_val_if_fail (widget != NULL, FALSE);
845 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
846 g_return_val_if_fail (event != NULL, FALSE);
848 range = GTK_RANGE (widget);
850 if (range->button == event->button)
852 gtk_grab_remove (widget);
855 range->x_click_point = -1;
856 range->y_click_point = -1;
858 if (range->click_child == RANGE_CLASS (range)->slider)
860 if (range->policy == GTK_UPDATE_DELAYED)
861 gtk_range_remove_timer (range);
863 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
864 (range->old_value != range->adjustment->value))
865 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
867 else if ((range->click_child == RANGE_CLASS (range)->trough) ||
868 (range->click_child == RANGE_CLASS (range)->step_forw) ||
869 (range->click_child == RANGE_CLASS (range)->step_back))
871 gtk_range_remove_timer (range);
873 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
874 (range->old_value != range->adjustment->value))
875 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
877 if (range->click_child == RANGE_CLASS (range)->step_forw)
879 range->click_child = 0;
880 gtk_range_draw_step_forw (range);
882 else if (range->click_child == RANGE_CLASS (range)->step_back)
884 range->click_child = 0;
885 gtk_range_draw_step_back (range);
889 range->click_child = 0;
896 gtk_range_motion_notify (GtkWidget *widget,
897 GdkEventMotion *event)
900 GdkModifierType mods;
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);
909 if (range->click_child == RANGE_CLASS (range)->slider)
914 if (event->is_hint || (event->window != range->slider))
915 gdk_window_get_pointer (range->slider, &x, &y, &mods);
917 switch (range->button)
920 mask = GDK_BUTTON1_MASK;
923 mask = GDK_BUTTON2_MASK;
926 mask = GDK_BUTTON3_MASK;
935 if (RANGE_CLASS (range)->motion)
936 (* RANGE_CLASS (range)->motion) (range, x - range->x_click_point, y - range->y_click_point);
944 gtk_range_key_press (GtkWidget *widget,
949 GtkScrollType scroll = GTK_SCROLL_NONE;
950 GtkTroughType pos = GTK_TROUGH_NONE;
952 g_return_val_if_fail (widget != NULL, FALSE);
953 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
954 g_return_val_if_fail (event != NULL, FALSE);
956 range = GTK_RANGE (widget);
959 if (RANGE_CLASS (range)->trough_keys)
960 return_val = (* RANGE_CLASS (range)->trough_keys) (range, event, &scroll, &pos);
964 if (scroll != GTK_SCROLL_NONE)
966 range->scroll_type = scroll;
967 gtk_range_scroll (range, -1);
968 if (range->old_value != range->adjustment->value)
970 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
971 switch (range->scroll_type)
973 case GTK_SCROLL_STEP_BACKWARD:
974 gtk_range_draw_step_back (range);
976 case GTK_SCROLL_STEP_FORWARD:
977 gtk_range_draw_step_forw (range);
982 if (pos != GTK_TROUGH_NONE)
984 if (pos == GTK_TROUGH_START)
985 range->adjustment->value = range->adjustment->lower;
986 else if (pos == GTK_TROUGH_END)
987 range->adjustment->value =
988 range->adjustment->upper - range->adjustment->page_size;
990 if (range->old_value != range->adjustment->value)
992 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment),
995 gtk_range_slider_update (range);
996 gtk_range_clear_background (range);
1004 gtk_range_enter_notify (GtkWidget *widget,
1005 GdkEventCrossing *event)
1009 g_return_val_if_fail (widget != NULL, FALSE);
1010 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1011 g_return_val_if_fail (event != NULL, FALSE);
1013 range = GTK_RANGE (widget);
1015 if (event->window == range->trough)
1017 range->in_child = RANGE_CLASS (range)->trough;
1019 else if (event->window == range->slider)
1021 range->in_child = RANGE_CLASS (range)->slider;
1023 if ((range->click_child == 0) ||
1024 (range->click_child == RANGE_CLASS (range)->trough))
1025 gtk_range_draw_slider (range);
1027 else if (event->window == range->step_forw)
1029 range->in_child = RANGE_CLASS (range)->step_forw;
1031 if ((range->click_child == 0) ||
1032 (range->click_child == RANGE_CLASS (range)->trough))
1033 gtk_range_draw_step_forw (range);
1035 else if (event->window == range->step_back)
1037 range->in_child = RANGE_CLASS (range)->step_back;
1039 if ((range->click_child == 0) ||
1040 (range->click_child == RANGE_CLASS (range)->trough))
1041 gtk_range_draw_step_back (range);
1048 gtk_range_leave_notify (GtkWidget *widget,
1049 GdkEventCrossing *event)
1053 g_return_val_if_fail (widget != NULL, FALSE);
1054 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1055 g_return_val_if_fail (event != NULL, FALSE);
1057 range = GTK_RANGE (widget);
1059 range->in_child = 0;
1061 if (event->window == range->trough)
1064 else if (event->window == range->slider)
1066 if ((range->click_child == 0) ||
1067 (range->click_child == RANGE_CLASS (range)->trough))
1068 gtk_range_draw_slider (range);
1070 else if (event->window == range->step_forw)
1072 if ((range->click_child == 0) ||
1073 (range->click_child == RANGE_CLASS (range)->trough))
1074 gtk_range_draw_step_forw (range);
1076 else if (event->window == range->step_back)
1078 if ((range->click_child == 0) ||
1079 (range->click_child == RANGE_CLASS (range)->trough))
1080 gtk_range_draw_step_back (range);
1087 gtk_range_focus_in (GtkWidget *widget,
1088 GdkEventFocus *event)
1090 g_return_val_if_fail (widget != NULL, FALSE);
1091 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1092 g_return_val_if_fail (event != NULL, FALSE);
1094 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1095 gtk_widget_draw_focus (widget);
1101 gtk_range_focus_out (GtkWidget *widget,
1102 GdkEventFocus *event)
1104 g_return_val_if_fail (widget != NULL, FALSE);
1105 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1106 g_return_val_if_fail (event != NULL, FALSE);
1108 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1109 gtk_widget_draw_focus (widget);
1115 gtk_real_range_draw_trough (GtkRange *range)
1117 g_return_if_fail (range != NULL);
1118 g_return_if_fail (GTK_IS_RANGE (range));
1122 gtk_paint_box (GTK_WIDGET (range)->style, range->trough,
1123 GTK_STATE_ACTIVE, GTK_SHADOW_IN,
1124 NULL, GTK_WIDGET(range), "trough",
1126 if (GTK_WIDGET_HAS_FOCUS (range))
1127 gtk_paint_focus (GTK_WIDGET (range)->style,
1129 NULL, GTK_WIDGET(range), "trough",
1135 gtk_real_range_draw_slider (GtkRange *range)
1137 GtkStateType state_type;
1139 g_return_if_fail (range != NULL);
1140 g_return_if_fail (GTK_IS_RANGE (range));
1144 if ((range->in_child == RANGE_CLASS (range)->slider) ||
1145 (range->click_child == RANGE_CLASS (range)->slider))
1146 state_type = GTK_STATE_PRELIGHT;
1148 state_type = GTK_STATE_NORMAL;
1149 gtk_paint_box (GTK_WIDGET (range)->style, range->slider,
1150 state_type, GTK_SHADOW_OUT,
1151 NULL, GTK_WIDGET (range), "slider",
1157 gtk_real_range_timer (GtkRange *range)
1161 g_return_val_if_fail (range != NULL, FALSE);
1162 g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
1165 if (range->click_child == RANGE_CLASS (range)->slider)
1167 if (range->policy == GTK_UPDATE_DELAYED)
1168 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
1173 GdkModifierType mods, mask;
1178 if (range->need_timer)
1179 range->timer = gtk_timeout_add (SCROLL_TIMER_LENGTH,
1180 (GtkFunction) RANGE_CLASS (range)->timer,
1184 range->need_timer = FALSE;
1187 switch (range->button)
1190 mask = GDK_BUTTON1_MASK;
1193 mask = GDK_BUTTON2_MASK;
1196 mask = GDK_BUTTON3_MASK;
1203 gdk_window_get_pointer (range->slider, NULL, NULL, &mods);
1206 return_val = gtk_range_scroll (range, -1);
1213 gtk_range_scroll (GtkRange *range,
1219 g_return_val_if_fail (range != NULL, FALSE);
1220 g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
1222 new_value = range->adjustment->value;
1225 switch (range->scroll_type)
1227 case GTK_SCROLL_NONE:
1230 case GTK_SCROLL_JUMP:
1231 if (jump_perc >= 0 && jump_perc <= 1)
1233 new_value = (range->adjustment->lower +
1234 (range->adjustment->upper - range->adjustment->page_size -
1235 range->adjustment->lower) * jump_perc);
1239 case GTK_SCROLL_STEP_BACKWARD:
1240 new_value -= range->adjustment->step_increment;
1241 if (new_value <= range->adjustment->lower)
1243 new_value = range->adjustment->lower;
1249 case GTK_SCROLL_STEP_FORWARD:
1250 new_value += range->adjustment->step_increment;
1251 if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
1253 new_value = range->adjustment->upper - range->adjustment->page_size;
1259 case GTK_SCROLL_PAGE_BACKWARD:
1260 new_value -= range->adjustment->page_increment;
1261 if (new_value <= range->adjustment->lower)
1263 new_value = range->adjustment->lower;
1269 case GTK_SCROLL_PAGE_FORWARD:
1270 new_value += range->adjustment->page_increment;
1271 if (new_value >= (range->adjustment->upper - range->adjustment->page_size))
1273 new_value = range->adjustment->upper - range->adjustment->page_size;
1280 if (new_value != range->adjustment->value)
1282 range->adjustment->value = new_value;
1284 if ((range->policy == GTK_UPDATE_CONTINUOUS) ||
1285 (!return_val && (range->policy == GTK_UPDATE_DELAYED)))
1287 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
1291 gtk_range_slider_update (range);
1292 gtk_range_clear_background (range);
1301 gtk_range_add_timer (GtkRange *range)
1303 g_return_if_fail (range != NULL);
1304 g_return_if_fail (GTK_IS_RANGE (range));
1308 range->need_timer = TRUE;
1309 range->timer = gtk_timeout_add (SCROLL_INITIAL_DELAY,
1310 (GtkFunction) RANGE_CLASS (range)->timer,
1316 gtk_range_remove_timer (GtkRange *range)
1318 g_return_if_fail (range != NULL);
1319 g_return_if_fail (GTK_IS_RANGE (range));
1323 gtk_timeout_remove (range->timer);
1326 range->need_timer = FALSE;
1330 gtk_range_adjustment_changed (GtkAdjustment *adjustment,
1335 g_return_if_fail (adjustment != NULL);
1336 g_return_if_fail (data != NULL);
1338 range = GTK_RANGE (data);
1340 if (((range->old_lower != adjustment->lower) ||
1341 (range->old_upper != adjustment->upper) ||
1342 (range->old_page_size != adjustment->page_size)) &&
1343 (range->old_value == adjustment->value))
1345 if ((adjustment->lower == adjustment->upper) ||
1346 (range->old_lower == (range->old_upper - range->old_page_size)))
1348 adjustment->value = adjustment->lower;
1349 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed");
1353 if ((range->old_value != adjustment->value) ||
1354 (range->old_lower != adjustment->lower) ||
1355 (range->old_upper != adjustment->upper) ||
1356 (range->old_page_size != adjustment->page_size))
1358 gtk_range_slider_update (range);
1359 gtk_range_clear_background (range);
1361 range->old_value = adjustment->value;
1362 range->old_lower = adjustment->lower;
1363 range->old_upper = adjustment->upper;
1364 range->old_page_size = adjustment->page_size;
1369 gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
1374 g_return_if_fail (adjustment != NULL);
1375 g_return_if_fail (data != NULL);
1377 range = GTK_RANGE (data);
1379 if (range->old_value != adjustment->value)
1381 gtk_range_slider_update (range);
1382 gtk_range_clear_background (range);
1384 range->old_value = adjustment->value;
1390 gtk_range_trough_hdims (GtkRange *range,
1400 g_return_if_fail (range != NULL);
1402 gdk_window_get_size (range->trough, &trough_width, NULL);
1403 gdk_window_get_size (range->slider, &slider_length, NULL);
1405 tleft = GTK_WIDGET (range)->style->klass->xthickness;
1406 tright = trough_width - slider_length - GTK_WIDGET (range)->style->klass->xthickness;
1408 if (range->step_back)
1410 gdk_window_get_size (range->step_back, &tmp_width, NULL);
1411 tleft += (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
1414 if (range->step_forw)
1416 gdk_window_get_size (range->step_forw, &tmp_width, NULL);
1417 tright -= (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing);
1427 gtk_range_trough_vdims (GtkRange *range,
1437 g_return_if_fail (range != NULL);
1439 gdk_window_get_size (range->trough, NULL, &trough_height);
1440 gdk_window_get_size (range->slider, NULL, &slider_length);
1442 ttop = GTK_WIDGET (range)->style->klass->ythickness;
1443 tbottom = trough_height - slider_length - GTK_WIDGET (range)->style->klass->ythickness;
1445 if (range->step_back)
1447 gdk_window_get_size (range->step_back, NULL, &tmp_height);
1448 ttop += (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
1451 if (range->step_forw)
1453 gdk_window_get_size (range->step_forw, NULL, &tmp_height);
1454 tbottom -= (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing);
1464 gtk_range_style_set (GtkWidget *widget,
1465 GtkStyle *previous_style)
1469 g_return_if_fail (widget != NULL);
1470 g_return_if_fail (GTK_IS_RANGE (widget));
1472 range = GTK_RANGE (widget);
1474 if (GTK_WIDGET_REALIZED (widget) &&
1475 !GTK_WIDGET_NO_WINDOW (widget))
1479 gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
1480 if (GTK_WIDGET_DRAWABLE (widget))
1481 gdk_window_clear (range->trough);
1483 /* The draw will take care of the slider */
1485 if (range->step_forw)
1487 gtk_style_set_background (widget->style, range->step_forw, GTK_STATE_ACTIVE);
1488 if (GTK_WIDGET_DRAWABLE (widget))
1489 gdk_window_clear (range->step_forw);
1491 if (range->step_back)
1493 gtk_style_set_background (widget->style, range->step_back, GTK_STATE_ACTIVE);
1494 if (GTK_WIDGET_DRAWABLE (widget))
1495 gdk_window_clear (range->step_back);
1497 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);