--- gtk+-2.6.4/gtk/gtkrange.c 2004-11-10 05:20:11.000000000 +0200 +++ gtk+-2.6.4/gtk/gtkrange.c 2005-04-06 16:19:37.788793592 +0300 @@ -25,6 +25,10 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +/* Modified for Nokia Oyj during 2002-2005. See CHANGES file for list + * of changes. + */ + #include #include #include @@ -44,7 +48,10 @@ PROP_0, PROP_UPDATE_POLICY, PROP_ADJUSTMENT, - PROP_INVERTED + PROP_INVERTED, + PROP_STREAM_INDICATOR, + PROP_MINIMUM_VISIBLE_BARS, + PROP_STREAM_POSITION }; enum { @@ -88,8 +95,20 @@ /* "grabbed" mouse location, OUTSIDE for no grab */ MouseLocation grab_location; gint grab_button; /* 0 if none */ + + /* OSSO hack: stream trough split position */ + gint stream_pixel_position; + gint minimum_visible_bars; }; +#define OSSO_GTK_RANGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_RANGE, OssoGtkRangePrivate)) +typedef struct _OssoGtkRangePrivate OssoGtkRangePrivate; + +struct _OssoGtkRangePrivate +{ + gboolean stream_indicator; + gdouble stream_position; +}; static void gtk_range_class_init (GtkRangeClass *klass); static void gtk_range_init (GtkRange *range); @@ -135,6 +154,7 @@ gint mouse_x, gint mouse_y); +static gint osso_gtk_range_focus_out (GtkWidget *widget, GdkEventFocus *event); /* Range methods */ @@ -247,6 +267,9 @@ widget_class->state_changed = gtk_range_state_changed; widget_class->style_set = gtk_range_style_set; + /* OSSO addition (see bug #1653) */ + widget_class->focus_out_event = osso_gtk_range_focus_out; + class->move_slider = gtk_range_move_slider; class->change_value = gtk_range_real_change_value; @@ -344,6 +367,34 @@ FALSE, G_PARAM_READWRITE)); + 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, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, + PROP_MINIMUM_VISIBLE_BARS, + g_param_spec_int ("minimum_visible_bars", + P_("Minimum visible bars"), + P_("The minimum number of visible bars in a HildonControlBar"), + 0, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + 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, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("slider_width", P_("Slider Width"), @@ -392,6 +443,52 @@ G_MAXINT, 0, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("hildonlike", + _("hildonlike"), + _("Change focus out behaviour, 1/0"), + FALSE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("two_part_trough", + _("Two-part trough"), + _("Allow different trough graphics on different sides of the slider, 1/0"), + FALSE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("stream_indicator_padding", + P_("Stream Indicator Padding"), + P_("How many pixels smallerthan the trough the stream indicator is drawn from both ends ."), + 0, + G_MAXINT, + 1, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("autodimmed_steppers", + _("Autodimmed steppers"), + _("Automatically dim steppers when maximum or minimum value has been reached"), + FALSE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("arrow_paint_box_layout", + _("Arrow paint box layout"), + _("Allows to use images instead of normal arrows."), + FALSE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean ("draw_trough_under_steppers", + _("Draw trough under steppers"), + _("Whether to draw trought for full length of range or exclude the steppers and spacing"), + TRUE, + G_PARAM_READABLE)); + + g_type_class_add_private (gobject_class, sizeof (OssoGtkRangePrivate)); } static void @@ -415,6 +512,15 @@ case PROP_INVERTED: gtk_range_set_inverted (range, g_value_get_boolean (value)); break; + case PROP_STREAM_INDICATOR: + osso_gtk_range_set_stream_indicator (range, g_value_get_boolean (value)); + break; + case PROP_STREAM_POSITION: + osso_gtk_range_set_stream_position (range, g_value_get_double (value)); + break; + case PROP_MINIMUM_VISIBLE_BARS: + range->layout->minimum_visible_bars = g_value_get_int(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -442,6 +548,15 @@ case PROP_INVERTED: g_value_set_boolean (value, range->inverted); break; + case PROP_STREAM_INDICATOR: + g_value_set_boolean (value, osso_gtk_range_get_stream_indicator (range)); + break; + case PROP_STREAM_POSITION: + g_value_set_double (value, osso_gtk_range_get_stream_indicator (range)); + break; + case PROP_MINIMUM_VISIBLE_BARS: + g_value_set_int (value, range->layout->minimum_visible_bars); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -451,6 +566,7 @@ static void gtk_range_init (GtkRange *range) { + OssoGtkRangePrivate *priv = OSSO_GTK_RANGE_GET_PRIVATE (range); GTK_WIDGET_SET_FLAGS (range, GTK_NO_WINDOW); range->adjustment = NULL; @@ -471,6 +587,9 @@ range->layout->grab_location = MOUSE_OUTSIDE; range->layout->grab_button = 0; range->timer = NULL; + + priv->stream_indicator = FALSE; + priv->stream_position = 0.0; } /** @@ -584,7 +703,10 @@ g_signal_connect (adjustment, "changed", G_CALLBACK (gtk_range_adjustment_changed), range); - g_signal_connect (adjustment, "value_changed", + /* OSSO modification : Changed for controlbar. + * There we intercept this signal and put forth + * our own, with modified parameters. */ + g_signal_connect_after (adjustment, "value_changed", G_CALLBACK (gtk_range_adjustment_value_changed), range); @@ -677,16 +799,21 @@ gdouble max) { gdouble value; + OssoGtkRangePrivate *priv; g_return_if_fail (GTK_IS_RANGE (range)); g_return_if_fail (min < max); + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + range->adjustment->lower = min; range->adjustment->upper = max; value = CLAMP (range->adjustment->value, range->adjustment->lower, (range->adjustment->upper - range->adjustment->page_size)); + if (priv->stream_indicator && value > priv->stream_position) + value = (gdouble)priv->stream_position; gtk_adjustment_set_value (range->adjustment, value); gtk_adjustment_changed (range->adjustment); @@ -707,10 +834,16 @@ gtk_range_set_value (GtkRange *range, gdouble value) { + OssoGtkRangePrivate *priv; + g_return_if_fail (GTK_IS_RANGE (range)); + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + value = CLAMP (value, range->adjustment->lower, (range->adjustment->upper - range->adjustment->page_size)); + if (priv->stream_indicator && value > priv->stream_position) + value = (gdouble)priv->stream_position; gtk_adjustment_set_value (range->adjustment, value); } @@ -913,6 +1046,10 @@ gint arrow_width; gint arrow_height; + /* OSSO modification: state of our style properties */ + gboolean autodimmed_steppers = FALSE; + gboolean arrow_paint_box_layout = FALSE; + /* More to get the right clip region than for efficiency */ if (!gdk_rectangle_intersect (area, rect, &intersection)) return; @@ -929,6 +1066,37 @@ else state_type = GTK_STATE_NORMAL; + /* OSSO modification : read all of our style properties needed in this func */ + gtk_widget_style_get (widget, + "autodimmed_steppers", &autodimmed_steppers, + "arrow_paint_box_layout", &arrow_paint_box_layout, + NULL); + + /* OSSO modification : dim the stepper if maximum or minimum value has been reached */ + if (autodimmed_steppers) + { + OssoGtkRangePrivate *priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + if (((!range->inverted && (arrow_type == GTK_ARROW_DOWN || + arrow_type == GTK_ARROW_RIGHT)) || + (range->inverted && (arrow_type == GTK_ARROW_UP || + arrow_type == GTK_ARROW_LEFT))) && + range->adjustment->value >= + (priv->stream_indicator + ? priv->stream_position + : range->adjustment->upper - range->adjustment->page_size)) + { + state_type = GTK_STATE_INSENSITIVE; + } + else if (((!range->inverted && (arrow_type == GTK_ARROW_UP || + arrow_type == GTK_ARROW_LEFT)) || + (range->inverted && (arrow_type == GTK_ARROW_DOWN || + arrow_type == GTK_ARROW_RIGHT))) && + range->adjustment->value <= range->adjustment->lower) + { + state_type = GTK_STATE_INSENSITIVE; + } + } + if (clicked) shadow_type = GTK_SHADOW_IN; else @@ -944,10 +1112,20 @@ rect->width, rect->height); - arrow_width = rect->width / 2; - arrow_height = rect->height / 2; - arrow_x = widget->allocation.x + rect->x + (rect->width - arrow_width) / 2; - arrow_y = widget->allocation.y + rect->y + (rect->height - arrow_height) / 2; + if (arrow_paint_box_layout) + { + arrow_width = rect->width; + arrow_height = rect->height; + arrow_x = widget->allocation.x + rect->x; + arrow_y = widget->allocation.y + rect->y; + } + else + { + arrow_width = rect->width / 2; + arrow_height = rect->height / 2; + arrow_x = widget->allocation.x + rect->x + (rect->width - arrow_width) / 2; + arrow_y = widget->allocation.y + rect->y + (rect->height - arrow_height) / 2; + } if (clicked) { @@ -982,8 +1160,11 @@ GdkRectangle area; gint focus_line_width = 0; gint focus_padding = 0; + OssoGtkRangePrivate *priv; range = GTK_RANGE (widget); + + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); if (GTK_WIDGET_CAN_FOCUS (range)) { @@ -1011,18 +1192,118 @@ if (gdk_rectangle_intersect (&expose_area, &range->range_rect, &area)) { + gint x = widget->allocation.x + range->range_rect.x + focus_line_width + focus_padding; + gint y = widget->allocation.y + range->range_rect.y + focus_line_width + focus_padding; + gint width = range->range_rect.width - 2 * (focus_line_width + focus_padding); + gint height = range->range_rect.height - 2 * (focus_line_width + focus_padding); + gint *virtual_position, *virtual_size; + gboolean two_part_trough = 0; + gint stepper_size = 0; + gint stepper_spacing = 0; + gboolean draw_trough_under_steppers = TRUE; + area.x += widget->allocation.x; area.y += widget->allocation.y; + + gtk_widget_style_get (GTK_WIDGET (range), + "two_part_trough", &two_part_trough, + "stepper_size", &stepper_size, + "stepper_spacing", &stepper_spacing, + "draw_trough_under_steppers", &draw_trough_under_steppers, + NULL); + + if (range->orientation == GTK_ORIENTATION_HORIZONTAL) + { + virtual_position = &x; + virtual_size = &width; + } + else + { + virtual_position = &y; + virtual_size = &height; + } + + if (draw_trough_under_steppers == FALSE) + { + *virtual_position += stepper_size + stepper_spacing; + *virtual_size -= 2 * (stepper_size + stepper_spacing); + } - gtk_paint_box (widget->style, - widget->window, - sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, - GTK_SHADOW_IN, - &area, GTK_WIDGET(range), "trough", - widget->allocation.x + range->range_rect.x + focus_line_width + focus_padding, - widget->allocation.y + range->range_rect.y + focus_line_width + focus_padding, - range->range_rect.width - 2 * (focus_line_width + focus_padding), - range->range_rect.height - 2 * (focus_line_width + focus_padding)); + if (two_part_trough == FALSE) + { + gtk_paint_box (widget->style, + widget->window, + sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, + GTK_SHADOW_IN, + &area, GTK_WIDGET(range), "trough", + x, y, + width, height); + } + else + { + gint trough_change_pos_x = width; + gint trough_change_pos_y = height; + + if (range->orientation == GTK_ORIENTATION_HORIZONTAL) + trough_change_pos_x = range->layout->slider.x + (range->layout->slider.width / 2) - stepper_size - stepper_spacing; + else + trough_change_pos_y = range->layout->slider.y + (range->layout->slider.height / 2) - stepper_size - stepper_spacing; + + gtk_paint_box (widget->style, + widget->window, + sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, + GTK_SHADOW_IN, + &area, GTK_WIDGET(range), "trough_northwest", + x, y, + trough_change_pos_x, trough_change_pos_y); + + if (range->orientation == GTK_ORIENTATION_HORIZONTAL) + trough_change_pos_y = 0; + else + trough_change_pos_x = 0; + + gtk_paint_box (widget->style, + widget->window, + sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, + GTK_SHADOW_IN, + &area, GTK_WIDGET(range), "trough_southeast", + x + trough_change_pos_x, y + trough_change_pos_y, + width - trough_change_pos_x, height - trough_change_pos_y); + } + + /* Stream indicator drawing does not support inverted state. */ + if (priv->stream_indicator) + { + gchar *used_detail; + gint stream_start_pos_x = 0; + gint stream_start_pos_y = 0; + gint stream_width = width; + gint stream_height = height; + + if (range->orientation == GTK_ORIENTATION_HORIZONTAL) + { + stream_start_pos_x = range->layout->slider.x; + stream_width = range->layout->stream_pixel_position - stream_start_pos_x; + } + else + { + stream_start_pos_y = range->layout->slider.y; + stream_height = range->layout->stream_pixel_position - stream_start_pos_y; + } + + if (priv->stream_position == range->adjustment->upper) + used_detail = "trough_stream_complete"; + else + used_detail = "trough_stream"; + + gtk_paint_box (widget->style, + widget->window, + sensitive ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE, + GTK_SHADOW_IN, + &area, GTK_WIDGET(range), used_detail, + widget->allocation.x + stream_start_pos_x, widget->allocation.y + stream_start_pos_y, + stream_width, stream_height); + } if (sensitive && @@ -1189,19 +1470,41 @@ { gdouble frac; gdouble value; - - if (range->orientation == GTK_ORIENTATION_VERTICAL) + gint stepper_spacing = 0; + gint minimum_visible_blocks = 0; + gint magic_value = 0; + + g_object_get(range, "minimum_visible_bars", &minimum_visible_blocks, NULL); + + g_print("coord = %d\n", coord); + gtk_widget_style_get (GTK_WIDGET (range), + "stepper_spacing", &stepper_spacing, + NULL); + + if (range->orientation == GTK_ORIENTATION_VERTICAL) { + if (minimum_visible_blocks > 0) + magic_value = ((range->layout->trough.height -(2*stepper_spacing)) / (range->adjustment->upper - range->adjustment->lower + 1)) * minimum_visible_blocks; if (range->layout->trough.height == range->layout->slider.height) frac = 1.0; else - frac = ((coord - range->layout->trough.y) / - (gdouble) (range->layout->trough.height - range->layout->slider.height)); - else + frac = ((coord - range->layout->trough.y - magic_value - stepper_spacing) / + (gdouble) (range->layout->trough.height - magic_value - range->layout->slider.height - (2 * stepper_spacing))); + } + else { + if (minimum_visible_blocks > 0) + magic_value = ((range->layout->trough.width -(2*stepper_spacing)) / (range->adjustment->upper - range->adjustment->lower + 1)) * minimum_visible_blocks; if (range->layout->trough.width == range->layout->slider.width) frac = 1.0; else - frac = ((coord - range->layout->trough.x) / - (gdouble) (range->layout->trough.width - range->layout->slider.width)); + frac = ((coord - range->layout->trough.x - magic_value - stepper_spacing) / + (gdouble) (range->layout->trough.width - magic_value - range->layout->slider.width - (2 * stepper_spacing))); + } + + if (frac < 0.0) + frac = 0.0; + else + if (frac > 1.0) + frac = 1.0; if (should_invert (range)) frac = 1.0 - frac; @@ -1242,6 +1545,8 @@ range->orientation == GTK_ORIENTATION_VERTICAL ? event->y : event->x); + g_print("button_press: calling coord_to_value with %d, click value = %d\n", event->x, click_value); + range->trough_click_forward = click_value > range->adjustment->value; range_grab_add (range, MOUSE_TROUGH, event->button); @@ -1286,7 +1591,9 @@ * On button 2 press, we warp the slider to mouse position, * then begin the slider drag. */ - if (event->button == 2) + /* OSSO modification : We want this to be + * the default behaviour. */ + if (range->layout->mouse_location == MOUSE_TROUGH) { gdouble slider_low_value, slider_high_value, new_value; @@ -1299,7 +1606,10 @@ range->orientation == GTK_ORIENTATION_VERTICAL ? event->y - range->layout->slider.height : event->x - range->layout->slider.width); - + + g_print("calling coord_to_value with %d\n", event->x); + g_print("calling coord_to_value with %d\n", range->orientation == GTK_ORIENTATION_VERTICAL? event->y-range->layout->slider.height:event->x-range->layout->slider.width); + /* compute new value for warped slider */ new_value = slider_low_value + (slider_high_value - slider_low_value) / 2; @@ -1353,8 +1663,10 @@ else delta = mouse_x - range->slide_initial_coordinate; + delta += -4; c = range->slide_initial_slider_position + delta; + g_print("delta = %d, calling coord_to_value with %d + delta = %d\n", delta, range->slide_initial_slider_position, c); new_value = coord_to_value (range, c); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_JUMP, new_value, @@ -1395,9 +1707,12 @@ if (range->layout->grab_button == event->button) { + /* OSSO modification : Commented out. + * Not sure about the reason unfortunately. */ +/* if (range->layout->grab_location == MOUSE_SLIDER) update_slider_position (range, range->layout->mouse_x, range->layout->mouse_y); - +*/ stop_scrolling (range); return TRUE; @@ -2026,6 +2341,7 @@ GdkRectangle range_rect; GtkRangeLayout *layout; GtkWidget *widget; + gint minimum_visible_bars = 0; if (!range->need_recalc) return; @@ -2047,6 +2363,8 @@ &slider_width, &stepper_size, &trough_border, &stepper_spacing, NULL, NULL); + g_object_get(range, "minimum_visible_bars", &minimum_visible_bars, NULL); + gtk_range_calc_request (range, slider_width, stepper_size, trough_border, stepper_spacing, &range_rect, &border, &n_steppers, &slider_length); @@ -2167,10 +2485,13 @@ /* Compute slider position/length */ { gint y, bottom, top, height; - - top = layout->trough.y + stepper_spacing; - bottom = layout->trough.y + layout->trough.height - stepper_spacing; - + gint magic_value; + + magic_value = (layout->trough.height / (range->adjustment->upper - range->adjustment->lower + 1)); + + top = layout->trough.y + stepper_spacing + (minimum_visible_bars * magic_value); + bottom = layout->trough.y + layout->trough.height - stepper_spacing; + /* slider height is the fraction (page_size / * total_adjustment_range) times the trough height in pixels */ @@ -2307,8 +2628,11 @@ /* Compute slider position/length */ { gint x, left, right, width; + gint magic_value; + + magic_value = (layout->trough.width / (range->adjustment->upper - range->adjustment->lower + 1)); - left = layout->trough.x + stepper_spacing; + left = layout->trough.x + stepper_spacing + (minimum_visible_bars * magic_value); right = layout->trough.x + layout->trough.width - stepper_spacing; /* slider width is the fraction (page_size / @@ -2340,6 +2664,32 @@ layout->slider.x = x; layout->slider.width = width; + + /* Hildon modification : Calculate the x point of streaming + * indicator. + */ + { + gint stream_indicator_padding = 0; + OssoGtkRangePrivate *priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + gtk_widget_style_get (widget, + "stream_indicator_padding", &stream_indicator_padding, + NULL); + + if (priv->stream_indicator == TRUE) + { + if (range->adjustment->upper - range->adjustment->lower != 0) + layout->stream_pixel_position = + (right - left - (2 * stream_indicator_padding)) * + ((priv->stream_position - range->adjustment->lower) / + (range->adjustment->upper - range->adjustment->lower)) + + left + stream_indicator_padding; + else + layout->stream_pixel_position = left + stream_indicator_padding; + + if (layout->stream_pixel_position < left + stream_indicator_padding) + layout->stream_pixel_position = left + stream_indicator_padding; + } + } /* These are publically exported */ range->slider_start = layout->slider.x; @@ -2382,12 +2732,17 @@ GtkScrollType scroll, gdouble value) { + OssoGtkRangePrivate *priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + /* potentially adjust the bounds _before we clamp */ g_signal_emit (range, signals[ADJUST_BOUNDS], 0, value); value = CLAMP (value, range->adjustment->lower, (range->adjustment->upper - range->adjustment->page_size)); + if (priv->stream_indicator && value > priv->stream_position) + value = (gdouble)priv->stream_position; + if (range->round_digits >= 0) { gdouble power; @@ -2465,11 +2820,16 @@ initial_timeout (gpointer data) { GtkRange *range; + GtkSettings *settings; + guint timeout = SCROLL_LATER_DELAY; + + settings = gtk_settings_get_default (); + g_object_get (settings, "gtk-update-timeout", &timeout, NULL); GDK_THREADS_ENTER (); range = GTK_RANGE (data); range->timer->timeout_id = - g_timeout_add (SCROLL_LATER_DELAY, + g_timeout_add (/*SCROLL_LATER_DELAY*/timeout, second_timeout, range); GDK_THREADS_LEAVE (); @@ -2482,13 +2842,19 @@ gtk_range_add_step_timer (GtkRange *range, GtkScrollType step) { + GtkSettings *settings; + guint timeout = SCROLL_INITIAL_DELAY; + g_return_if_fail (range->timer == NULL); g_return_if_fail (step != GTK_SCROLL_NONE); + settings = gtk_settings_get_default (); + g_object_get (settings, "gtk-initial-timeout", &timeout, NULL); + range->timer = g_new (GtkRangeStepTimer, 1); range->timer->timeout_id = - g_timeout_add (SCROLL_INITIAL_DELAY, + g_timeout_add (/*SCROLL_INITIAL_DELAY*/timeout, initial_timeout, range); range->timer->step = step; @@ -2528,9 +2894,15 @@ static void gtk_range_reset_update_timer (GtkRange *range) { + /*GtkSettings *settings; + guint timeout = UPDATE_DELAY; + + settings = gtk_settings_get_default (); + g_object_get (settings, "gtk-update-timeout", &timeout, NULL);*/ + gtk_range_remove_update_timer (range); - range->update_timeout_id = g_timeout_add (UPDATE_DELAY, + range->update_timeout_id = g_timeout_add (/*timeout*/UPDATE_DELAY, update_timeout, range); } @@ -2544,3 +2916,116 @@ range->update_timeout_id = 0; } } + +/** + * osso_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. + **/ +void +osso_gtk_range_set_stream_indicator (GtkRange *range, gboolean stream_indicator) +{ + OssoGtkRangePrivate *priv; + + g_return_if_fail (GTK_IS_RANGE (range)); + + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + + if (stream_indicator == priv->stream_indicator) + return; + + priv->stream_indicator = stream_indicator; + g_signal_emit_by_name (G_OBJECT (range), "value_changed", NULL); +} + +/** + * osso_gtk_range_get_stream_indicator: + * @range: A GtkRange + * + * Return value: Whether GtkRange displays an + * stream indicator graphics and slider is restricted + * to streamed area + **/ +gboolean +osso_gtk_range_get_stream_indicator (GtkRange *range) +{ + OssoGtkRangePrivate *priv; + + g_return_val_if_fail (GTK_IS_RANGE (range), FALSE); + + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + + return priv->stream_indicator; +} + +/** + * osso_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. + **/ +void +osso_gtk_range_set_stream_position (GtkRange *range, + gdouble position) +{ + OssoGtkRangePrivate *priv; + gdouble new_pos; + + g_return_if_fail (GTK_IS_RANGE (range)); + + new_pos = CLAMP (position, + range->adjustment->lower, + range->adjustment->upper); + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + + priv->stream_position = new_pos; + /* Reset the value to clamp it with the stream_position. */ + if (priv->stream_indicator == TRUE) + gtk_range_set_value (range, gtk_range_get_value (range)); + + g_object_notify (G_OBJECT (range), "stream_position"); +} +/** + * osso_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. + **/ +gdouble +osso_gtk_range_get_stream_position (GtkRange *range) +{ + OssoGtkRangePrivate *priv; + + g_return_if_fail (GTK_IS_RANGE (range)); + + priv = OSSO_GTK_RANGE_GET_PRIVATE (range); + + return priv->stream_position; +} + +/* OSSO addition : A function to ensure that + * scrolling stops if widget loses focus (example: + * dialog pops up) */ +static gint +osso_gtk_range_focus_out (GtkWidget *widget, GdkEventFocus *event) +{ + gboolean hildonlike; + + gtk_widget_style_get (widget, "hildonlike", &hildonlike, NULL); + + if (hildonlike) + { + stop_scrolling (GTK_RANGE (widget)); + } + return GTK_WIDGET_CLASS (parent_class)->focus_out_event (widget, event); +}