diff options
Diffstat (limited to 'gtk/gtkrange.c')
-rw-r--r-- | gtk/gtkrange.c | 1369 |
1 files changed, 1369 insertions, 0 deletions
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c new file mode 100644 index 0000000000..f00bbf6838 --- /dev/null +++ b/gtk/gtkrange.c @@ -0,0 +1,1369 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include "gtkmain.h" +#include "gtkrange.h" +#include "gtksignal.h" + + +#define SCROLL_TIMER_LENGTH 20 +#define SCROLL_INITIAL_DELAY 100 +#define SCROLL_DELAY_LENGTH 300 + +#define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass) + + +static void gtk_range_class_init (GtkRangeClass *klass); +static void gtk_range_init (GtkRange *range); +static void gtk_range_destroy (GtkObject *object); +static void gtk_range_draw (GtkWidget *widget, + GdkRectangle *area); +static void gtk_range_draw_focus (GtkWidget *widget); +static void gtk_range_unrealize (GtkWidget *widget); +static gint gtk_range_expose (GtkWidget *widget, + GdkEventExpose *event); +static gint gtk_range_button_press (GtkWidget *widget, + GdkEventButton *event); +static gint gtk_range_button_release (GtkWidget *widget, + GdkEventButton *event); +static gint gtk_range_motion_notify (GtkWidget *widget, + GdkEventMotion *event); +static gint gtk_range_key_press (GtkWidget *widget, + GdkEventKey *event); +static gint gtk_range_enter_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gint gtk_range_leave_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gint gtk_range_focus_in (GtkWidget *widget, + GdkEventFocus *event); +static gint gtk_range_focus_out (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_real_range_draw_trough (GtkRange *range); +static void gtk_real_range_draw_slider (GtkRange *range); +static gint gtk_real_range_timer (GtkRange *range); +static gint gtk_range_scroll (GtkRange *range); + +static void gtk_range_add_timer (GtkRange *range); +static void gtk_range_remove_timer (GtkRange *range); + +static void gtk_range_adjustment_changed (GtkAdjustment *adjustment, + gpointer data); +static void gtk_range_adjustment_value_changed (GtkAdjustment *adjustment, + gpointer data); + +static void gtk_range_trough_hdims (GtkRange *range, + gint *left, + gint *right); +static void gtk_range_trough_vdims (GtkRange *range, + gint *top, + gint *bottom); + +static GtkWidgetClass *parent_class = NULL; + + +guint +gtk_range_get_type () +{ + static guint range_type = 0; + + if (!range_type) + { + GtkTypeInfo range_info = + { + "GtkRange", + sizeof (GtkRange), + sizeof (GtkRangeClass), + (GtkClassInitFunc) gtk_range_class_init, + (GtkObjectInitFunc) gtk_range_init, + (GtkArgFunc) NULL, + }; + + range_type = gtk_type_unique (gtk_widget_get_type (), &range_info); + } + + return range_type; +} + +static void +gtk_range_class_init (GtkRangeClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + + parent_class = gtk_type_class (gtk_widget_get_type ()); + + object_class->destroy = gtk_range_destroy; + + widget_class->draw = gtk_range_draw; + widget_class->draw_focus = gtk_range_draw_focus; + widget_class->unrealize = gtk_range_unrealize; + widget_class->expose_event = gtk_range_expose; + widget_class->button_press_event = gtk_range_button_press; + widget_class->button_release_event = gtk_range_button_release; + widget_class->motion_notify_event = gtk_range_motion_notify; + widget_class->key_press_event = gtk_range_key_press; + widget_class->enter_notify_event = gtk_range_enter_notify; + widget_class->leave_notify_event = gtk_range_leave_notify; + widget_class->focus_in_event = gtk_range_focus_in; + widget_class->focus_out_event = gtk_range_focus_out; + + class->slider_width = 11; + class->stepper_size = 11; + class->stepper_slider_spacing = 1; + class->min_slider_size = 7; + class->trough = 1; + class->slider = 2; + class->step_forw = 3; + class->step_back = 4; + class->draw_background = NULL; + class->draw_trough = gtk_real_range_draw_trough; + class->draw_slider = gtk_real_range_draw_slider; + class->draw_step_forw = NULL; + class->draw_step_back = NULL; + class->trough_click = NULL; + class->trough_keys = NULL; + class->motion = NULL; + class->timer = gtk_real_range_timer; +} + +static void +gtk_range_init (GtkRange *range) +{ + range->trough = NULL; + range->slider = NULL; + range->step_forw = NULL; + range->step_back = NULL; + + range->x_click_point = 0; + range->y_click_point = 0; + range->button = 0; + range->digits = -1; + range->policy = GTK_UPDATE_CONTINUOUS; + range->scroll_type = GTK_SCROLL_NONE; + range->in_child = 0; + range->click_child = 0; + range->need_timer = FALSE; + range->timer = 0; + range->old_value = 0.0; + range->old_lower = 0.0; + range->old_upper = 0.0; + range->old_page_size = 0.0; + range->adjustment = NULL; +} + +GtkAdjustment* +gtk_range_get_adjustment (GtkRange *range) +{ + g_return_val_if_fail (range != NULL, NULL); + g_return_val_if_fail (GTK_IS_RANGE (range), NULL); + + return range->adjustment; +} + +void +gtk_range_set_update_policy (GtkRange *range, + GtkUpdateType policy) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + range->policy = policy; +} + +void +gtk_range_set_adjustment (GtkRange *range, + GtkAdjustment *adjustment) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->adjustment) + { + gtk_signal_disconnect_by_data (GTK_OBJECT (range->adjustment), (gpointer) range); + gtk_object_unref (GTK_OBJECT (range->adjustment)); + } + + range->adjustment = adjustment; + gtk_object_ref (GTK_OBJECT (range->adjustment)); + + gtk_signal_connect (GTK_OBJECT (adjustment), "changed", + (GtkSignalFunc) gtk_range_adjustment_changed, + (gpointer) range); + gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", + (GtkSignalFunc) gtk_range_adjustment_value_changed, + (gpointer) range); + + range->old_value = adjustment->value; + range->old_lower = adjustment->lower; + range->old_upper = adjustment->upper; + range->old_page_size = adjustment->page_size; + + gtk_range_adjustment_changed (range->adjustment, (gpointer) range); +} + +void +gtk_range_draw_background (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->trough && RANGE_CLASS (range)->draw_background) + (* RANGE_CLASS (range)->draw_background) (range); +} + +void +gtk_range_draw_trough (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->trough && RANGE_CLASS (range)->draw_trough) + (* RANGE_CLASS (range)->draw_trough) (range); +} + +void +gtk_range_draw_slider (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->slider && RANGE_CLASS (range)->draw_slider) + (* RANGE_CLASS (range)->draw_slider) (range); +} + +void +gtk_range_draw_step_forw (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->step_forw && RANGE_CLASS (range)->draw_step_forw) + (* RANGE_CLASS (range)->draw_step_forw) (range); +} + +void +gtk_range_draw_step_back (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->step_back && RANGE_CLASS (range)->draw_step_back) + (* RANGE_CLASS (range)->draw_step_back) (range); +} + +void +gtk_range_slider_update (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (RANGE_CLASS (range)->slider_update) + (* RANGE_CLASS (range)->slider_update) (range); +} + +gint +gtk_range_trough_click (GtkRange *range, + gint x, + gint y) +{ + g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE); + g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE); + + if (RANGE_CLASS (range)->trough_click) + return (* RANGE_CLASS (range)->trough_click) (range, x, y); + + return GTK_TROUGH_NONE; +} + +void +gtk_range_default_hslider_update (GtkRange *range) +{ + gint left; + gint right; + gint x; + + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (GTK_WIDGET_REALIZED (range)) + { + gtk_range_trough_hdims (range, &left, &right); + x = left; + + if (range->adjustment->value < range->adjustment->lower) + { + range->adjustment->value = range->adjustment->lower; + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + else if (range->adjustment->value > range->adjustment->upper) + { + range->adjustment->value = range->adjustment->upper; + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + + if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size)) + x += ((right - left) * (range->adjustment->value - range->adjustment->lower) / + (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size)); + + if (x < left) + x = left; + else if (x > right) + x = right; + + gdk_window_move (range->slider, x, GTK_WIDGET (range)->style->klass->ythickness); + } +} + +void +gtk_range_default_vslider_update (GtkRange *range) +{ + gint top; + gint bottom; + gint y; + + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (GTK_WIDGET_REALIZED (range)) + { + gtk_range_trough_vdims (range, &top, &bottom); + y = top; + + if (range->adjustment->value < range->adjustment->lower) + { + range->adjustment->value = range->adjustment->lower; + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + else if (range->adjustment->value > range->adjustment->upper) + { + range->adjustment->value = range->adjustment->upper; + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + + if (range->adjustment->lower != (range->adjustment->upper - range->adjustment->page_size)) + y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) / + (range->adjustment->upper - range->adjustment->lower - range->adjustment->page_size)); + + if (y < top) + y = top; + else if (y > bottom) + y = bottom; + + gdk_window_move (range->slider, GTK_WIDGET (range)->style->klass->ythickness, y); + } +} + +gint +gtk_range_default_htrough_click (GtkRange *range, + gint x, + gint y) +{ + gint xthickness; + gint ythickness; + gint trough_width; + gint trough_height; + gint slider_x; + + g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE); + g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE); + + xthickness = GTK_WIDGET (range)->style->klass->xthickness; + ythickness = GTK_WIDGET (range)->style->klass->ythickness; + + if ((x > xthickness) && (y > ythickness)) + { + gdk_window_get_size (range->trough, &trough_width, &trough_height); + + if ((x < (trough_width - xthickness) && (y < (trough_height - ythickness)))) + { + gdk_window_get_position (range->slider, &slider_x, NULL); + + if (x < slider_x) + return GTK_TROUGH_START; + else + return GTK_TROUGH_END; + } + } + + return GTK_TROUGH_NONE; +} + +gint +gtk_range_default_vtrough_click (GtkRange *range, + gint x, + gint y) +{ + gint xthickness; + gint ythickness; + gint trough_width; + gint trough_height; + gint slider_y; + + g_return_val_if_fail (range != NULL, GTK_TROUGH_NONE); + g_return_val_if_fail (GTK_IS_RANGE (range), GTK_TROUGH_NONE); + + xthickness = GTK_WIDGET (range)->style->klass->xthickness; + ythickness = GTK_WIDGET (range)->style->klass->ythickness; + + if ((x > xthickness) && (y > ythickness)) + { + gdk_window_get_size (range->trough, &trough_width, &trough_height); + + if ((x < (trough_width - xthickness) && (y < (trough_height - ythickness)))) + { + gdk_window_get_position (range->slider, NULL, &slider_y); + + if (y < slider_y) + return GTK_TROUGH_START; + else + return GTK_TROUGH_END; + } + } + + return GTK_TROUGH_NONE; +} + +void +gtk_range_default_hmotion (GtkRange *range, + gint xdelta, + gint ydelta) +{ + gdouble old_value; + gint left, right; + gint slider_x, slider_y; + gint new_pos; + + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + range = GTK_RANGE (range); + + gdk_window_get_position (range->slider, &slider_x, &slider_y); + gtk_range_trough_hdims (range, &left, &right); + + if (left == right) + return; + + new_pos = slider_x + xdelta; + + if (new_pos < left) + new_pos = left; + else if (new_pos > right) + new_pos = right; + + old_value = range->adjustment->value; + range->adjustment->value = ((range->adjustment->upper - + range->adjustment->lower - + range->adjustment->page_size) * + (new_pos - left) / (right - left) + + range->adjustment->lower); + + if (range->digits >= 0) + { + char buffer[64]; + + sprintf (buffer, "%0.*f", range->digits, range->adjustment->value); + sscanf (buffer, "%f", &range->adjustment->value); + } + + if (old_value != range->adjustment->value) + { + if (range->policy == GTK_UPDATE_CONTINUOUS) + { + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + else + { + gtk_range_slider_update (range); + gtk_range_draw_background (range); + + if (range->policy == GTK_UPDATE_DELAYED) + { + gtk_range_remove_timer (range); + range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH, + (GtkFunction) RANGE_CLASS (range)->timer, + (gpointer) range); + } + } + } +} + +void +gtk_range_default_vmotion (GtkRange *range, + gint xdelta, + gint ydelta) +{ + gdouble old_value; + gint top, bottom; + gint slider_x, slider_y; + gint new_pos; + + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + range = GTK_RANGE (range); + + gdk_window_get_position (range->slider, &slider_x, &slider_y); + gtk_range_trough_vdims (range, &top, &bottom); + + if (bottom == top) + return; + + new_pos = slider_y + ydelta; + + if (new_pos < top) + new_pos = top; + else if (new_pos > bottom) + new_pos = bottom; + + old_value = range->adjustment->value; + range->adjustment->value = ((range->adjustment->upper - + range->adjustment->lower - + range->adjustment->page_size) * + (new_pos - top) / (bottom - top) + + range->adjustment->lower); + + if (range->digits >= 0) + { + char buffer[64]; + + sprintf (buffer, "%0.*f", range->digits, range->adjustment->value); + sscanf (buffer, "%f", &range->adjustment->value); + } + + if (old_value != range->adjustment->value) + { + if (range->policy == GTK_UPDATE_CONTINUOUS) + { + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + else + { + gtk_range_slider_update (range); + gtk_range_draw_background (range); + + if (range->policy == GTK_UPDATE_DELAYED) + { + gtk_range_remove_timer (range); + range->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH, + (GtkFunction) RANGE_CLASS (range)->timer, + (gpointer) range); + } + } + } +} + +gfloat +gtk_range_calc_value (GtkRange *range, + gint position) +{ + return 0.0; +} + + +static void +gtk_range_destroy (GtkObject *object) +{ + GtkRange *range; + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_RANGE (object)); + + range = GTK_RANGE (object); + + if (range->adjustment) + gtk_object_unref (GTK_OBJECT (range->adjustment)); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +static void +gtk_range_draw (GtkWidget *widget, + GdkRectangle *area) +{ + GtkRange *range; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_RANGE (widget)); + g_return_if_fail (area != NULL); + + if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget)) + { + range = GTK_RANGE (widget); + + gtk_range_draw_background (range); + gtk_range_draw_trough (range); + gtk_range_draw_slider (range); + gtk_range_draw_step_forw (range); + gtk_range_draw_step_back (range); + } +} + +static void +gtk_range_draw_focus (GtkWidget *widget) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_RANGE (widget)); + + if (GTK_WIDGET_DRAWABLE (widget)) + gtk_range_draw_trough (GTK_RANGE (widget)); +} + +static void +gtk_range_unrealize (GtkWidget *widget) +{ + GtkRange *range; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_RANGE (widget)); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED); + range = GTK_RANGE (widget); + + gtk_style_detach (widget->style); + + if (range->slider) + gdk_window_destroy (range->slider); + if (range->trough) + gdk_window_destroy (range->trough); + if (range->step_forw) + gdk_window_destroy (range->step_forw); + if (range->step_back) + gdk_window_destroy (range->step_back); + if (widget->window) + gdk_window_destroy (widget->window); + + range->slider = NULL; + range->trough = NULL; + range->step_forw = NULL; + range->step_back = NULL; + widget->window = NULL; +} + +static gint +gtk_range_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkRange *range; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + range = GTK_RANGE (widget); + + if (event->window == range->trough) + { + gtk_range_draw_trough (range); + } + else if (event->window == widget->window) + { + gtk_range_draw_background (range); + } + else if (event->window == range->slider) + { + gtk_range_draw_slider (range); + } + else if (event->window == range->step_forw) + { + gtk_range_draw_step_forw (range); + } + else if (event->window == range->step_back) + { + gtk_range_draw_step_back (range); + } + return FALSE; +} + +static gint +gtk_range_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GtkRange *range; + gint trough_part; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + + range = GTK_RANGE (widget); + if (!range->button) + { + gtk_grab_add (widget); + + range->button = event->button; + range->x_click_point = event->x; + range->y_click_point = event->y; + + if (event->window == range->trough) + { + range->click_child = RANGE_CLASS (range)->trough; + + trough_part = gtk_range_trough_click (range, event->x, event->y); + + range->scroll_type = GTK_SCROLL_NONE; + if (trough_part == GTK_TROUGH_START) + range->scroll_type = GTK_SCROLL_PAGE_BACKWARD; + else if (trough_part == GTK_TROUGH_END) + range->scroll_type = GTK_SCROLL_PAGE_FORWARD; + + if (range->scroll_type != GTK_SCROLL_NONE) + { + gtk_range_scroll (range); + gtk_range_add_timer (range); + } + } + else if (event->window == range->slider) + { + range->click_child = RANGE_CLASS (range)->slider; + range->scroll_type = GTK_SCROLL_NONE; + } + else if (event->window == range->step_forw) + { + range->click_child = RANGE_CLASS (range)->step_forw; + range->scroll_type = GTK_SCROLL_STEP_FORWARD; + + gtk_range_scroll (range); + gtk_range_add_timer (range); + gtk_range_draw_step_forw (range); + } + else if (event->window == range->step_back) + { + range->click_child = RANGE_CLASS (range)->step_back; + range->scroll_type = GTK_SCROLL_STEP_BACKWARD; + + gtk_range_scroll (range); + gtk_range_add_timer (range); + gtk_range_draw_step_back (range); + } + } + + return FALSE; +} + +static gint +gtk_range_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GtkRange *range; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + range = GTK_RANGE (widget); + + if (range->button == event->button) + { + gtk_grab_remove (widget); + + range->button = 0; + range->x_click_point = -1; + range->y_click_point = -1; + + if (range->click_child == RANGE_CLASS (range)->slider) + { + if (range->policy == GTK_UPDATE_DELAYED) + gtk_range_remove_timer (range); + + if ((range->policy != GTK_UPDATE_CONTINUOUS) && + (range->old_value != range->adjustment->value)) + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + else if ((range->click_child == RANGE_CLASS (range)->trough) || + (range->click_child == RANGE_CLASS (range)->step_forw) || + (range->click_child == RANGE_CLASS (range)->step_back)) + { + gtk_range_remove_timer (range); + + if ((range->policy != GTK_UPDATE_CONTINUOUS) && + (range->old_value != range->adjustment->value)) + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + + if (range->click_child == RANGE_CLASS (range)->step_forw) + { + range->click_child = 0; + gtk_range_draw_step_forw (range); + } + else if (range->click_child == RANGE_CLASS (range)->step_back) + { + range->click_child = 0; + gtk_range_draw_step_back (range); + } + } + + range->click_child = 0; + } + + return FALSE; +} + +static gint +gtk_range_motion_notify (GtkWidget *widget, + GdkEventMotion *event) +{ + GtkRange *range; + GdkModifierType mods; + gint x, y, mask; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + range = GTK_RANGE (widget); + + if (range->click_child == RANGE_CLASS (range)->slider) + { + x = event->x; + y = event->y; + + if (event->is_hint || (event->window != range->slider)) + gdk_window_get_pointer (range->slider, &x, &y, &mods); + + switch (range->button) + { + case 1: + mask = GDK_BUTTON1_MASK; + break; + case 2: + mask = GDK_BUTTON2_MASK; + break; + case 3: + mask = GDK_BUTTON3_MASK; + break; + default: + mask = 0; + break; + } + + if (mods & mask) + { + if (RANGE_CLASS (range)->motion) + (* RANGE_CLASS (range)->motion) (range, x - range->x_click_point, y - range->y_click_point); + } + } + + return FALSE; +} + +static gint +gtk_range_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GtkRange *range; + gint return_val; + GtkScrollType scroll = GTK_SCROLL_NONE; + GtkTroughType pos = GTK_TROUGH_NONE; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + range = GTK_RANGE (widget); + return_val = FALSE; + + if (RANGE_CLASS (range)->trough_keys) + return_val = (* RANGE_CLASS (range)->trough_keys) (range, event, &scroll, &pos); + + if (return_val) + { + if (scroll != GTK_SCROLL_NONE) + { + range->scroll_type = scroll; + gtk_range_scroll (range); + if (range->old_value != range->adjustment->value) + { + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + switch (range->scroll_type) + { + case GTK_SCROLL_STEP_BACKWARD: + gtk_range_draw_step_back (range); + break; + case GTK_SCROLL_STEP_FORWARD: + gtk_range_draw_step_forw (range); + break; + } + } + } + if (pos != GTK_TROUGH_NONE) + { + if (pos == GTK_TROUGH_START) + range->adjustment->value = range->adjustment->lower; + else + range->adjustment->value = + range->adjustment->upper - range->adjustment->page_size; + + if (range->old_value != range->adjustment->value) + { + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), + "value_changed"); + + gtk_range_slider_update (range); + gtk_range_draw_background (range); + } + } + } + return return_val; +} + +static gint +gtk_range_enter_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + GtkRange *range; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + range = GTK_RANGE (widget); + + if (event->window == range->trough) + { + range->in_child = RANGE_CLASS (range)->trough; + } + else if (event->window == range->slider) + { + range->in_child = RANGE_CLASS (range)->slider; + + if ((range->click_child == 0) || + (range->click_child == RANGE_CLASS (range)->trough)) + gtk_range_draw_slider (range); + } + else if (event->window == range->step_forw) + { + range->in_child = RANGE_CLASS (range)->step_forw; + + if ((range->click_child == 0) || + (range->click_child == RANGE_CLASS (range)->trough)) + gtk_range_draw_step_forw (range); + } + else if (event->window == range->step_back) + { + range->in_child = RANGE_CLASS (range)->step_back; + + if ((range->click_child == 0) || + (range->click_child == RANGE_CLASS (range)->trough)) + gtk_range_draw_step_back (range); + } + + return FALSE; +} + +static gint +gtk_range_leave_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + GtkRange *range; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + range = GTK_RANGE (widget); + + range->in_child = 0; + + if (event->window == range->trough) + { + } + else if (event->window == range->slider) + { + if ((range->click_child == 0) || + (range->click_child == RANGE_CLASS (range)->trough)) + gtk_range_draw_slider (range); + } + else if (event->window == range->step_forw) + { + if ((range->click_child == 0) || + (range->click_child == RANGE_CLASS (range)->trough)) + gtk_range_draw_step_forw (range); + } + else if (event->window == range->step_back) + { + if ((range->click_child == 0) || + (range->click_child == RANGE_CLASS (range)->trough)) + gtk_range_draw_step_back (range); + } + + return FALSE; +} + +static gint +gtk_range_focus_in (GtkWidget *widget, + GdkEventFocus *event) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); + gtk_widget_draw_focus (widget); + + return FALSE; +} + +static gint +gtk_range_focus_out (GtkWidget *widget, + GdkEventFocus *event) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); + gtk_widget_draw_focus (widget); + + return FALSE; +} + +static void +gtk_real_range_draw_trough (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->trough) + { + gtk_draw_shadow (GTK_WIDGET (range)->style, range->trough, + GTK_STATE_NORMAL, GTK_SHADOW_IN, + 0, 0, -1, -1); + + if (GTK_WIDGET_HAS_FOCUS (range)) + gdk_draw_rectangle (GTK_WIDGET (range)->window, + GTK_WIDGET (range)->style->black_gc, + FALSE, 0, 0, + GTK_WIDGET (range)->allocation.width - 1, + GTK_WIDGET (range)->allocation.height - 1); + else if (range->trough != GTK_WIDGET (range)->window) + gdk_draw_rectangle (GTK_WIDGET (range)->window, + GTK_WIDGET (range)->style->bg_gc[GTK_STATE_NORMAL], + FALSE, 0, 0, + GTK_WIDGET (range)->allocation.width - 1, + GTK_WIDGET (range)->allocation.height - 1); + } +} + +static void +gtk_real_range_draw_slider (GtkRange *range) +{ + GtkStateType state_type; + + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->slider) + { + if ((range->in_child == RANGE_CLASS (range)->slider) || + (range->click_child == RANGE_CLASS (range)->slider)) + state_type = GTK_STATE_PRELIGHT; + else + state_type = GTK_STATE_NORMAL; + + gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type); + gdk_window_clear (range->slider); + + gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider, + state_type, GTK_SHADOW_OUT, + 0, 0, -1, -1); + } +} + +static gint +gtk_real_range_timer (GtkRange *range) +{ + gint return_val; + + g_return_val_if_fail (range != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (range), FALSE); + + return_val = TRUE; + if (range->click_child == RANGE_CLASS (range)->slider) + { + if (range->policy == GTK_UPDATE_DELAYED) + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + return_val = FALSE; + } + else + { + if (!range->timer) + { + return_val = FALSE; + if (range->need_timer) + range->timer = gtk_timeout_add (SCROLL_TIMER_LENGTH, + (GtkFunction) RANGE_CLASS (range)->timer, + (gpointer) range); + else + return FALSE; + range->need_timer = FALSE; + } + + if (gtk_range_scroll (range)) + return return_val; + } + + return return_val; +} + +static gint +gtk_range_scroll (GtkRange *range) +{ + gfloat new_value; + gint return_val; + + g_return_val_if_fail (range != NULL, FALSE); + g_return_val_if_fail (GTK_IS_RANGE (range), FALSE); + + new_value = range->adjustment->value; + return_val = TRUE; + + switch (range->scroll_type) + { + case GTK_SCROLL_NONE: + break; + + case GTK_SCROLL_STEP_BACKWARD: + new_value -= range->adjustment->step_increment; + if (new_value <= range->adjustment->lower) + { + new_value = range->adjustment->lower; + return_val = FALSE; + range->timer = 0; + } + break; + + case GTK_SCROLL_STEP_FORWARD: + new_value += range->adjustment->step_increment; + if (new_value >= (range->adjustment->upper - range->adjustment->page_size)) + { + new_value = range->adjustment->upper - range->adjustment->page_size; + return_val = FALSE; + range->timer = 0; + } + break; + + case GTK_SCROLL_PAGE_BACKWARD: + new_value -= range->adjustment->page_increment; + if (new_value <= range->adjustment->lower) + { + new_value = range->adjustment->lower; + return_val = FALSE; + range->timer = 0; + } + break; + + case GTK_SCROLL_PAGE_FORWARD: + new_value += range->adjustment->page_increment; + if (new_value >= (range->adjustment->upper - range->adjustment->page_size)) + { + new_value = range->adjustment->upper - range->adjustment->page_size; + return_val = FALSE; + range->timer = 0; + } + break; + } + + if (new_value != range->adjustment->value) + { + range->adjustment->value = new_value; + + if ((range->policy == GTK_UPDATE_CONTINUOUS) || + (!return_val && (range->policy == GTK_UPDATE_DELAYED))) + { + gtk_signal_emit_by_name (GTK_OBJECT (range->adjustment), "value_changed"); + } + else + { + gtk_range_slider_update (range); + gtk_range_draw_background (range); + } + } + + return return_val; +} + + +static void +gtk_range_add_timer (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (!range->timer) + { + range->need_timer = TRUE; + range->timer = gtk_timeout_add (SCROLL_INITIAL_DELAY, + (GtkFunction) RANGE_CLASS (range)->timer, + (gpointer) range); + } +} + +static void +gtk_range_remove_timer (GtkRange *range) +{ + g_return_if_fail (range != NULL); + g_return_if_fail (GTK_IS_RANGE (range)); + + if (range->timer) + { + gtk_timeout_remove (range->timer); + range->timer = 0; + } + range->need_timer = FALSE; +} + +static void +gtk_range_adjustment_changed (GtkAdjustment *adjustment, + gpointer data) +{ + GtkRange *range; + + g_return_if_fail (adjustment != NULL); + g_return_if_fail (data != NULL); + + range = GTK_RANGE (data); + + if (((range->old_lower != adjustment->lower) || + (range->old_upper != adjustment->upper) || + (range->old_page_size != adjustment->page_size)) && + (range->old_value == adjustment->value)) + { + if ((adjustment->lower == adjustment->upper) || + (range->old_lower == (range->old_upper - range->old_page_size))) + { + adjustment->value = adjustment->lower; + gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed"); + } + } + + if ((range->old_value != adjustment->value) || + (range->old_lower != adjustment->lower) || + (range->old_upper != adjustment->upper) || + (range->old_page_size != adjustment->page_size)) + { + gtk_range_slider_update (range); + gtk_range_draw_background (range); + + range->old_value = adjustment->value; + range->old_lower = adjustment->lower; + range->old_upper = adjustment->upper; + range->old_page_size = adjustment->page_size; + } +} + +static void +gtk_range_adjustment_value_changed (GtkAdjustment *adjustment, + gpointer data) +{ + GtkRange *range; + + g_return_if_fail (adjustment != NULL); + g_return_if_fail (data != NULL); + + range = GTK_RANGE (data); + + if (range->old_value != adjustment->value) + { + gtk_range_slider_update (range); + gtk_range_draw_background (range); + + range->old_value = adjustment->value; + } +} + + +static void +gtk_range_trough_hdims (GtkRange *range, + gint *left, + gint *right) +{ + gint trough_width; + gint slider_length; + gint tmp_width; + gint tleft; + gint tright; + + g_return_if_fail (range != NULL); + + gdk_window_get_size (range->trough, &trough_width, NULL); + gdk_window_get_size (range->slider, &slider_length, NULL); + + tleft = GTK_WIDGET (range)->style->klass->xthickness; + tright = trough_width - slider_length - GTK_WIDGET (range)->style->klass->xthickness; + + if (range->step_back) + { + gdk_window_get_size (range->step_back, &tmp_width, NULL); + tleft += (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing); + } + + if (range->step_forw) + { + gdk_window_get_size (range->step_forw, &tmp_width, NULL); + tright -= (tmp_width + RANGE_CLASS (range)->stepper_slider_spacing); + } + + if (left) + *left = tleft; + if (right) + *right = tright; +} + +static void +gtk_range_trough_vdims (GtkRange *range, + gint *top, + gint *bottom) +{ + gint trough_height; + gint slider_length; + gint tmp_height; + gint ttop; + gint tbottom; + + g_return_if_fail (range != NULL); + + gdk_window_get_size (range->trough, NULL, &trough_height); + gdk_window_get_size (range->slider, NULL, &slider_length); + + ttop = GTK_WIDGET (range)->style->klass->xthickness; + tbottom = trough_height - slider_length - GTK_WIDGET (range)->style->klass->ythickness; + + if (range->step_back) + { + gdk_window_get_size (range->step_back, NULL, &tmp_height); + ttop += (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing); + } + + if (range->step_forw) + { + gdk_window_get_size (range->step_forw, NULL, &tmp_height); + tbottom -= (tmp_height + RANGE_CLASS (range)->stepper_slider_spacing); + } + + if (top) + *top = ttop; + if (bottom) + *bottom = tbottom; +} |