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 /* reversed_1 */ NULL,
99 /* reversed_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->draw_trough = gtk_real_range_draw_trough;
146 class->draw_slider = gtk_real_range_draw_slider;
147 class->draw_step_forw = NULL;
148 class->draw_step_back = NULL;
149 class->trough_click = NULL;
150 class->trough_keys = NULL;
151 class->motion = NULL;
152 class->timer = gtk_real_range_timer;
156 gtk_range_init (GtkRange *range)
158 range->trough = NULL;
159 range->slider = NULL;
160 range->step_forw = NULL;
161 range->step_back = NULL;
163 range->x_click_point = 0;
164 range->y_click_point = 0;
167 range->policy = GTK_UPDATE_CONTINUOUS;
168 range->scroll_type = GTK_SCROLL_NONE;
170 range->click_child = 0;
171 range->need_timer = FALSE;
173 range->old_value = 0.0;
174 range->old_lower = 0.0;
175 range->old_upper = 0.0;
176 range->old_page_size = 0.0;
177 range->adjustment = NULL;
181 gtk_range_get_adjustment (GtkRange *range)
183 g_return_val_if_fail (range != NULL, NULL);
184 g_return_val_if_fail (GTK_IS_RANGE (range), NULL);
186 return range->adjustment;
190 gtk_range_set_update_policy (GtkRange *range,
191 GtkUpdateType policy)
193 g_return_if_fail (range != NULL);
194 g_return_if_fail (GTK_IS_RANGE (range));
196 range->policy = policy;
200 gtk_range_set_adjustment (GtkRange *range,
201 GtkAdjustment *adjustment)
203 g_return_if_fail (range != NULL);
204 g_return_if_fail (GTK_IS_RANGE (range));
206 if (range->adjustment != adjustment)
208 if (range->adjustment)
210 gtk_signal_disconnect_by_data (GTK_OBJECT (range->adjustment),
212 gtk_object_unref (GTK_OBJECT (range->adjustment));
214 range->adjustment = adjustment;
217 gtk_object_ref (GTK_OBJECT (adjustment));
218 gtk_object_sink (GTK_OBJECT (adjustment));
220 gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
221 (GtkSignalFunc) gtk_range_adjustment_changed,
223 gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
224 (GtkSignalFunc) gtk_range_adjustment_value_changed,
227 range->old_value = adjustment->value;
228 range->old_lower = adjustment->lower;
229 range->old_upper = adjustment->upper;
230 range->old_page_size = adjustment->page_size;
232 gtk_range_adjustment_changed (adjustment, (gpointer) range);
238 gtk_range_draw_background (GtkRange *range)
240 g_return_if_fail (range != NULL);
241 g_return_if_fail (GTK_IS_RANGE (range));
243 if (range->trough && RANGE_CLASS (range)->draw_background)
244 (* RANGE_CLASS (range)->draw_background) (range);
248 gtk_range_draw_trough (GtkRange *range)
250 g_return_if_fail (range != NULL);
251 g_return_if_fail (GTK_IS_RANGE (range));
253 if (range->trough && RANGE_CLASS (range)->draw_trough)
254 (* RANGE_CLASS (range)->draw_trough) (range);
258 gtk_range_draw_slider (GtkRange *range)
260 g_return_if_fail (range != NULL);
261 g_return_if_fail (GTK_IS_RANGE (range));
263 if (range->slider && RANGE_CLASS (range)->draw_slider)
264 (* RANGE_CLASS (range)->draw_slider) (range);
268 gtk_range_draw_step_forw (GtkRange *range)
270 g_return_if_fail (range != NULL);
271 g_return_if_fail (GTK_IS_RANGE (range));
273 if (range->step_forw && RANGE_CLASS (range)->draw_step_forw)
274 (* RANGE_CLASS (range)->draw_step_forw) (range);
278 gtk_range_draw_step_back (GtkRange *range)
280 g_return_if_fail (range != NULL);
281 g_return_if_fail (GTK_IS_RANGE (range));
283 if (range->step_back && RANGE_CLASS (range)->draw_step_back)
284 (* RANGE_CLASS (range)->draw_step_back) (range);
288 gtk_range_slider_update (GtkRange *range)
290 g_return_if_fail (range != NULL);
291 g_return_if_fail (GTK_IS_RANGE (range));
293 if (RANGE_CLASS (range)->slider_update)
294 (* RANGE_CLASS (range)->slider_update) (range);
298 gtk_range_trough_click (GtkRange *range,
303 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
304 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
306 if (RANGE_CLASS (range)->trough_click)
307 return (* RANGE_CLASS (range)->trough_click) (range, x, y, jump_perc);
309 return GTK_TROUGH_NONE;
313 gtk_range_default_hslider_update (GtkRange *range)
319 g_return_if_fail (range != NULL);
320 g_return_if_fail (GTK_IS_RANGE (range));
322 if (GTK_WIDGET_REALIZED (range))
324 gtk_range_trough_hdims (range, &left, &right);
327 if (range->adjustment->value < range->adjustment->lower)
329 range->adjustment->value = range->adjustment->lower;
330 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
332 else if (range->adjustment->value > range->adjustment->upper)
334 range->adjustment->value = range->adjustment->upper;
335 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
338 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
339 x += ((right - left) * (range->adjustment->value - range->adjustment->lower) /
340 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
347 gdk_window_move (range->slider, x, GTK_WIDGET (range)->style->klass->ythickness);
352 gtk_range_default_vslider_update (GtkRange *range)
358 g_return_if_fail (range != NULL);
359 g_return_if_fail (GTK_IS_RANGE (range));
361 if (GTK_WIDGET_REALIZED (range))
363 gtk_range_trough_vdims (range, &top, &bottom);
366 if (range->adjustment->value < range->adjustment->lower)
368 range->adjustment->value = range->adjustment->lower;
369 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
371 else if (range->adjustment->value > range->adjustment->upper)
373 range->adjustment->value = range->adjustment->upper;
374 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
377 if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size))
378 y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) /
379 (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size));
386 gdk_window_move (range->slider, GTK_WIDGET (range)->style->klass->xthickness, y);
391 gtk_range_default_htrough_click (GtkRange *range,
403 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
404 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
406 ythickness = GTK_WIDGET (range)->style->klass->ythickness;
408 gtk_range_trough_hdims (range, &left, &right);
409 gdk_window_get_size (range->slider, &slider_length, NULL);
410 right += slider_length;
412 if ((x > left) && (y > ythickness))
414 gdk_window_get_size (range->trough, &trough_width, &trough_height);
416 if ((x < right) && (y < (trough_height - ythickness)))
420 *jump_perc = ((gdouble) (x - left)) / ((gdouble) (right - left));
421 return GTK_TROUGH_JUMP;
424 gdk_window_get_position (range->slider, &slider_x, NULL);
427 return GTK_TROUGH_START;
429 return GTK_TROUGH_END;
433 return GTK_TROUGH_NONE;
437 gtk_range_default_vtrough_click (GtkRange *range,
449 g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE);
450 g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE);
452 xthickness = GTK_WIDGET (range)->style->klass->xthickness;
454 gtk_range_trough_vdims (range, &top, &bottom);
455 gdk_window_get_size (range->slider, NULL, &slider_length);
456 bottom += slider_length;
458 if ((x > xthickness) && (y > top))
460 gdk_window_get_size (range->trough, &trough_width, &trough_height);
462 if ((x < (trough_width - xthickness) && (y < bottom)))
466 *jump_perc = ((gdouble) (y - top)) / ((gdouble) (bottom - top));
468 return GTK_TROUGH_JUMP;
471 gdk_window_get_position (range->slider, NULL, &slider_y);
474 return GTK_TROUGH_START;
476 return GTK_TROUGH_END;
480 return GTK_TROUGH_NONE;
484 gtk_range_default_hmotion (GtkRange *range,
490 gint slider_x, slider_y;
493 g_return_if_fail (range != NULL);
494 g_return_if_fail (GTK_IS_RANGE (range));
496 range = GTK_RANGE (range);
498 gdk_window_get_position (range->slider, &slider_x, &slider_y);
499 gtk_range_trough_hdims (range, &left, &right);
504 new_pos = slider_x + xdelta;
508 else if (new_pos > right)
511 old_value = range->adjustment->value;
512 range->adjustment->value = ((range->adjustment->upper -
513 range->adjustment->lower -
514 range->adjustment->page_size) *
515 (new_pos - left) / (right - left) +
516 range->adjustment->lower);
518 if (range->digits >= 0)
522 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
523 sscanf (buffer, "%f", &range->adjustment->value);
526 if (old_value != range->adjustment->value)
528 if (range->policy == GTK_UPDATE_CONTINUOUS)
530 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
534 gtk_range_slider_update (range);
535 gtk_range_draw_background (range);
537 if (range->policy == GTK_UPDATE_DELAYED)
539 gtk_range_remove_timer (range);
540 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
541 (GtkFunction) RANGE_CLASS (range)->timer,
549 gtk_range_default_vmotion (GtkRange *range,
555 gint slider_x, slider_y;
558 g_return_if_fail (range != NULL);
559 g_return_if_fail (GTK_IS_RANGE (range));
561 range = GTK_RANGE (range);
563 gdk_window_get_position (range->slider, &slider_x, &slider_y);
564 gtk_range_trough_vdims (range, &top, &bottom);
569 new_pos = slider_y + ydelta;
573 else if (new_pos > bottom)
576 old_value = range->adjustment->value;
577 range->adjustment->value = ((range->adjustment->upper -
578 range->adjustment->lower -
579 range->adjustment->page_size) *
580 (new_pos - top) / (bottom - top) +
581 range->adjustment->lower);
583 if (range->digits >= 0)
587 sprintf (buffer, "%0.*f", range->digits, range->adjustment->value);
588 sscanf (buffer, "%f", &range->adjustment->value);
591 if (old_value != range->adjustment->value)
593 if (range->policy == GTK_UPDATE_CONTINUOUS)
595 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
599 gtk_range_slider_update (range);
600 gtk_range_draw_background (range);
602 if (range->policy == GTK_UPDATE_DELAYED)
604 gtk_range_remove_timer (range);
605 range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
606 (GtkFunction) RANGE_CLASS (range)->timer,
615 gtk_range_finalize (GtkObject *object)
619 g_return_if_fail (object != NULL);
620 g_return_if_fail (GTK_IS_RANGE (object));
622 range = GTK_RANGE (object);
624 if (range->adjustment)
625 gtk_object_unref (GTK_OBJECT (range->adjustment));
627 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
631 gtk_range_draw (GtkWidget *widget,
636 g_return_if_fail (widget != NULL);
637 g_return_if_fail (GTK_IS_RANGE (widget));
638 g_return_if_fail (area != NULL);
640 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
642 range = GTK_RANGE (widget);
644 gtk_range_draw_background (range);
645 gtk_range_draw_trough (range);
646 gtk_range_draw_slider (range);
647 gtk_range_draw_step_forw (range);
648 gtk_range_draw_step_back (range);
653 gtk_range_draw_focus (GtkWidget *widget)
655 g_return_if_fail (widget != NULL);
656 g_return_if_fail (GTK_IS_RANGE (widget));
658 if (GTK_WIDGET_DRAWABLE (widget))
659 gtk_range_draw_trough (GTK_RANGE (widget));
663 gtk_range_unrealize (GtkWidget *widget)
667 g_return_if_fail (widget != NULL);
668 g_return_if_fail (GTK_IS_RANGE (widget));
670 range = GTK_RANGE (widget);
674 gdk_window_set_user_data (range->slider, NULL);
675 gdk_window_destroy (range->slider);
676 range->slider = NULL;
680 gdk_window_set_user_data (range->trough, NULL);
681 gdk_window_destroy (range->trough);
682 range->trough = NULL;
684 if (range->step_forw)
686 gdk_window_set_user_data (range->step_forw, NULL);
687 gdk_window_destroy (range->step_forw);
688 range->step_forw = NULL;
690 if (range->step_back)
692 gdk_window_set_user_data (range->step_back, NULL);
693 gdk_window_destroy (range->step_back);
694 range->step_back = NULL;
697 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
698 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
702 gtk_range_expose (GtkWidget *widget,
703 GdkEventExpose *event)
707 g_return_val_if_fail (widget != NULL, FALSE);
708 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
709 g_return_val_if_fail (event != NULL, FALSE);
711 range = GTK_RANGE (widget);
713 if (event->window == range->trough)
715 /* Don't redraw if we are only exposing the literal trough region.
716 * this may not work correctly if someone overrides the default
717 * trough-drawing handler. (Probably should really pass another
718 * argument - the redrawn area to all the drawing functions)
721 gint xt = widget->style->klass->xthickness;
722 gint yt = widget->style->klass->ythickness;
724 if (!((event->area.x >= xt) &&
725 (event->area.y >= yt) &&
726 (event->area.x + event->area.width <=
727 widget->allocation.width - xt) &&
728 (event->area.y + event->area.height <=
729 widget->allocation.height - xt)))
730 gtk_range_draw_trough (range);
732 else if (event->window == widget->window)
734 gtk_range_draw_background (range);
736 else if (event->window == range->slider)
738 gtk_range_draw_slider (range);
740 else if (event->window == range->step_forw)
742 gtk_range_draw_step_forw (range);
744 else if (event->window == range->step_back)
746 gtk_range_draw_step_back (range);
752 gtk_range_button_press (GtkWidget *widget,
753 GdkEventButton *event)
759 g_return_val_if_fail (widget != NULL, FALSE);
760 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
761 g_return_val_if_fail (event != NULL, FALSE);
763 if (!GTK_WIDGET_HAS_FOCUS (widget))
764 gtk_widget_grab_focus (widget);
767 range = GTK_RANGE (widget);
768 if (range->button == 0)
770 gtk_grab_add (widget);
772 range->button = event->button;
773 range->x_click_point = event->x;
774 range->y_click_point = event->y;
776 if (event->window == range->trough)
778 range->click_child = RANGE_CLASS (range)->trough;
780 if (range->button == 2)
781 trough_part = gtk_range_trough_click (range, event->x, event->y, &jump_perc);
783 trough_part = gtk_range_trough_click (range, event->x, event->y, NULL);
785 range->scroll_type = GTK_SCROLL_NONE;
786 if (trough_part == GTK_TROUGH_START)
787 range->scroll_type = GTK_SCROLL_PAGE_BACKWARD;
788 else if (trough_part == GTK_TROUGH_END)
789 range->scroll_type = GTK_SCROLL_PAGE_FORWARD;
790 else if (trough_part == GTK_TROUGH_JUMP &&
791 jump_perc >= 0 && jump_perc <= 1)
792 range->scroll_type = GTK_SCROLL_JUMP;
794 if (range->scroll_type != GTK_SCROLL_NONE)
796 gtk_range_scroll (range, jump_perc);
797 gtk_range_add_timer (range);
800 else if (event->window == range->slider)
802 range->click_child = RANGE_CLASS (range)->slider;
803 range->scroll_type = GTK_SCROLL_NONE;
805 else if (event->window == range->step_forw)
807 range->click_child = RANGE_CLASS (range)->step_forw;
808 range->scroll_type = GTK_SCROLL_STEP_FORWARD;
810 gtk_range_scroll (range, -1);
811 gtk_range_add_timer (range);
812 gtk_range_draw_step_forw (range);
814 else if (event->window == range->step_back)
816 range->click_child = RANGE_CLASS (range)->step_back;
817 range->scroll_type = GTK_SCROLL_STEP_BACKWARD;
819 gtk_range_scroll (range, -1);
820 gtk_range_add_timer (range);
821 gtk_range_draw_step_back (range);
829 gtk_range_button_release (GtkWidget *widget,
830 GdkEventButton *event)
834 g_return_val_if_fail (widget != NULL, FALSE);
835 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
836 g_return_val_if_fail (event != NULL, FALSE);
838 range = GTK_RANGE (widget);
840 if (range->button == event->button)
842 gtk_grab_remove (widget);
845 range->x_click_point = -1;
846 range->y_click_point = -1;
848 if (range->click_child == RANGE_CLASS (range)->slider)
850 if (range->policy == GTK_UPDATE_DELAYED)
851 gtk_range_remove_timer (range);
853 if ((range->policy != GTK_UPDATE_CONTINUOUS) &&
854 (range->old_value != range->adjustment->value))
855 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
857 else if ((range->click_child == RANGE_CLASS (range)->trough) ||
858 (range->click_child == RANGE_CLASS (range)->step_forw) ||
859 (range->click_child == RANGE_CLASS (range)->step_back))
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 if (range->click_child == RANGE_CLASS (range)->step_forw)
869 range->click_child = 0;
870 gtk_range_draw_step_forw (range);
872 else if (range->click_child == RANGE_CLASS (range)->step_back)
874 range->click_child = 0;
875 gtk_range_draw_step_back (range);
879 range->click_child = 0;
886 gtk_range_motion_notify (GtkWidget *widget,
887 GdkEventMotion *event)
890 GdkModifierType mods;
893 g_return_val_if_fail (widget != NULL, FALSE);
894 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
895 g_return_val_if_fail (event != NULL, FALSE);
897 range = GTK_RANGE (widget);
899 if (range->click_child == RANGE_CLASS (range)->slider)
904 if (event->is_hint || (event->window != range->slider))
905 gdk_window_get_pointer (range->slider, &x, &y, &mods);
907 switch (range->button)
910 mask = GDK_BUTTON1_MASK;
913 mask = GDK_BUTTON2_MASK;
916 mask = GDK_BUTTON3_MASK;
925 if (RANGE_CLASS (range)->motion)
926 (* RANGE_CLASS (range)->motion) (range, x - range->x_click_point, y - range->y_click_point);
934 gtk_range_key_press (GtkWidget *widget,
939 GtkScrollType scroll = GTK_SCROLL_NONE;
940 GtkTroughType pos = GTK_TROUGH_NONE;
942 g_return_val_if_fail (widget != NULL, FALSE);
943 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
944 g_return_val_if_fail (event != NULL, FALSE);
946 range = GTK_RANGE (widget);
949 if (RANGE_CLASS (range)->trough_keys)
950 return_val = (* RANGE_CLASS (range)->trough_keys) (range, event, &scroll, &pos);
954 if (scroll != GTK_SCROLL_NONE)
956 range->scroll_type = scroll;
957 gtk_range_scroll (range, -1);
958 if (range->old_value != range->adjustment->value)
960 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed");
961 switch (range->scroll_type)
963 case GTK_SCROLL_STEP_BACKWARD:
964 gtk_range_draw_step_back (range);
966 case GTK_SCROLL_STEP_FORWARD:
967 gtk_range_draw_step_forw (range);
972 if (pos != GTK_TROUGH_NONE)
974 if (pos == GTK_TROUGH_START)
975 range->adjustment->value = range->adjustment->lower;
976 else if (pos == GTK_TROUGH_END)
977 range->adjustment->value =
978 range->adjustment->upper - range->adjustment->page_size;
980 if (range->old_value != range->adjustment->value)
982 gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment),
985 gtk_range_slider_update (range);
986 gtk_range_draw_background (range);
994 gtk_range_enter_notify (GtkWidget *widget,
995 GdkEventCrossing *event)
999 g_return_val_if_fail (widget != NULL, FALSE);
1000 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1001 g_return_val_if_fail (event != NULL, FALSE);
1003 range = GTK_RANGE (widget);
1005 if (event->window == range->trough)
1007 range->in_child = RANGE_CLASS (range)->trough;
1009 else if (event->window == range->slider)
1011 range->in_child = RANGE_CLASS (range)->slider;
1013 if ((range->click_child == 0) ||
1014 (range->click_child == RANGE_CLASS (range)->trough))
1015 gtk_range_draw_slider (range);
1017 else if (event->window == range->step_forw)
1019 range->in_child = RANGE_CLASS (range)->step_forw;
1021 if ((range->click_child == 0) ||
1022 (range->click_child == RANGE_CLASS (range)->trough))
1023 gtk_range_draw_step_forw (range);
1025 else if (event->window == range->step_back)
1027 range->in_child = RANGE_CLASS (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_leave_notify (GtkWidget *widget,
1039 GdkEventCrossing *event)
1043 g_return_val_if_fail (widget != NULL, FALSE);
1044 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1045 g_return_val_if_fail (event != NULL, FALSE);
1047 range = GTK_RANGE (widget);
1049 range->in_child = 0;
1051 if (event->window == range->trough)
1054 else if (event->window == range->slider)
1056 if ((range->click_child == 0) ||
1057 (range->click_child == RANGE_CLASS (range)->trough))
1058 gtk_range_draw_slider (range);
1060 else if (event->window == range->step_forw)
1062 if ((range->click_child == 0) ||
1063 (range->click_child == RANGE_CLASS (range)->trough))
1064 gtk_range_draw_step_forw (range);
1066 else if (event->window == range->step_back)
1068 if ((range->click_child == 0) ||
1069 (range->click_child == RANGE_CLASS (range)->trough))
1070 gtk_range_draw_step_back (range);
1077 gtk_range_focus_in (GtkWidget *widget,
1078 GdkEventFocus *event)
1080 g_return_val_if_fail (widget != NULL, FALSE);
1081 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1082 g_return_val_if_fail (event != NULL, FALSE);
1084 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1085 gtk_widget_draw_focus (widget);
1091 gtk_range_focus_out (GtkWidget *widget,
1092 GdkEventFocus *event)
1094 g_return_val_if_fail (widget != NULL, FALSE);
1095 g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE);
1096 g_return_val_if_fail (event != NULL, FALSE);
1098 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1099 gtk_widget_draw_focus (widget);
1105 gtk_real_range_draw_trough (GtkRange *range)
1107 g_return_if_fail (range != NULL);
1108 g_return_if_fail (GTK_IS_RANGE (range));
1112 gtk_draw_shadow (GTK_WIDGET (range)->style, range->trough,
1113 GTK_STATE_NORMAL, GTK_SHADOW_IN,
1116 if (GTK_WIDGET_HAS_FOCUS (range))
1117 gdk_draw_rectangle (GTK_WIDGET (range)->window,
1118 GTK_WIDGET (range)->style->black_gc,
1120 GTK_WIDGET (range)->allocation.width - 1,
1121 GTK_WIDGET (range)->allocation.height - 1);
1122 else if (range->trough != GTK_WIDGET (range)->window)
1123 gdk_draw_rectangle (GTK_WIDGET (range)->window,
1124 GTK_WIDGET (range)->style->bg_gc[GTK_STATE_NORMAL],
1126 GTK_WIDGET (range)->allocation.width - 1,
1127 GTK_WIDGET (range)->allocation.height - 1);
1132 gtk_real_range_draw_slider (GtkRange *range)
1134 GtkStateType state_type;
1136 g_return_if_fail (range != NULL);
1137 g_return_if_fail (GTK_IS_RANGE (range));
1141 if ((range->in_child == RANGE_CLASS (range)->slider) ||
1142 (range->click_child == RANGE_CLASS (range)->slider))
1143 state_type = GTK_STATE_PRELIGHT;
1145 state_type = GTK_STATE_NORMAL;
1147 gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
1148 gdk_window_clear (range->slider);
1150 gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
1151 state_type, GTK_SHADOW_OUT,
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_draw_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_draw_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_draw_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);