Index: gtk/gtkrange.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.c,v
retrieving revision 1.129
diff -u -p -r1.129 gtkrange.c
--- gtk/gtkrange.c	8 Oct 2006 05:07:15 -0000	1.129
+++ gtk/gtkrange.c	26 Oct 2006 16:10:43 -0000
@@ -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 {
@@ -351,6 +354,53 @@ gtk_range_class_init (GtkRangeClass *cla
 						      GTK_SENSITIVITY_AUTO,
 						      GTK_PARAM_READWRITE));
 
+  /**
+   * GtkRange:show-fill-level:
+   *
+   * Whether to display a fill level indicator graphics on trough.
+   *
+   * 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:
+   *
+   * Whether to restrict the upper boundary to the 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).
+   *
+   * 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,
+                                                        0.0,
+                                                        GTK_PARAM_READWRITE));
+
   gtk_widget_class_install_style_property (widget_class,
 					   g_param_spec_int ("slider-width",
 							     P_("Slider Width"),
@@ -472,6 +522,15 @@ gtk_range_set_property (GObject      *ob
     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 +564,15 @@ gtk_range_get_property (GObject      *ob
     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;
@@ -848,6 +916,14 @@ gtk_range_set_range (GtkRange *range,
                  range->adjustment->lower,
                  (range->adjustment->upper - range->adjustment->page_size));
 
+  if (gtk_range_get_show_fill_level (range) &&
+      gtk_range_get_restrict_to_fill_level (range))
+    {
+      gdouble fill_level = gtk_range_get_fill_level (range);
+
+      value = MIN (value, fill_level);
+    }
+
   gtk_adjustment_set_value (range->adjustment, value);
   gtk_adjustment_changed (range->adjustment);
 }
@@ -872,6 +948,14 @@ gtk_range_set_value (GtkRange *range,
   value = CLAMP (value, range->adjustment->lower,
                  (range->adjustment->upper - range->adjustment->page_size));
 
+  if (gtk_range_get_show_fill_level (range) &&
+      gtk_range_get_restrict_to_fill_level (range))
+    {
+      gdouble fill_level = gtk_range_get_fill_level (range);
+
+      value = MIN (value, fill_level);
+    }
+
   gtk_adjustment_set_value (range->adjustment, value);
 }
 
@@ -891,6 +975,168 @@ 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 and
+ *                   restricts the slider.
+ *
+ * Sets whether a graphical fill level is show on the trough and
+ * the slider is restricted to the filled area.
+ *
+ * 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 != gtk_range_get_show_fill_level (range))
+    {
+      g_object_set_data (G_OBJECT (range), "gtk-range-show-fill-level",
+                         GINT_TO_POINTER (show_fill_level));
+      g_object_notify (G_OBJECT (range), "show-fill-level");
+      gtk_widget_queue_draw (GTK_WIDGET (range));
+
+      if (gtk_range_get_restrict_to_fill_level (range))
+        gtk_range_set_value (range, gtk_range_get_value (range));
+    }
+}
+
+/**
+ * gtk_range_get_show_fill_level:
+ * @range: A #GtkRange
+ *
+ * Return value: Whether GtkRange displays a fill level
+ *               graphics and slider is restricted to the filled area
+ *
+ * Since: 2.12
+ **/
+gboolean
+gtk_range_get_show_fill_level (GtkRange *range)
+{
+  g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
+
+  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (range),
+                                             "gtk-range-show-fill-level"));
+}
+
+/**
+ * gtk_range_set_restrict_to_fill_level:
+ * @range:                  A #GtkRange
+ * @restrict_to_fill_level: Whether the fill level restricts the slider
+ *                          when it's shown.
+ *
+ * Sets whether the slider is restricted to the fill level when the
+ * fill level indicator is shown.
+ *
+ * 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 != gtk_range_get_restrict_to_fill_level (range))
+    {
+      g_object_set_data (G_OBJECT (range), "gtk-range-restrict-to-fill-level",
+                         GINT_TO_POINTER (restrict_to_fill_level));
+      g_object_notify (G_OBJECT (range), "restrict-to-fill-level");
+
+      if (gtk_range_get_show_fill_level (range))
+        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 when
+ *               the fill level indicator is shown.
+ *
+ * Since: 2.12
+ **/
+gboolean
+gtk_range_get_restrict_to_fill_level (GtkRange *range)
+{
+  g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
+
+  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (range),
+                                             "gtk-range-restrict-to-fill-level"));
+}
+
+/**
+ * gtk_range_set_fill_level:
+ * @range:   A #GtkRange
+ * @positon: The new position of the fill level indicator
+ *
+ * Sets the new position of the fill level indicator. It is automatically
+ * clamped between lower and upper.  Note that you need to enable
+ * show_fill_level before any fill-level functionality is active.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_range_set_fill_level (GtkRange *range,
+                          gdouble   fill_level)
+{
+  g_return_if_fail (GTK_IS_RANGE (range));
+
+  fill_level = CLAMP (fill_level,
+                      range->adjustment->lower,
+                      range->adjustment->upper - range->adjustment->page_size);
+
+  if (fill_level != gtk_range_get_fill_level (range))
+    {
+      gdouble *val = g_new (gdouble, 1);
+
+      *val = fill_level;
+
+      g_object_set_data_full (G_OBJECT (range), "gtk-range-fill-level",
+                              val, (GDestroyNotify) g_free);
+      g_object_notify (G_OBJECT (range), "fill-level");
+
+      if (gtk_range_get_show_fill_level (range) &&
+          gtk_range_get_restrict_to_fill_level (range))
+        {
+          gtk_widget_queue_draw (GTK_WIDGET (range));
+          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. Note
+ *               that this value is undefined when the fill-level indicator
+ *               is not enabled.
+ *
+ * Since: 2.12
+ **/
+gdouble
+gtk_range_get_fill_level (GtkRange *range)
+{
+  gdouble *val;
+
+  g_return_val_if_fail (GTK_IS_RANGE (range), 0.0);
+
+  val = g_object_get_data (G_OBJECT (range), "gtk-range-fill-level");
+
+  if (val)
+    return *val;
+
+  return 0;
+}
+
 static gboolean
 should_invert (GtkRange *range)
 {  
@@ -1314,6 +1560,61 @@ gtk_range_expose (GtkWidget      *widget
                          height - trough_change_pos_y);
         }
 
