diff options
author | Michael Natterer <mitch@imendio.com> | 2006-11-15 12:23:10 +0000 |
---|---|---|
committer | Michael Natterer <mitch@src.gnome.org> | 2006-11-15 12:23:10 +0000 |
commit | eeff106d4efe299c4880bd9be46e7fd4c0274d59 (patch) | |
tree | ab11ba24a43e58a619edd657b0bd8e8b37644545 | |
parent | d5b35a5db9e63e4a7eb89ca6b24c677a81fb2cd2 (diff) | |
download | gdk-pixbuf-eeff106d4efe299c4880bd9be46e7fd4c0274d59.tar.gz |
added properties "fill-level", "show-fill-level" and
2006-11-15 Michael Natterer <mitch@imendio.com>
* gtk/gtkrange.[ch]: added properties "fill-level",
"show-fill-level" and "restrict-to-fill-level" and getters/setters
for them. The "fill level" is an additional marker on the range's
trough than can be e.g. used to indicate the amount of
pre-buffering in a range showing the play position of streamed
media. See the embedded API docs for details. Made GtkRangeLayout
a GTypeInstance private struct and removed finalize()
implementation. Fixes bug #349808
* gtk/gtk.symbols: added the new symbols.
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | gtk/gtk.symbols | 6 | ||||
-rw-r--r-- | gtk/gtkrange.c | 326 | ||||
-rw-r--r-- | gtk/gtkrange.h | 12 |
4 files changed, 339 insertions, 18 deletions
@@ -1,3 +1,16 @@ +2006-11-15 Michael Natterer <mitch@imendio.com> + + * gtk/gtkrange.[ch]: added properties "fill-level", + "show-fill-level" and "restrict-to-fill-level" and getters/setters + for them. The "fill level" is an additional marker on the range's + trough than can be e.g. used to indicate the amount of + pre-buffering in a range showing the play position of streamed + media. See the embedded API docs for details. Made GtkRangeLayout + a GTypeInstance private struct and removed finalize() + implementation. Fixes bug #349808 + + * gtk/gtk.symbols: added the new symbols. + 2006-11-14 Behdad Esfahbod <behdad@gnome.org> * configure.in: Make libtool magic robust. (#352795) diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 787be1305..61343e4a0 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -2955,17 +2955,23 @@ gtk_radio_tool_button_set_group #if IN_HEADER(__GTK_RANGE_H__) #if IN_FILE(__GTK_RANGE_C__) gtk_range_get_adjustment +gtk_range_get_fill_level gtk_range_get_inverted gtk_range_get_lower_stepper_sensitivity +gtk_range_get_restrict_to_fill_level +gtk_range_get_show_fill_level gtk_range_get_type G_GNUC_CONST gtk_range_get_update_policy gtk_range_get_upper_stepper_sensitivity gtk_range_get_value gtk_range_set_adjustment +gtk_range_set_fill_level gtk_range_set_increments gtk_range_set_inverted gtk_range_set_lower_stepper_sensitivity gtk_range_set_range +gtk_range_set_restrict_to_fill_level +gtk_range_set_show_fill_level gtk_range_set_update_policy gtk_range_set_upper_stepper_sensitivity gtk_range_set_value diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index ec88c7409..216f9049c 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -46,7 +46,10 @@ enum { PROP_ADJUSTMENT, PROP_INVERTED, PROP_LOWER_STEPPER_SENSITIVITY, - PROP_UPPER_STEPPER_SENSITIVITY + PROP_UPPER_STEPPER_SENSITIVITY, + PROP_SHOW_FILL_LEVEL, + PROP_RESTRICT_TO_FILL_LEVEL, + PROP_FILL_LEVEL }; enum { @@ -68,6 +71,8 @@ typedef enum { MOUSE_WIDGET /* inside widget but not in any of the above GUI elements */ } MouseLocation; +#define GTK_RANGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RANGE, GtkRangeLayout)) + struct _GtkRangeLayout { /* These are in widget->window coordinates */ @@ -96,8 +101,14 @@ struct _GtkRangeLayout guint lower_sensitive : 1; guint upper_sensitive : 1; + /* Fill level */ + guint show_fill_level : 1; + guint restrict_to_fill_level : 1; + GtkSensitivityType lower_sensitivity; GtkSensitivityType upper_sensitivity; + + gdouble fill_level; }; @@ -110,7 +121,6 @@ static void gtk_range_get_property (GObject *object, GValue *value, GParamSpec *pspec); static void gtk_range_destroy (GtkObject *object); -static void gtk_range_finalize (GObject *object); static void gtk_range_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_range_size_allocate (GtkWidget *widget, @@ -214,7 +224,6 @@ gtk_range_class_init (GtkRangeClass *class) gobject_class->set_property = gtk_range_set_property; gobject_class->get_property = gtk_range_get_property; - gobject_class->finalize = gtk_range_finalize; object_class->destroy = gtk_range_destroy; widget_class->size_request = gtk_range_size_request; @@ -351,6 +360,58 @@ gtk_range_class_init (GtkRangeClass *class) GTK_SENSITIVITY_AUTO, GTK_PARAM_READWRITE)); + /** + * GtkRange:show-fill-level: + * + * The show-fill-level property controls wether fill level indicator + * graphics are displayed on the trough. See + * gtk_range_set_show_fill_level(). + * + * Since: 2.12 + **/ + g_object_class_install_property (gobject_class, + PROP_SHOW_FILL_LEVEL, + g_param_spec_boolean ("show-fill-level", + P_("Show Fill Level"), + P_("Whether to display a fill level indicator graphics on trough."), + FALSE, + GTK_PARAM_READWRITE)); + + /** + * GtkRange:restrict-to-fill-level: + * + * The restrict-to-fill-level proeprty controls whether slider + * movement is restricted to an upper boundary set by the + * fill-level. See gtk_range_set_restrict_to_fill_level(). + * + * Since: 2.12 + **/ + g_object_class_install_property (gobject_class, + PROP_RESTRICT_TO_FILL_LEVEL, + g_param_spec_boolean ("restrict-to-fill-level", + P_("Restrict to Fill Level"), + P_("Whether to restrict the upper boundary to the fill level."), + TRUE, + GTK_PARAM_READWRITE)); + + /** + * GtkRange:fill-level: + * + * The fill level (e.g. prebuffering of a network stream). + * See gtk_range_set_fill_level(). + * + * Since: 2.12 + **/ + g_object_class_install_property (gobject_class, + PROP_FILL_LEVEL, + g_param_spec_double ("fill-level", + P_("Fill Level"), + P_("The fill level."), + -G_MAXDOUBLE, + G_MAXDOUBLE, + G_MAXDOUBLE, + GTK_PARAM_READWRITE)); + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("slider-width", P_("Slider Width"), @@ -443,6 +504,8 @@ gtk_range_class_init (GtkRangeClass *class) P_("Whether to draw trought for full length of range or exclude the steppers and spacing"), TRUE, GTK_PARAM_READABLE)); + + g_type_class_add_private (class, sizeof (GtkRangeLayout)); } static void @@ -472,6 +535,15 @@ gtk_range_set_property (GObject *object, case PROP_UPPER_STEPPER_SENSITIVITY: gtk_range_set_upper_stepper_sensitivity (range, g_value_get_enum (value)); break; + case PROP_SHOW_FILL_LEVEL: + gtk_range_set_show_fill_level (range, g_value_get_boolean (value)); + break; + case PROP_RESTRICT_TO_FILL_LEVEL: + gtk_range_set_restrict_to_fill_level (range, g_value_get_boolean (value)); + break; + case PROP_FILL_LEVEL: + gtk_range_set_fill_level (range, g_value_get_double (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -505,6 +577,15 @@ gtk_range_get_property (GObject *object, case PROP_UPPER_STEPPER_SENSITIVITY: g_value_set_enum (value, gtk_range_get_upper_stepper_sensitivity (range)); break; + case PROP_SHOW_FILL_LEVEL: + g_value_set_boolean (value, gtk_range_get_show_fill_level (range)); + break; + case PROP_RESTRICT_TO_FILL_LEVEL: + g_value_set_boolean (value, gtk_range_get_restrict_to_fill_level (range)); + break; + case PROP_FILL_LEVEL: + g_value_set_double (value, gtk_range_get_fill_level (range)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -527,7 +608,7 @@ gtk_range_init (GtkRange *range) range->has_stepper_d = FALSE; range->need_recalc = TRUE; range->round_digits = -1; - range->layout = g_new0 (GtkRangeLayout, 1); + range->layout = GTK_RANGE_GET_PRIVATE (range); range->layout->mouse_location = MOUSE_OUTSIDE; range->layout->mouse_x = -1; range->layout->mouse_y = -1; @@ -537,6 +618,9 @@ gtk_range_init (GtkRange *range) range->layout->upper_sensitivity = GTK_SENSITIVITY_AUTO; range->layout->lower_sensitive = TRUE; range->layout->upper_sensitive = TRUE; + range->layout->show_fill_level = FALSE; + range->layout->restrict_to_fill_level = TRUE; + range->layout->fill_level = G_MAXDOUBLE; range->timer = NULL; } @@ -844,8 +928,13 @@ gtk_range_set_range (GtkRange *range, range->adjustment->lower = min; range->adjustment->upper = max; - value = CLAMP (range->adjustment->value, - range->adjustment->lower, + value = range->adjustment->value; + + if (range->layout->restrict_to_fill_level) + value = MIN (value, MAX (range->adjustment->lower, + range->layout->fill_level)); + + value = CLAMP (value, range->adjustment->lower, (range->adjustment->upper - range->adjustment->page_size)); gtk_adjustment_set_value (range->adjustment, value); @@ -868,7 +957,11 @@ gtk_range_set_value (GtkRange *range, gdouble value) { g_return_if_fail (GTK_IS_RANGE (range)); - + + if (range->layout->restrict_to_fill_level) + value = MIN (value, MAX (range->adjustment->lower, + range->layout->fill_level)); + value = CLAMP (value, range->adjustment->lower, (range->adjustment->upper - range->adjustment->page_size)); @@ -891,6 +984,153 @@ gtk_range_get_value (GtkRange *range) return range->adjustment->value; } +/** + * gtk_range_set_show_fill_level: + * @range: A #GtkRange + * @show_fill_level: Whether a fill level indicator graphics is shown. + * + * Sets whether a graphical fill level is show on the trough. See + * gtk_range_set_fill_level() for a general description of the fill + * level concept. + * + * Since: 2.12 + **/ +void +gtk_range_set_show_fill_level (GtkRange *range, + gboolean show_fill_level) +{ + g_return_if_fail (GTK_IS_RANGE (range)); + + show_fill_level = show_fill_level ? TRUE : FALSE; + + if (show_fill_level != range->layout->show_fill_level) + { + range->layout->show_fill_level = show_fill_level; + g_object_notify (G_OBJECT (range), "show-fill-level"); + gtk_widget_queue_draw (GTK_WIDGET (range)); + } +} + +/** + * gtk_range_get_show_fill_level: + * @range: A #GtkRange + * + * Return value: Whether GtkRange displays a fill level graphics. + * + * Since: 2.12 + **/ +gboolean +gtk_range_get_show_fill_level (GtkRange *range) +{ + g_return_val_if_fail (GTK_IS_RANGE (range), FALSE); + + return range->layout->show_fill_level; +} + +/** + * gtk_range_set_restrict_to_fill_level: + * @range: A #GtkRange + * @restrict_to_fill_level: Whether the fill level restricts slider movement. + * + * Sets whether the slider is restricted to the fill level. See + * gtk_range_set_fill_level() for a general description of the fill + * level concept. + * + * Since: 2.12 + **/ +void +gtk_range_set_restrict_to_fill_level (GtkRange *range, + gboolean restrict_to_fill_level) +{ + g_return_if_fail (GTK_IS_RANGE (range)); + + restrict_to_fill_level = restrict_to_fill_level ? TRUE : FALSE; + + if (restrict_to_fill_level != range->layout->restrict_to_fill_level) + { + range->layout->restrict_to_fill_level = restrict_to_fill_level; + g_object_notify (G_OBJECT (range), "restrict-to-fill-level"); + + gtk_range_set_value (range, gtk_range_get_value (range)); + } +} + +/** + * gtk_range_get_restrict_to_fill_level: + * @range: A #GtkRange + * + * Return value: Whether GtkRange is restricted to the fill level. + * + * Since: 2.12 + **/ +gboolean +gtk_range_get_restrict_to_fill_level (GtkRange *range) +{ + g_return_val_if_fail (GTK_IS_RANGE (range), FALSE); + + return range->layout->restrict_to_fill_level; +} + +/** + * gtk_range_set_fill_level: + * @range: A #GtkRange + * @positon: The new position of the fill level indicator + * + * Set the new position of the fill level indicator. + * + * The "fill level" is probably best described by its most prominent + * use case, which is an indicator for the amount of pre-buffering in + * a streaming media player. In that use case, the value of the range + * would indicate the current play position, and the fill level would + * be the position up to which the file/stream has been downloaded. + * + * This amount of prebuffering can be displayed on the range's trough + * and is themeable separately from the trough. To enable fill level + * display, use gtk_range_set_show_fill_level(). The range defaults + * to not showing the fill level. + * + * Additionally, it's possible to restrict the range's slider position + * to values which are smaller than the fill level. This is controller + * by gtk_range_set_restrict_to_fill_level() and is by default + * enabled. + * + * Since: 2.12 + **/ +void +gtk_range_set_fill_level (GtkRange *range, + gdouble fill_level) +{ + g_return_if_fail (GTK_IS_RANGE (range)); + + if (fill_level != range->layout->fill_level) + { + range->layout->fill_level = fill_level; + g_object_notify (G_OBJECT (range), "fill-level"); + + if (range->layout->show_fill_level) + gtk_widget_queue_draw (GTK_WIDGET (range)); + + if (range->layout->restrict_to_fill_level) + gtk_range_set_value (range, gtk_range_get_value (range)); + } +} + +/** + * gtk_range_get_fill_level: + * @range : A #GtkRange + * + * Return value: The current position of the fill level indicator. + * + * Since: 2.12 + **/ +gdouble +gtk_range_get_fill_level (GtkRange *range) +{ + g_return_val_if_fail (GTK_IS_RANGE (range), 0.0); + + return range->layout->fill_level; +} + static gboolean should_invert (GtkRange *range) { @@ -904,16 +1144,6 @@ should_invert (GtkRange *range) } static void -gtk_range_finalize (GObject *object) -{ - GtkRange *range = GTK_RANGE (object); - - g_free (range->layout); - - (* G_OBJECT_CLASS (gtk_range_parent_class)->finalize) (object); -} - -static void gtk_range_destroy (GtkObject *object) { GtkRange *range = GTK_RANGE (object); @@ -1314,6 +1544,64 @@ gtk_range_expose (GtkWidget *widget, height - trough_change_pos_y); } + if (range->layout->show_fill_level && + range->adjustment->upper - range->adjustment->page_size - + range->adjustment->lower != 0) + { + gdouble fill_level = range->layout->fill_level; + gint fill_x = x; + gint fill_y = y; + gint fill_width = width; + gint fill_height = height; + gchar *fill_detail; + + fill_level = CLAMP (fill_level, range->adjustment->lower, + range->adjustment->upper - + range->adjustment->page_size); + + if (range->orientation == GTK_ORIENTATION_HORIZONTAL) + { + fill_x = widget->allocation.x + range->layout->trough.x; + fill_width = (range->layout->slider.width + + (fill_level - range->adjustment->lower) / + (range->adjustment->upper - + range->adjustment->lower - + range->adjustment->page_size) * + (range->layout->trough.width - + range->layout->slider.width)); + + if (should_invert (range)) + fill_x += range->layout->trough.width - fill_width; + } + else + { + fill_y = widget->allocation.y + range->layout->trough.y; + fill_height = (range->layout->slider.height + + (fill_level - range->adjustment->lower) / + (range->adjustment->upper - + range->adjustment->lower - + range->adjustment->page_size) * + (range->layout->trough.height - + range->layout->slider.height)); + + if (should_invert (range)) + fill_y += range->layout->trough.height - fill_height; + } + + if (fill_level < range->adjustment->upper - range->adjustment->page_size) + fill_detail = "trough-fill-level-full"; + else + fill_detail = "trough-fill-level"; + + gtk_paint_box (widget->style, + widget->window, + sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, + GTK_SHADOW_OUT, + &area, GTK_WIDGET (range), fill_detail, + fill_x, fill_y, + fill_width, fill_height); + } + if (sensitive && GTK_WIDGET_HAS_FOCUS (range)) gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), @@ -2901,6 +3189,10 @@ gtk_range_real_change_value (GtkRange *range, /* potentially adjust the bounds _before we clamp */ g_signal_emit (range, signals[ADJUST_BOUNDS], 0, value); + if (range->layout->restrict_to_fill_level) + value = MIN (value, MAX (range->adjustment->lower, + range->layout->fill_level)); + value = CLAMP (value, range->adjustment->lower, (range->adjustment->upper - range->adjustment->page_size)); diff --git a/gtk/gtkrange.h b/gtk/gtkrange.h index d4ef1b3e8..7ebb9df67 100644 --- a/gtk/gtkrange.h +++ b/gtk/gtkrange.h @@ -160,7 +160,17 @@ void gtk_range_set_value (GtkRange *range gdouble value); gdouble gtk_range_get_value (GtkRange *range); -gdouble _gtk_range_get_wheel_delta (GtkRange *range, +void gtk_range_set_show_fill_level (GtkRange *range, + gboolean show_fill_level); +gboolean gtk_range_get_show_fill_level (GtkRange *range); +void gtk_range_set_restrict_to_fill_level (GtkRange *range, + gboolean restrict_to_fill_level); +gboolean gtk_range_get_restrict_to_fill_level (GtkRange *range); +void gtk_range_set_fill_level (GtkRange *range, + gdouble fill_level); +gdouble gtk_range_get_fill_level (GtkRange *range); + +gdouble _gtk_range_get_wheel_delta (GtkRange *range, GdkScrollDirection direction); |