Index: gtk/gtkrange.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.c,v
retrieving revision 1.128
diff -u -p -r1.128 gtkrange.c
--- gtk/gtkrange.c	18 Jul 2006 14:22:38 -0000	1.128
+++ gtk/gtkrange.c	3 Aug 2006 15:22:22 -0000
@@ -47,7 +47,9 @@ enum {
   PROP_ADJUSTMENT,
   PROP_INVERTED,
   PROP_LOWER_STEPPER_SENSITIVITY,
-  PROP_UPPER_STEPPER_SENSITIVITY
+  PROP_UPPER_STEPPER_SENSITIVITY,
+  PROP_STREAM_INDICATOR,
+  PROP_STREAM_POSITION
 };
 
 enum {
@@ -99,6 +101,8 @@ struct _GtkRangeLayout
 
   GtkSensitivityType lower_sensitivity;
   GtkSensitivityType upper_sensitivity;
+
+  gint stream_pixel_position;
 };
 
 
@@ -352,6 +356,38 @@ gtk_range_class_init (GtkRangeClass *cla
 						      GTK_SENSITIVITY_AUTO,
 						      GTK_PARAM_READWRITE));
 
+  /**
+   * GtkRange:stream-indicator:
+   *
+   * Whether to display a stream indicator graphics on trough.
+   *
+   * Since: 2.12
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_STREAM_INDICATOR,
+                                   g_param_spec_boolean ("stream-indicator",
+                                                         P_("Stream Indicator"),
+                                                         P_("Whether to display a stream indicator graphics on trough."),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkRange:stream-position:
+   *
+   * The position of the streaming.
+   *
+   * Since: 2.12
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_STREAM_POSITION,
+                                   g_param_spec_double ("stream-position",
+							P_("Stream Position"),
+							P_("The position of the streaming."),
+							-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"),
@@ -473,6 +509,12 @@ 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_STREAM_INDICATOR:
+      gtk_range_set_stream_indicator (range, g_value_get_boolean (value));
+      break;
+    case PROP_STREAM_POSITION:
+      gtk_range_set_stream_position (range, g_value_get_double (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -506,6 +548,12 @@ 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_STREAM_INDICATOR:
+      g_value_set_boolean (value, gtk_range_get_stream_indicator (range));
+      break;
+    case PROP_STREAM_POSITION:
+      g_value_set_double (value, gtk_range_get_stream_position (range));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -849,6 +897,9 @@ gtk_range_set_range (GtkRange *range,
                  range->adjustment->lower,
                  (range->adjustment->upper - range->adjustment->page_size));
 
+  if (gtk_range_get_stream_indicator (range))
+    value = MIN (value, gtk_range_get_stream_position (range));
+
   gtk_adjustment_set_value (range->adjustment, value);
   gtk_adjustment_changed (range->adjustment);
 }
@@ -873,6 +924,9 @@ gtk_range_set_value (GtkRange *range,
   value = CLAMP (value, range->adjustment->lower,
                  (range->adjustment->upper - range->adjustment->page_size));
 
+  if (gtk_range_get_stream_indicator (range))
+    value = MIN (value, gtk_range_get_stream_position (range));
+
   gtk_adjustment_set_value (range->adjustment, value);
 }
 
@@ -892,6 +946,125 @@ gtk_range_get_value (GtkRange *range)
   return range->adjustment->value;
 }
 
+/**
+ * gtk_range_set_stream_indicator:
+ * @range: A #GtkRange
+ * @stream_indicator: Whether stream indicator graphics is shown and restricts slider.
+ *
+ * Sets whether a graphical stream indicator is show on the trough and
+ * the slider is restricted to streamed area.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_range_set_stream_indicator (GtkRange *range,
+                                gboolean  stream_indicator)
+{
+  gboolean old_value;
+
+  g_return_if_fail (GTK_IS_RANGE (range));
+
+  stream_indicator = stream_indicator ? TRUE : FALSE;
+
+  old_value = gtk_range_get_stream_indicator (range);
+
+  if (stream_indicator != old_value)
+    {
+      g_object_set_data (G_OBJECT (range), "gtk-range-stream-indicator",
+                         GINT_TO_POINTER (stream_indicator));
+      g_object_notify (G_OBJECT (range), "stream-indicator");
+      gtk_widget_queue_draw (GTK_WIDGET (range));
+
+      gtk_range_set_value (range, gtk_range_get_value (range));
+    }
+}
+
+/**
+ * gtk_range_get_stream_indicator:
+ * @range: A #GtkRange
+ *
+ * Return value: Whether GtkRange displays an stream indicator
+ *               graphics and slider is restricted to streamed area
+ *
+ * Since: 2.12
+ **/
+gboolean
+gtk_range_get_stream_indicator (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-stream-indicator"));
+}
+
+/**
+ * gtk_range_set_stream_position:
+ * @range : A #GtkRange
+ * @position : The new position of the stream indicator
+ *
+ * Sets the new position of the stream indicator.  It is automatically
+ * clamped between lower and upper.  Note that you need to enable
+ * stream_indicator before any stream-functionality is active.
+ *
+ * Since: 2.12
+ **/
+void
+gtk_range_set_stream_position (GtkRange *range,
+                               gdouble   position)
+{
+  gdouble old_value;
+
+  g_return_if_fail (GTK_IS_RANGE (range));
+
+  position = CLAMP (position,
+                    range->adjustment->lower,
+                    range->adjustment->upper);
+
+  old_value = gtk_range_get_stream_position (range);
+
+  if (position != old_value)
+    {
+      gdouble *val = g_new (gdouble, 1);
+
+      *val = position;
+
+      g_object_set_data_full (G_OBJECT (range), "gtk-range-stream-position",
+                              val, (GDestroyNotify) g_free);
+      g_object_notify (G_OBJECT (range), "stream-position");
+
+      if (gtk_range_get_stream_indicator (range))
+        {
+          gtk_widget_queue_draw (GTK_WIDGET (range));
+          gtk_range_set_value (range, gtk_range_get_value (range));
+        }
+    }
+}
+
+/**
+ * gtk_range_get_stream_position:
+ * @range : A #GtkRange
+ *
+ * Return value: The current position of the stream indicator. Note
+ *               that this value is undefined when stream indicator
+ *               is not enabled.
+ *
+ * Since: 2.12
+ **/
+gdouble
+gtk_range_get_stream_position (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-stream-position");
+
+  if (val)
+    return *val;
+
+  return 0;
+}
+
 static gboolean
 should_invert (GtkRange *range)
 {  
@@ -1315,6 +1488,74 @@ gtk_range_expose (GtkWidget      *widget
                          height - trough_change_pos_y);
         }
 
