X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hildon%2Fhildon-pannable-area.c;h=83a2b24969658687baf17dfacb521b87d1805b80;hb=363f803d7d98338324e35c9d789e80fa579f775e;hp=bc991067a08dc0870369eab549f4c80c6a2e7ea1;hpb=54746707bd1fa5ba2a29a300e489bbd307e67620;p=hildon diff --git a/hildon/hildon-pannable-area.c b/hildon/hildon-pannable-area.c index bc99106..83a2b24 100644 --- a/hildon/hildon-pannable-area.c +++ b/hildon/hildon-pannable-area.c @@ -141,6 +141,10 @@ struct _HildonPannableAreaPrivate { GtkPolicyType hscrollbar_policy; GdkGC *scrollbars_gc; + GdkColor scroll_color; + + gboolean center_on_child_focus; + gboolean center_on_child_focus_pending; }; /*signals*/ @@ -180,6 +184,7 @@ enum { PROP_SIZE_REQUEST_POLICY, PROP_HADJUSTMENT, PROP_VADJUSTMENT, + PROP_CENTER_ON_CHILD_FOCUS, PROP_LAST }; @@ -291,6 +296,9 @@ static void hildon_pannable_area_child_mapped (GtkWidget *widget, static void hildon_pannable_area_add (GtkContainer *container, GtkWidget *child); static void hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child); static void hildon_pannable_calculate_vel_factor (HildonPannableArea * self); +static void hildon_pannable_area_set_focus_child (GtkContainer *container, + GtkWidget *child); +static void hildon_pannable_area_center_on_child_focus (HildonPannableArea *area); static void @@ -323,6 +331,7 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) container_class->add = hildon_pannable_area_add; container_class->remove = hildon_pannable_area_remove; + container_class->set_focus_child = hildon_pannable_area_set_focus_child; klass->horizontal_movement = NULL; klass->vertical_movement = NULL; @@ -392,7 +401,7 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) "Maximum scroll velocity", "Maximum distance the child widget should scroll " "per 'frame', in pixels per frame.", - 0, G_MAXDOUBLE, 500, + 0, G_MAXDOUBLE, 2000, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); @@ -402,7 +411,7 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) "Maximum scroll velocity when overshooting", "Maximum distance the child widget should scroll " "per 'frame', in pixels per frame when it overshoots after hitting the edge.", - 0, G_MAXDOUBLE, 20, + 0, G_MAXDOUBLE, 130, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); @@ -571,6 +580,16 @@ hildon_pannable_area_class_init (HildonPannableAreaClass * klass) GTK_TYPE_ADJUSTMENT, G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_CENTER_ON_CHILD_FOCUS, + g_param_spec_boolean ("center-on-child-focus", + "Center on the child with the focus", + "Whether to center the pannable on the child that receives the focus.", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + gtk_widget_class_install_style_property (widget_class, g_param_spec_uint ("indicator-width", @@ -717,6 +736,10 @@ hildon_pannable_area_init (HildonPannableArea * area) priv->last_in = TRUE; priv->x_offset = 0; priv->y_offset = 0; + priv->center_on_child_focus_pending = FALSE; + + gtk_style_lookup_color (GTK_WIDGET (area)->style, + "SecondaryTextColor", &priv->scroll_color); priv->hadjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); @@ -827,6 +850,9 @@ hildon_pannable_area_get_property (GObject * object, hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (object))); break; + case PROP_CENTER_ON_CHILD_FOCUS: + g_value_set_boolean (value, priv->center_on_child_focus); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -942,6 +968,9 @@ hildon_pannable_area_set_property (GObject * object, hildon_pannable_area_set_size_request_policy (HILDON_PANNABLE_AREA (object), g_value_get_enum (value)); break; + case PROP_CENTER_ON_CHILD_FOCUS: + priv->center_on_child_focus = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -1194,6 +1223,8 @@ hildon_pannable_area_size_allocate (GtkWidget * widget, if (child && GTK_WIDGET_VISIBLE (child)) { + hildon_pannable_area_check_scrollbars (HILDON_PANNABLE_AREA (widget)); + hildon_pannable_area_child_allocate_calculate (widget, allocation, &child_allocation); @@ -1241,6 +1272,7 @@ hildon_pannable_area_style_set (GtkWidget * widget, GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)-> style_set (widget, previous_style); + gtk_style_lookup_color (widget->style, "SecondaryTextColor", &priv->scroll_color); gtk_widget_style_get (widget, "indicator-width", &priv->indicator_width, NULL); } @@ -1486,7 +1518,7 @@ hildon_pannable_draw_vscroll (GtkWidget *widget, height); if (priv->scroll_indicator_alpha == 1.0) { - gtk_style_lookup_color (widget->style, "SecondaryTextColor", &transp_color); + transp_color = priv->scroll_color; } else if (priv->scroll_indicator_alpha < 1.0) { tranparency_color (&transp_color, *back_color, *scroll_color, priv->scroll_indicator_alpha); @@ -1532,7 +1564,7 @@ hildon_pannable_draw_hscroll (GtkWidget *widget, width); if (priv->scroll_indicator_alpha == 1.0) { - gtk_style_lookup_color (widget->style, "SecondaryTextColor", &transp_color); + transp_color = priv->scroll_color; } else if (priv->scroll_indicator_alpha < 1.0) { tranparency_color (&transp_color, *back_color, *scroll_color, priv->scroll_indicator_alpha); @@ -1693,8 +1725,7 @@ hildon_pannable_area_expose_event (GtkWidget * widget, GdkColor scroll_color = widget->style->base[GTK_STATE_SELECTED]; #else /* USE_CAIRO_SCROLLBARS */ GdkColor back_color = widget->style->bg[GTK_STATE_NORMAL]; - GdkColor scroll_color; - gtk_style_lookup_color (widget->style, "SecondaryTextColor", &scroll_color); + GdkColor scroll_color = priv->scroll_color; #endif if (G_UNLIKELY (priv->initial_effect)) { @@ -1950,6 +1981,8 @@ hildon_pannable_area_button_press_cb (GtkWidget * widget, (gpointer) & priv->child); event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event); + /* remove the reference we added with the copy */ + g_object_unref (priv->event_window); event->x = x; event->y = y; priv->cx = x; @@ -2136,7 +2169,7 @@ hildon_pannable_axis_scroll (HildonPannableArea *area, *vel *= -1; } else if ((*overshooting > 1) && (*vel < 0)) { /* we add the MIN in order to avoid very small speeds */ - *vel = MIN ((((gdouble)*overshot_dist)*0.4) * -1, -2.0); + *vel = MIN (((((gdouble)*overshot_dist)*0.8) * -1), -10.0); } *overshot_dist = CLAMP (*overshot_dist + *vel, 0, overshoot_max); @@ -2152,7 +2185,7 @@ hildon_pannable_axis_scroll (HildonPannableArea *area, *vel *= -1; } else if ((*overshooting > 1) && (*vel > 0)) { /* we add the MAX in order to avoid very small speeds */ - *vel = MAX ((((gdouble)*overshot_dist)*0.4) * -1, 2.0); + *vel = MAX (((((gdouble)*overshot_dist)*0.8) * -1), 10.0); } *overshot_dist = CLAMP (*overshot_dist + (*vel), -overshoot_max, 0); @@ -2304,6 +2337,8 @@ hildon_pannable_area_timeout (HildonPannableArea * area) hildon_pannable_area_scroll (area, priv->vel_x, priv->vel_y); + gdk_window_process_updates (GTK_WIDGET (area)->window, FALSE); + return TRUE; } @@ -2607,6 +2642,8 @@ hildon_pannable_area_motion_notify_cb (GtkWidget * widget, if (priv->child) { /* Send motion notify to child */ event = (GdkEventMotion *) gdk_event_copy ((GdkEvent *) event); + /* remove the reference we added with the copy */ + g_object_unref (priv->event_window); event->x = priv->cx + (event->x - priv->ix); event->y = priv->cy + (event->y - priv->iy); event->window = g_object_ref (priv->child); @@ -2684,12 +2721,12 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget, /* If overshoot has been initiated with a finger down, on release set max speed */ if (priv->overshot_dist_y != 0) { priv->overshooting_y = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */ - priv->vel_y = priv->vmax_overshooting; + priv->vel_y = priv->overshot_dist_y * 0.9; } if (priv->overshot_dist_x != 0) { priv->overshooting_x = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */ - priv->vel_x = priv->vmax_overshooting; + priv->vel_x = priv->overshot_dist_x * 0.9; } priv->button_pressed = FALSE; @@ -2719,10 +2756,16 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget, (GSourceFunc) hildon_pannable_area_timeout, widget); } else { + if (priv->center_on_child_focus_pending) { + hildon_pannable_area_center_on_child_focus (area); + } + if (priv->moved) g_signal_emit (widget, pannable_area_signals[PANNING_FINISHED], 0); } + area->priv->center_on_child_focus_pending = FALSE; + priv->scroll_indicator_event_interrupt = 0; priv->scroll_delay_counter = priv->scrollbar_fade_delay; @@ -2742,6 +2785,8 @@ hildon_pannable_area_button_release_cb (GtkWidget * widget, event->x, event->y, &x, &y, GDK_BUTTON_RELEASE_MASK); event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event); + /* remove the reference we added with the copy */ + g_object_unref (priv->event_window); event->x = x; event->y = y; @@ -2868,6 +2913,39 @@ hildon_pannable_area_add (GtkContainer *container, GtkWidget *child) } } +/* call this function if you are not panning */ +static void +hildon_pannable_area_center_on_child_focus (HildonPannableArea *area) +{ + GtkWidget *focused_child = NULL; + GtkWidget *window = NULL; + + window = gtk_widget_get_toplevel (GTK_WIDGET (area)); + + if (GTK_WIDGET_TOPLEVEL (window)) { + focused_child = gtk_window_get_focus (GTK_WINDOW (window)); + } + + if (focused_child) { + hildon_pannable_area_scroll_to_child (area, focused_child); + } +} + +static void +hildon_pannable_area_set_focus_child (GtkContainer *container, + GtkWidget *child) +{ + HildonPannableArea *area = HILDON_PANNABLE_AREA (container); + + if (!area->priv->center_on_child_focus) { + return; + } + + if (GTK_IS_WIDGET (child)) { + area->priv->center_on_child_focus_pending = TRUE; + } +} + static void hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child) { @@ -3454,3 +3532,44 @@ hildon_pannable_area_set_size_request_policy (HildonPannableArea *area, g_object_notify (G_OBJECT (area), "size-request-policy"); } +/** + * hildon_pannable_area_get_center_on_child_focus + * @area: A #HildonPannableArea + * + * Gets the @area #HildonPannableArea:center-on-child-focus property + * value. + * + * See #HildonPannableArea:center-on-child-focus for more information. + * + * Returns: the @area #HildonPannableArea:center-on-child-focus value + * + * Since: 2.2 + **/ +gboolean +hildon_pannable_area_get_center_on_child_focus (HildonPannableArea *area) +{ + g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), FALSE); + + return area->priv->center_on_child_focus; +} + +/** + * hildon_pannable_area_set_center_on_child_focus + * @area: A #HildonPannableArea + * @value: the new value + * + * Sets the @area #HildonPannableArea:center-on-child-focus property + * to @value. + * + * See #HildonPannableArea:center-on-child-focus for more information. + * + * Since: 2.2 + **/ +void +hildon_pannable_area_set_center_on_child_focus (HildonPannableArea *area, + gboolean value) +{ + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + + area->priv->center_on_child_focus = value; +}