+      if (gtk_range_get_show_fill_level (range) &&
+          range->adjustment->upper - range->adjustment->page_size -
+          range->adjustment->lower != 0)
+	{
+          gdouble  fill_level  = gtk_range_get_fill_level (range);
+	  gint     fill_x      = x;
+	  gint     fill_y      = y;
+	  gint     fill_width  = width;
+	  gint     fill_height = height;
+	  gchar   *fill_detail;
+
+	  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 (gtk_range_get_fill_level (range) <
+              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),
@@ -2902,6 +3203,14 @@ gtk_range_real_change_value (GtkRange   
 
   value = CLAMP (value, range->adjustment->lower,
                  (range->adjustment->upper - range->adjustment->page_size));
+
+  if (gtk_range_get_show_fill_level (range) &&
+      gtk_range_get_restrict_to_fill_level (range))
+    {
+      gdouble fill_level = gtk_range_get_fill_level (range);
+
+      value = MIN (value, fill_level);
+    }
 
   if (range->round_digits >= 0)
     {
Index: gtk/gtkrange.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.h,v
retrieving revision 1.31
diff -u -p -r1.31 gtkrange.h
--- gtk/gtkrange.h	11 Nov 2005 12:48:29 -0000	1.31
+++ gtk/gtkrange.h	26 Oct 2006 16:10:43 -0000
@@ -160,6 +160,16 @@ void               gtk_range_set_value  
                                                             gdouble        value);
 gdouble            gtk_range_get_value                     (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);
 