+      if (gtk_range_get_stream_indicator (range) &&
+          gtk_range_get_stream_position (range) > range->adjustment->value)
+	{
+	  gchar *stream_detail;
+	  gint   stream_x = x;
+	  gint   stream_y = y;
+	  gint   stream_width  = width;
+	  gint   stream_height = height;
+
+	  if (range->orientation == GTK_ORIENTATION_HORIZONTAL)
+	    {
+	      stream_x     = widget->allocation.x + range->layout->slider.x;
+	      stream_width = (widget->allocation.x +
+                              range->layout->stream_pixel_position -
+                              stream_x);
+
+              if (stream_width < 0)
+                {
+                  stream_x += stream_width;
+                  stream_width *= -1;
+                }
+
+#if 0
+              gdk_draw_line (widget->window,
+                             widget->style->black_gc,
+                             widget->allocation.x + range->layout->stream_pixel_position,
+                             y,
+                             widget->allocation.x + range->layout->stream_pixel_position,
+                             y + height - 1);
+#endif
+	    }
+	  else
+	    {
+	      stream_y      = widget->allocation.y + range->layout->slider.y;
+	      stream_height = (widget->allocation.y +
+                               range->layout->stream_pixel_position -
+                               stream_y);
+
+              if (stream_height < 0)
+                {
+                  stream_y += stream_height;
+                  stream_height *= -1;
+                }
+
+#if 0
+              gdk_draw_line (widget->window,
+                             widget->style->black_gc,
+                             x,
+                             widget->allocation.y + range->layout->stream_pixel_position,
+                             x + width - 1,
+                             widget->allocation.y + range->layout->stream_pixel_position);
+#endif
+	    }
+
+	  if (gtk_range_get_stream_position (range) <= range->adjustment->upper)
+	    stream_detail = "trough-stream-complete";
+	  else
+	    stream_detail = "trough-stream";
+
+          gtk_paint_box (widget->style,
+                         widget->window,
+                         sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE,
+                         GTK_SHADOW_OUT,
+                         &area, GTK_WIDGET (range), stream_detail,
+                         stream_x, stream_y,
+                         stream_width, stream_height);
+	}
+
       if (sensitive &&
           GTK_WIDGET_HAS_FOCUS (range))
         gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
