-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 2001 Red Hat, Inc.
*
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include <config.h>
+#include "config.h"
#include <stdio.h>
#include <math.h>
#include <gdk/gdkkeysyms.h>
GtkSensitivityType lower_sensitivity;
GtkSensitivityType upper_sensitivity;
+ guint repaint_id;
gdouble fill_level;
};
static void gtk_range_unrealize (GtkWidget *widget);
static void gtk_range_map (GtkWidget *widget);
static void gtk_range_unmap (GtkWidget *widget);
-static gint gtk_range_expose (GtkWidget *widget,
+static gboolean gtk_range_expose (GtkWidget *widget,
GdkEventExpose *event);
-static gint gtk_range_button_press (GtkWidget *widget,
+static gboolean gtk_range_button_press (GtkWidget *widget,
GdkEventButton *event);
-static gint gtk_range_button_release (GtkWidget *widget,
+static gboolean gtk_range_button_release (GtkWidget *widget,
GdkEventButton *event);
-static gint gtk_range_motion_notify (GtkWidget *widget,
+static gboolean gtk_range_motion_notify (GtkWidget *widget,
GdkEventMotion *event);
-static gint gtk_range_enter_notify (GtkWidget *widget,
+static gboolean gtk_range_enter_notify (GtkWidget *widget,
GdkEventCrossing *event);
-static gint gtk_range_leave_notify (GtkWidget *widget,
+static gboolean gtk_range_leave_notify (GtkWidget *widget,
GdkEventCrossing *event);
static gboolean gtk_range_grab_broken (GtkWidget *widget,
GdkEventGrabBroken *event);
gboolean was_grabbed);
static void gtk_range_state_changed (GtkWidget *widget,
GtkStateType previous_state);
-static gint gtk_range_scroll_event (GtkWidget *widget,
+static gboolean gtk_range_scroll_event (GtkWidget *widget,
GdkEventScroll *event);
static void gtk_range_style_set (GtkWidget *widget,
GtkStyle *previous_style);
GtkScrollType scroll);
/* Internals */
-static void gtk_range_scroll (GtkRange *range,
+static gboolean gtk_range_scroll (GtkRange *range,
GtkScrollType scroll);
static gboolean gtk_range_update_mouse_location (GtkRange *range);
static void gtk_range_calc_layout (GtkRange *range,
class->slider_detail = "slider";
class->stepper_detail = "stepper";
+ /**
+ * GtkRange::value-changed:
+ * @range: the #GtkRange
+ *
+ * Emitted when the range value changes.
+ */
signals[VALUE_CHANGED] =
g_signal_new (I_("value_changed"),
G_TYPE_FROM_CLASS (gobject_class),
G_TYPE_NONE, 1,
G_TYPE_DOUBLE);
+ /**
+ * GtkRange::move-slider:
+ * @range: the #GtkRange
+ * @step: how to move the slider
+ *
+ * Virtual function that moves the slider. Used for keybindings.
+ */
signals[MOVE_SLIDER] =
g_signal_new (I_("move_slider"),
G_TYPE_FROM_CLASS (gobject_class),
/**
* GtkRange::change-value:
- * @range: the range that received the signal.
- * @scroll: the type of scroll action that was performed.
- * @value: the new value resulting from the scroll action.
+ * @range: the range that received the signal
+ * @scroll: the type of scroll action that was performed
+ * @value: the new value resulting from the scroll action
* @returns: %TRUE to prevent other handlers from being invoked for the
- * signal. %FALSE to propagate the signal further.
+ * signal, %FALSE to propagate the signal further
*
* The ::change-value signal is emitted when a scroll action is
* performed on a range. It allows an application to determine the
G_TYPE_BOOLEAN, 2,
GTK_TYPE_SCROLL_TYPE,
G_TYPE_DOUBLE);
-
+
g_object_class_install_property (gobject_class,
PROP_UPDATE_POLICY,
g_param_spec_enum ("update-policy",
/**
* GtkRange:show-fill-level:
*
- * The show-fill-level property controls wether fill level indicator
+ * The show-fill-level property controls whether fill level indicator
* graphics are displayed on the trough. See
* gtk_range_set_show_fill_level().
*
/**
* GtkRange:restrict-to-fill-level:
*
- * The restrict-to-fill-level proeprty controls whether slider
+ * The restrict-to-fill-level property controls whether slider
* movement is restricted to an upper boundary set by the
- * fill-level. See gtk_range_set_restrict_to_fill_level().
+ * fill level. See gtk_range_set_restrict_to_fill_level().
*
* Since: 2.12
**/
*
* The spacing between the stepper buttons and thumb. Note that
* setting this value to anything > 0 will automatically set the
- * trough-under-steppers style property to TRUE as well. Also,
+ * trough-under-steppers style property to %TRUE as well. Also,
* stepper-spacing won't have any effect if there are no steppers.
*/
gtk_widget_class_install_style_property (widget_class,
/**
* GtkRange:trough-side-details:
*
+ * When %TRUE, the parts of the trough on the two sides of the
+ * slider are drawn with different details.
+ *
* Since: 2.10
*/
gtk_widget_class_install_style_property (widget_class,
*
* Whether to draw the trough across the full length of the range or
* to exclude the steppers and their spacing. Note that setting the
- * stepper-spacing style property to any value > 0 will
+ * #GtkRange:stepper-spacing style property to any value > 0 will
* automatically enable trough-under-steppers too.
*
* Since: 2.10
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boolean ("trough-under-steppers",
P_("Trough Under Steppers"),
- P_("Whether to draw trought for full length of range or exclude the steppers and spacing"),
+ P_("Whether to draw trough for full length of range or exclude the steppers and spacing"),
TRUE,
GTK_PARAM_READABLE));
* continuous. #GTK_UPDATE_DISCONTINUOUS means that the value will only
* be updated when the user releases the button and ends the slider
* drag operation.
- *
**/
void
gtk_range_set_update_policy (GtkRange *range,
* is normally 0 for #GtkScale and nonzero for #GtkScrollbar, and
* indicates the size of the visible area of the widget being scrolled.
* The page size affects the size of the scrollbar slider.
- *
**/
void
gtk_range_set_adjustment (GtkRange *range,
* slider moves from top to bottom or left to right. Inverted
* ranges have higher values at the top or on the right rather than
* on the bottom or left.
- *
**/
void
gtk_range_set_inverted (GtkRange *range,
* The step size is used when the user clicks the #GtkScrollbar
* arrows or moves #GtkScale via arrow keys. The page size
* is used for example when moving via Page Up or Page Down keys.
- *
**/
void
gtk_range_set_increments (GtkRange *range,
*
* Sets the current value of the range; if the value is outside the
* minimum or maximum range values, it will be clamped to fit inside
- * them. The range emits the "value_changed" signal if the value
- * changes.
- *
+ * them. The range emits the #GtkRange::value-changed signal if the
+ * value changes.
**/
void
gtk_range_set_value (GtkRange *range,
* gtk_range_get_show_fill_level:
* @range: A #GtkRange
*
- * Return value: Whether GtkRange displays a fill level graphics.
+ * Gets whether the range displays the fill level graphically.
+ *
+ * Return value: %TRUE if @range shows the fill level.
*
* Since: 2.12
**/
* gtk_range_get_restrict_to_fill_level:
* @range: A #GtkRange
*
- * Return value: Whether GtkRange is restricted to the fill level.
+ * Gets whether the range is restricted to the fill level.
+ *
+ * Return value: %TRUE if @range is restricted to the fill level.
*
* Since: 2.12
**/
/**
* gtk_range_set_fill_level:
- * @range: A #GtkRange
- * @positon: The new position of the fill level indicator
+ * @range: a #GtkRange
+ * @fill_level: the new position of the fill level indicator
*
* Set the new position of the fill level indicator.
*
* gtk_range_get_fill_level:
* @range : A #GtkRange
*
- * Return value: The current position of the fill level indicator.
+ * Gets the current position of the fill level indicator.
+ *
+ * Return value: The current fill level
*
* Since: 2.12
**/
gtk_range_remove_step_timer (range);
gtk_range_remove_update_timer (range);
-
+
+ if (range->layout->repaint_id)
+ g_source_remove (range->layout->repaint_id);
+ range->layout->repaint_id = 0;
+
if (range->adjustment)
{
g_signal_handlers_disconnect_by_func (range->adjustment,
arrow_x, arrow_y, arrow_width, arrow_height);
}
-static gint
+static gboolean
gtk_range_expose (GtkWidget *widget,
GdkEventExpose *event)
{
- GtkRange *range;
+ GtkRange *range = GTK_RANGE (widget);
gboolean sensitive;
GtkStateType state;
GtkShadowType shadow_type;
g_object_get (gtk_widget_get_settings (widget),
"gtk-touchscreen-mode", &touchscreen,
NULL);
+ if (GTK_WIDGET_CAN_FOCUS (range))
+ gtk_widget_style_get (GTK_WIDGET (range),
+ "focus-line-width", &focus_line_width,
+ "focus-padding", &focus_padding,
+ NULL);
- range = GTK_RANGE (widget);
+ /* we're now exposing, so there's no need to force early repaints */
+ if (range->layout->repaint_id)
+ g_source_remove (range->layout->repaint_id);
+ range->layout->repaint_id = 0;
- if (GTK_WIDGET_CAN_FOCUS (range))
- {
- gtk_widget_style_get (GTK_WIDGET (range),
- "focus-line-width", &focus_line_width,
- "focus-padding", &focus_padding,
- NULL);
- }
-
expose_area = event->area;
expose_area.x -= widget->allocation.x;
expose_area.y -= widget->allocation.y;
static void
range_grab_remove (GtkRange *range)
{
+ MouseLocation location;
+
gtk_grab_remove (GTK_WIDGET (range));
-
+
+ location = range->layout->grab_location;
range->layout->grab_location = MOUSE_OUTSIDE;
range->layout->grab_button = 0;
- if (gtk_range_update_mouse_location (range))
+ if (gtk_range_update_mouse_location (range) ||
+ location != MOUSE_OUTSIDE)
gtk_widget_queue_draw (GTK_WIDGET (range));
}
gtk_range_remove_step_timer (range);
/* Flush any pending discontinuous/delayed updates */
gtk_range_update_value (range);
-
- /* Just be lazy about this, if we scrolled it will all redraw anyway,
- * so no point optimizing the button deactivate case
- */
- gtk_widget_queue_draw (GTK_WIDGET (range));
}
static gboolean
return delta;
}
-static gint
+static gboolean
gtk_range_scroll_event (GtkWidget *widget,
GdkEventScroll *event)
{
return TRUE;
}
-static gint
+static gboolean
gtk_range_motion_notify (GtkWidget *widget,
GdkEventMotion *event)
{
return range->layout->mouse_location != MOUSE_OUTSIDE;
}
-static gint
+static gboolean
gtk_range_enter_notify (GtkWidget *widget,
GdkEventCrossing *event)
{
return TRUE;
}
-static gint
+static gboolean
gtk_range_leave_notify (GtkWidget *widget,
GdkEventCrossing *event)
{
*/
}
+static gboolean
+force_repaint (gpointer data)
+{
+ GtkRange *range = GTK_RANGE (data);
+ range->layout->repaint_id = 0;
+ if (GTK_WIDGET_DRAWABLE (range))
+ gdk_window_process_updates (GTK_WIDGET (range)->window, FALSE);
+ return FALSE;
+}
+
static void
gtk_range_adjustment_value_changed (GtkAdjustment *adjustment,
gpointer data)
if (layout_changed (range->layout, &layout))
{
gtk_widget_queue_draw (GTK_WIDGET (range));
-
- /* This is so we don't lag the widget being scrolled. */
- if (GTK_WIDGET_REALIZED (range))
- gdk_window_process_updates (GTK_WIDGET (range)->window, FALSE);
+ /* setup a timer to ensure the range isn't lagging too much behind the scroll position */
+ if (!range->layout->repaint_id)
+ range->layout->repaint_id = gdk_threads_add_timeout_full (GDK_PRIORITY_EVENTS, 181, force_repaint, range, NULL);
}
/* Note that we don't round off to range->round_digits here.
&handled);
}
-static void
+static gboolean
gtk_range_scroll (GtkRange *range,
GtkScrollType scroll)
{
+ gdouble old_value = range->adjustment->value;
+
switch (scroll)
{
case GTK_SCROLL_STEP_LEFT:
case GTK_SCROLL_NONE:
break;
}
+
+ return range->adjustment->value != old_value;
}
static void
}
}
- gtk_range_scroll (range, scroll);
+ if (! gtk_range_scroll (range, scroll))
+ gtk_widget_error_bell (GTK_WIDGET (range));
/* Policy DELAYED makes sense with key events,
* but DISCONTINUOUS doesn't, so we update immediately