@@ -2678,6 +2919,34 @@ gtk_range_calc_layout (GtkRange *range,
         /* These are publically exported */
         range->slider_start = layout->slider.y;
         range->slider_end = layout->slider.y + layout->slider.height;
+
+        if (gtk_range_get_stream_indicator (range))
+	  {
+            gdouble stream_position;
+	    gint    stream_indicator_padding = 0;
+
+            stream_position = gtk_range_get_stream_position (range);
+
+#if 0
+	    gtk_widget_style_get (widget,
+	                          "stream-indicator-padding", &stream_indicator_padding,
+				  NULL);
+#endif
+
+            if (range->adjustment->upper - range->adjustment->lower != 0)
+              layout->stream_pixel_position =
+                (bottom - top - 1 - 2 * stream_indicator_padding) *
+                ((stream_position - range->adjustment->lower) /
+                 (range->adjustment->upper - range->adjustment->lower));
+            else
+              layout->stream_pixel_position = 0;
+
+            if (should_invert (range))
+              layout->stream_pixel_position =
+                bottom - top - 1 - layout->stream_pixel_position;
+
+            layout->stream_pixel_position += top + stream_indicator_padding;
+          }
       }
     }
   else
@@ -2827,9 +3096,37 @@ gtk_range_calc_layout (GtkRange *range,
         /* These are publically exported */
         range->slider_start = layout->slider.x;
         range->slider_end = layout->slider.x + layout->slider.width;
+
+        if (gtk_range_get_stream_indicator (range))
+	  {
+            gdouble stream_position;
+	    gint    stream_indicator_padding = 0;
+
+            stream_position = gtk_range_get_stream_position (range);
+
+#if 0
+	    gtk_widget_style_get (widget,
+	                          "stream-indicator-padding", &stream_indicator_padding,
+				  NULL);
+#endif
+
+            if (range->adjustment->upper - range->adjustment->lower != 0)
+              layout->stream_pixel_position =
+                (right - left - 1 - 2 * stream_indicator_padding) *
+                ((stream_position - range->adjustment->lower) /
+                 (range->adjustment->upper - range->adjustment->lower));
+            else
+              layout->stream_pixel_position = 0;
+
+            if (should_invert (range))
+              layout->stream_pixel_position =
+                right - left - 1 - layout->stream_pixel_position;
+
+            layout->stream_pixel_position += left + stream_indicator_padding;
+          }
       }
     }
-  
+
   gtk_range_update_mouse_location (range);
 
   switch (range->layout->upper_sensitivity)
@@ -2903,6 +3200,9 @@ gtk_range_real_change_value (GtkRange   
 
   value = CLAMP (value, range->adjustment->lower,
                  (range->adjustment->upper - range->adjustment->page_size));
+
+  if (gtk_range_get_stream_indicator (range))
+    value = MIN (value, gtk_range_get_stream_position (range));
 
   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	3 Aug 2006 15:22:22 -0000
@@ -160,6 +160,13 @@ void               gtk_range_set_value  
                                                             gdouble        value);
 gdouble            gtk_range_get_value                     (GtkRange      *range);
 
+void               gtk_range_set_stream_indicator          (GtkRange      *range,
+                                                            gboolean       stream_indicator);
+gboolean           gtk_range_get_stream_indicator          (GtkRange      *range);
+void               gtk_range_set_stream_position           (GtkRange      *range,
+                                                            gdouble        position);
+gdouble            gtk_range_get_stream_position           (GtkRange      *range);
+
 gdouble	          _gtk_range_get_wheel_delta               (GtkRange      *range,
                                                             GdkScrollDirection direction);
 
