+2009-03-05 Alejandro G. Castro <alex@igalia.com>
+
+ Added a new example application that allows tuning the pannable
+ area and replaced defines with properties in order to simplify the
+ tuning: PROP_DRAG_INERTIA, PROP_PANNING_THRESHOLD,
+ PROP_SCROLLBAR_FADE_DELAY, PROP_BOUNCE_STEPS, PROP_FORCE and
+ PROP_DIRECTION_ERROR_MARGIN.
+
+ * examples/hildon-pannable-area-tuning-example.c: New example
+ application.
+ * src/hildon-pannable-area.c,
+ (hildon_pannable_area_class_init),
+ (hildon_pannable_area_init),
+ (hildon_pannable_area_get_property),
+ (hildon_pannable_area_set_property),
+ (hildon_pannable_area_launch_fade_timeout),
+ (hildon_pannable_area_adjust_value_changed),
+ (hildon_pannable_axis_scroll),
+ (hildon_pannable_area_motion_notify_cb),
+ (hildon_pannable_area_scroll_cb),
+ (hildon_pannable_area_button_release_cb): We have converted some
+ of the defines that control the widget to properties to simplify
+ the tuning.
+
2009-03-05 Alberto Garcia <agarcia@igalia.com>
* src/hildon-app-menu.c (hildon_app_menu_map)
hildon-edit-toolbar-example \
hildon-wizard-dialog-example \
hildon-pannable-area-tree-view-example \
+ hildon-pannable-area-tuning-example \
hildon-pannable-area-scroll-jump-example \
hildon-pannable-area-buttons-scroll-example \
hildon-pannable-area-gesture-signals-example \
$(EXTRA_CFLAGS)
hildon_pannable_area_tree_view_example_SOURCES = hildon-pannable-area-tree-view-example.c
+# Hildon pannable area tuning example
+hildon_pannable_area_tuning_example_LDADD = $(HILDON_OBJ_LIBS)
+hildon_pannable_area_tuning_example_CFLAGS = $(HILDON_OBJ_CFLAGS) \
+ $(EXTRA_CFLAGS)
+hildon_pannable_area_tuning_example_SOURCES = hildon-pannable-area-tuning-example.c
+
# Hildon pannable area scroll jump example
hildon_pannable_area_scroll_jump_example_LDADD = $(HILDON_OBJ_LIBS)
hildon_pannable_area_scroll_jump_example_CFLAGS = $(HILDON_OBJ_CFLAGS)
--- /dev/null
+/*
+ * This file is a part of hildon examples
+ *
+ * Copyright (C) 2009 Nokia Corporation, all rights reserved.
+ * Copyright (C) 2006 The Free Software Foundation
+ *
+ * Author: Claudio Saavedra <csaavedra@alumnos.utalca.cl>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+/* This example is based on other example written by Claudio for
+ EOG */
+
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+#include "hildon.h"
+
+typedef struct {
+ GtkWidget *pannable;
+ GtkWidget *treeview;
+} ApplicationContext;
+
+enum {
+ PIXBUF_COLUMN,
+ TEXT_COLUMN,
+ N_COLUMNS};
+
+enum {
+ COLUMN_PROP_NAME = 0,
+ COLUMN_PROP_VALUE,
+ COLUMN_PROP_TYPE,
+ N_COLS
+};
+
+static GtkListStore *
+create_list_store (void)
+{
+ GtkListStore *store;
+
+ store = gtk_list_store_new (N_COLS,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_GTYPE);
+
+ return store;
+}
+
+static void
+list_store_fill (GtkListStore *store,
+ GObject *object)
+{
+ guint n_properties, i;
+ GParamSpec **param_specs;
+ GtkTreeIter iter;
+ GObjectClass *objectclass;
+ gdouble f_value;
+ gint i_value;
+ gchar *s_value = NULL;
+
+ objectclass = G_OBJECT_GET_CLASS (object);
+ param_specs = g_object_class_list_properties (objectclass,
+ &n_properties);
+
+ for (i = 0; i < n_properties; i++) {
+ if (param_specs [i]->owner_type == G_TYPE_FROM_CLASS (objectclass)) {
+ switch (param_specs[i]->value_type) {
+ case G_TYPE_DOUBLE:
+ g_object_get (object,
+ param_specs[i]->name, &f_value, NULL);
+ s_value = g_strdup_printf ("%f", f_value);
+ break;
+ case G_TYPE_OBJECT:
+ break;
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_ENUM:
+ case G_TYPE_UINT:
+ case G_TYPE_INT:
+ g_object_get (object,
+ param_specs[i]->name, &i_value, NULL);
+ s_value = g_strdup_printf ("%d", i_value);
+ break;
+ }
+
+ if (s_value) {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COLUMN_PROP_NAME, param_specs[i]->name,
+ COLUMN_PROP_VALUE, s_value,
+ COLUMN_PROP_TYPE, param_specs[i]->value_type,
+ -1);
+
+ g_free (s_value);
+ s_value = NULL;
+ }
+ }
+ }
+
+ g_free (param_specs);
+}
+
+static void
+cell_edited_cb (GtkCellRendererText *renderer,
+ gchar *path_string,
+ gchar *s_value,
+ gpointer user_data)
+{
+ ApplicationContext *app_ctx;
+ GObjectClass *objectclass;
+ GParamSpec **param_specs;
+ gint column;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ gdouble f_value;
+ gint i_value;
+ gchar *p_name;
+ GtkTreeIter iter;
+ guint n_properties, i = 0;
+
+ app_ctx = (ApplicationContext *)user_data;
+
+ objectclass = G_OBJECT_GET_CLASS (app_ctx->pannable);
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (app_ctx->treeview));
+ path = gtk_tree_path_new_from_string (path_string);
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (model, &iter,
+ COLUMN_PROP_NAME, &p_name,
+ -1);
+
+ param_specs = g_object_class_list_properties (objectclass,
+ &n_properties);
+
+ column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer),
+ "column"));
+
+ while (strcmp (param_specs[i]->name, p_name)) i++;
+
+ switch (param_specs[i]->value_type) {
+ case G_TYPE_DOUBLE:
+ f_value = g_ascii_strtod (s_value, NULL);
+ g_object_set (G_OBJECT (app_ctx->pannable),
+ p_name, f_value, NULL);
+ break;
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_ENUM:
+ case G_TYPE_UINT:
+ case G_TYPE_INT:
+ i_value = atoi (s_value);
+ g_object_set (G_OBJECT (app_ctx->pannable),
+ p_name, i_value, NULL);
+ break;
+ }
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ column, s_value,
+ -1);
+
+ g_free (param_specs);
+
+ g_free (p_name);
+}
+
+static GtkWidget *
+create_attributes_treeview (ApplicationContext *app_ctx)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GtkTreeView *treeview;
+
+ treeview = GTK_TREE_VIEW (gtk_tree_view_new ());
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Property",
+ renderer,
+ "text",
+ COLUMN_PROP_NAME,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id (column, COLUMN_PROP_NAME);
+ gtk_tree_view_append_column (treeview, column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "editable", TRUE, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Value",
+ renderer,
+ "text", COLUMN_PROP_VALUE,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id (column, COLUMN_PROP_VALUE);
+ gtk_tree_view_append_column (treeview, column);
+ g_signal_connect (renderer, "edited",
+ G_CALLBACK (cell_edited_cb), app_ctx);
+ g_object_set_data (G_OBJECT (renderer), "column",
+ GINT_TO_POINTER (COLUMN_PROP_VALUE));
+
+ return GTK_WIDGET (treeview);
+}
+
+static void
+on_notify_cb (GObject *object,
+ GParamSpec *param_spec,
+ gpointer user_data)
+{
+ GtkTreeModel *store;
+ GtkTreeIter iter;
+ gchar *par_name;
+ gfloat f_value;
+ gchar s_value[128];
+
+ store = GTK_TREE_MODEL (user_data);
+
+ gtk_tree_model_get_iter_first (store, &iter);
+
+ do {
+
+ gtk_tree_model_get (store, &iter,
+ COLUMN_PROP_NAME, &par_name,
+ -1);
+ if (strcmp (par_name, param_spec->name) == 0 &&
+ param_spec->value_type == G_TYPE_FLOAT) {
+ g_object_get (object,
+ param_spec->name, &f_value,
+ NULL);
+ g_sprintf (s_value, "%f", f_value);
+ gtk_list_store_set (GTK_LIST_STORE (store), &iter,
+ COLUMN_PROP_VALUE, s_value,
+ -1);
+ }
+
+ g_free (par_name);
+
+ } while (gtk_tree_model_iter_next (store, &iter));
+}
+
+static GtkWidget*
+create_pannable_treeview (void)
+{
+ GtkWidget *tv;
+ GtkTreeViewColumn *col;
+ GtkCellRenderer *renderer;
+ GtkListStore *store;
+ GSList *stocks, *item;
+ gint i;
+
+ /* Create a treeview */
+ tv = gtk_tree_view_new ();
+
+ g_object_set (tv, "fixed-height-mode", TRUE, NULL);
+
+ col = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_title (col, "Title");
+
+ g_object_set (tv, "fixed-height-mode", TRUE, NULL);
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_renderer_set_fixed_size (renderer, 48, 48);
+ gtk_tree_view_column_pack_start (col, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (col, renderer, "stock-id", PIXBUF_COLUMN, NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (col, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (col, renderer, "text", TEXT_COLUMN, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(tv), col);
+
+ /* Add some rows to the treeview */
+ stocks = gtk_stock_list_ids ();
+ item = stocks;
+ store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
+ for (i = 0; i < 100; i++) {
+ GtkTreeIter iter;
+ GtkStockItem stock_item;
+ gchar *stock_id;
+
+ stock_id = (gchar *)item->data;
+ gtk_stock_lookup (stock_id, &stock_item);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, PIXBUF_COLUMN, stock_id, TEXT_COLUMN, stock_item.label, -1);
+
+ item = item->next? item->next : stocks;
+ }
+ gtk_tree_view_set_model (GTK_TREE_VIEW (tv), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ g_slist_foreach (stocks, (GFunc)g_free, NULL);
+ g_slist_free (stocks);
+
+ return tv;
+}
+gint
+main (gint argc, gchar **argv)
+{
+ HildonProgram *program;
+ GtkWidget *window;
+ GtkWidget *pannable;
+ GtkWidget *hbox, *vbox;
+ GtkWidget *treeview, *pannable_treeview;
+ GtkWidget *sw;
+ GtkListStore *store;
+ ApplicationContext *app_ctx = NULL;
+
+ hildon_gtk_init (&argc, &argv);
+
+ program = hildon_program_get_instance ();
+
+ /* Create the main window */
+ window = hildon_window_new ();
+ hildon_program_add_window (program, HILDON_WINDOW (window));
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 5);
+
+ g_signal_connect (G_OBJECT (window), "delete-event",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ pannable = hildon_pannable_area_new ();
+
+ app_ctx = g_new0 (ApplicationContext, 1);
+ app_ctx->pannable = pannable;
+
+ pannable_treeview = create_pannable_treeview();
+
+ gtk_container_add (GTK_CONTAINER (pannable),
+ pannable_treeview);
+
+ treeview = create_attributes_treeview (app_ctx);
+
+ app_ctx->treeview = treeview;
+ store = create_list_store ();
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+ GTK_TREE_MODEL (store));
+
+ list_store_fill (store, G_OBJECT (pannable));
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+ GTK_SHADOW_ETCHED_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+
+ gtk_container_add (GTK_CONTAINER (sw), treeview);
+
+ hbox = gtk_hbox_new (FALSE, 10);
+
+ vbox = gtk_vbox_new (FALSE, 10);
+ gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 10);
+
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 10);
+
+/* vbox = gtk_vbox_new (FALSE, 10); */
+/* gtk_box_pack_start (GTK_BOX (vbox), pannable, TRUE, TRUE, 10); */
+ gtk_box_pack_start (GTK_BOX (hbox), pannable, TRUE, TRUE, 10);
+
+ g_signal_connect_after (pannable, "notify",
+ G_CALLBACK (on_notify_cb), store);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+ gtk_container_add (GTK_CONTAINER (window), hbox);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ g_free (app_ctx);
+
+ return 0;
+}
#define USE_CAIRO_SCROLLBARS 0
-#define SMOOTH_FACTOR 0.85
-#define FORCE 5
-#define BOUNCE_STEPS 6
#define SCROLL_BAR_MIN_SIZE 5
#define RATIO_TOLERANCE 0.000001
-#define SCROLLBAR_FADE_DELAY 30
-#define SCROLL_FADE_TIMEOUT 10
+#define SCROLL_FADE_TIMEOUT 100
#define MOTION_EVENTS_PER_SECOND 25
-#define PANNING_THRESHOLD 3
-#define DIRECTION_ERROR_MARGIN 10
+#define CURSOR_STOPPED_TIMEOUT 125
G_DEFINE_TYPE (HildonPannableArea, hildon_pannable_area, GTK_TYPE_BIN)
gdouble vmax;
gdouble vfast_factor;
gdouble decel;
+ gdouble drag_inertia;
gdouble scroll_time;
gdouble vel_factor;
guint sps;
+ guint panning_threshold;
+ guint scrollbar_fade_delay;
+ guint bounce_steps;
+ guint force;
+ guint direction_error_margin;
gdouble vel_x;
gdouble vel_y;
GdkWindow *child;
PROP_VELOCITY_MAX,
PROP_VELOCITY_FAST_FACTOR,
PROP_DECELERATION,
+ PROP_DRAG_INERTIA,
PROP_SPS,
+ PROP_PANNING_THRESHOLD,
+ PROP_SCROLLBAR_FADE_DELAY,
+ PROP_BOUNCE_STEPS,
+ PROP_FORCE,
+ PROP_DIRECTION_ERROR_MARGIN,
PROP_VSCROLLBAR_POLICY,
PROP_HSCROLLBAR_POLICY,
PROP_VOVERSHOOT_MAX,
gdouble delta,
gdouble dist,
gdouble vmax,
+ gdouble drag_inertia,
+ gdouble force,
guint sps);
static gboolean hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area);
static void hildon_pannable_area_motion_event_scroll (HildonPannableArea *area,
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
+ PROP_DRAG_INERTIA,
+ g_param_spec_double ("drag_inertia",
+ "Inertia of the cursor dragging",
+ "Percentage of the calculated speed in each moment we are are going to use"
+ "to calculate the launch speed, the other part would be the speed"
+ "calculated previously",
+ 0, 1.0, 0.85,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
PROP_SPS,
g_param_spec_uint ("sps",
"Scrolls per second",
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
+ PROP_PANNING_THRESHOLD,
+ g_param_spec_uint ("panning_threshold",
+ "Threshold to consider a motion event an scroll",
+ "Amount of pixels to consider a motion event an scroll, if it is less"
+ "it is a click detected incorrectly by the touch screen.",
+ 0, G_MAXUINT, 3,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_SCROLLBAR_FADE_DELAY,
+ g_param_spec_uint ("scrollbar_fade_delay",
+ "Time before starting to fade the scrollbar",
+ "Time the scrollbar is going to be visible if the widget is not in"
+ "action in miliseconds",
+ 0, G_MAXUINT, 3000,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_BOUNCE_STEPS,
+ g_param_spec_uint ("bounce_steps",
+ "Bounce steps",
+ "Number of steps that is going to be used to bounce when hitting the"
+ "edge, the rubberband effect depends on it",
+ 0, G_MAXUINT, 6,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_FORCE,
+ g_param_spec_uint ("force",
+ "Multiplier of the calculated speed",
+ "Force applied to the movement, multiplies the calculated speed of the"
+ "user movement the cursor in the screen",
+ 0, G_MAXUINT, 5,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_DIRECTION_ERROR_MARGIN,
+ g_param_spec_uint ("direction_error_margin",
+ "Margin in the direction detection",
+ "After detecting the direction of the movement (horizontal or"
+ "vertical), we can add this margin of error to allow the movement in"
+ "the other direction even apparently it is not",
+ 0, G_MAXUINT, 10,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
PROP_VOVERSHOOT_MAX,
g_param_spec_int ("vovershoot_max",
"Vertical overshoot distance",
- "Space we allow the widget to pass over its vertical limits when hitting the edges, set 0 in order to deactivate overshooting.",
+ "Space we allow the widget to pass over its vertical limits when"
+ "hitting the edges, set 0 in order to deactivate overshooting.",
0, G_MAXINT, 150,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
PROP_HOVERSHOOT_MAX,
g_param_spec_int ("hovershoot_max",
"Horizontal overshoot distance",
- "Space we allow the widget to pass over its horizontal limits when hitting the edges, set 0 in order to deactivate overshooting.",
+ "Space we allow the widget to pass over its horizontal limits when"
+ "hitting the edges, set 0 in order to deactivate overshooting.",
0, G_MAXINT, 150,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
PROP_SCROLL_TIME,
g_param_spec_double ("scroll_time",
"Time to scroll to a position",
- "The time to scroll to a position when calling the hildon_pannable_scroll_to function"
- "acceleration scrolling mode.",
+ "The time to scroll to a position when calling the hildon_pannable_scroll_to function",
1.0, 20.0, 10.0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
PROP_LOW_FRICTION_MODE,
g_param_spec_boolean ("low-friction-mode",
"Do not decelerate the initial velocity",
- "Avoid decelerating the panning movement, like no friction, the widget will stop in the edges or if the user clicks.",
+ "Avoid decelerating the panning movement, like no friction, the widget"
+ "will stop in the edges or if the user clicks.",
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
priv->scroll_indicator_timeout = 0;
priv->motion_event_scroll_timeout = 0;
priv->scroll_indicator_event_interrupt = 0;
- priv->scroll_delay_counter = SCROLLBAR_FADE_DELAY;
+ priv->scroll_delay_counter = priv->scrollbar_fade_delay;
priv->scroll_to_x = -1;
priv->scroll_to_y = -1;
priv->first_drag = TRUE;
case PROP_DECELERATION:
g_value_set_double (value, priv->decel);
break;
+ case PROP_DRAG_INERTIA:
+ g_value_set_double (value, priv->drag_inertia);
+ break;
case PROP_SPS:
g_value_set_uint (value, priv->sps);
break;
+ case PROP_PANNING_THRESHOLD:
+ g_value_set_uint (value, priv->panning_threshold);
+ break;
+ case PROP_SCROLLBAR_FADE_DELAY:
+ /* convert to miliseconds */
+ g_value_set_uint (value, priv->scrollbar_fade_delay * SCROLL_FADE_TIMEOUT);
+ break;
+ case PROP_BOUNCE_STEPS:
+ g_value_set_uint (value, priv->bounce_steps);
+ break;
+ case PROP_FORCE:
+ g_value_set_uint (value, priv->force);
+ break;
+ case PROP_DIRECTION_ERROR_MARGIN:
+ g_value_set_uint (value, priv->direction_error_margin);
+ break;
case PROP_VSCROLLBAR_POLICY:
g_value_set_enum (value, priv->vscrollbar_policy);
break;
priv->decel = g_value_get_double (value);
break;
+ case PROP_DRAG_INERTIA:
+ priv->drag_inertia = g_value_get_double (value);
+ break;
case PROP_SPS:
priv->sps = g_value_get_uint (value);
break;
+ case PROP_PANNING_THRESHOLD:
+ priv->panning_threshold = g_value_get_uint (value);
+ break;
+ case PROP_SCROLLBAR_FADE_DELAY:
+ /* convert to miliseconds */
+ priv->scrollbar_fade_delay = g_value_get_uint (value)/(SCROLL_FADE_TIMEOUT);
+ break;
+ case PROP_BOUNCE_STEPS:
+ priv->bounce_steps = g_value_get_uint (value);
+ break;
+ case PROP_FORCE:
+ priv->force = g_value_get_uint (value);
+ break;
+ case PROP_DIRECTION_ERROR_MARGIN:
+ priv->direction_error_margin = g_value_get_uint (value);
+ break;
case PROP_VSCROLLBAR_POLICY:
priv->vscrollbar_policy = g_value_get_enum (value);
priv->scroll_indicator_event_interrupt = 0;
if ((!priv->scroll_indicator_timeout)&&(priv->scroll_indicator_alpha)>0.1) {
- priv->scroll_delay_counter = SCROLLBAR_FADE_DELAY;
+ priv->scroll_delay_counter = priv->scrollbar_fade_delay;
hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget),
priv->scroll_indicator_alpha);
if (!priv->scroll_indicator_timeout)
priv->scroll_indicator_timeout =
- gdk_threads_add_timeout ((gint) (1000.0 / (gdouble) SCROLL_FADE_TIMEOUT),
+ gdk_threads_add_timeout (SCROLL_FADE_TIMEOUT,
(GSourceFunc) hildon_pannable_area_scroll_indicator_fade,
area);
}
if ((priv->vscroll_visible) || (priv->hscroll_visible)) {
priv->scroll_indicator_event_interrupt = 0;
- priv->scroll_delay_counter = SCROLLBAR_FADE_DELAY;
+ priv->scroll_delay_counter = priv->scrollbar_fade_delay;
hildon_pannable_area_launch_fade_timeout (area, 1.0);
}
} else {
if (!priv->clicked) {
- /* When the overshoot has started we continue for BOUNCE_STEPS more steps into the overshoot
- * before we reverse direction. The deceleration factor is calculated based on
- * the percentage distance from the first item with each iteration, therefore always
- * returning us to the top/bottom most element
+ /* When the overshoot has started we continue for
+ * PROP_BOUNCE_STEPS more steps into the overshoot before we
+ * reverse direction. The deceleration factor is calculated
+ * based on the percentage distance from the first item with
+ * each iteration, therefore always returning us to the
+ * top/bottom most element
*/
if (*overshot_dist > 0) {
- if ((*overshooting < BOUNCE_STEPS) && (*vel > 0)) {
+ if ((*overshooting < priv->bounce_steps) && (*vel > 0)) {
(*overshooting)++;
*vel = (((gdouble)*overshot_dist)/overshoot_max) * (*vel);
- } else if ((*overshooting >= BOUNCE_STEPS) && (*vel > 0)) {
+ } else if ((*overshooting >= priv->bounce_steps) && (*vel > 0)) {
*vel *= -1;
(*overshooting)--;
} else if ((*overshooting > 1) && (*vel < 0)) {
(*overshooting)--;
- /* we add the MAX in order to avoid very small speeds */
+ /* we add the MIN in order to avoid very small speeds */
*vel = MIN ((((gdouble)*overshot_dist)/overshoot_max) * (*vel), -10.0);
}
} else if (*overshot_dist < 0) {
- if ((*overshooting < BOUNCE_STEPS) && (*vel < 0)) {
+ if ((*overshooting < priv->bounce_steps) && (*vel < 0)) {
(*overshooting)++;
*vel = (((gdouble)*overshot_dist)/overshoot_max) * (*vel) * -1;
- } else if ((*overshooting >= BOUNCE_STEPS) && (*vel < 0)) {
+ } else if ((*overshooting >= priv->bounce_steps) && (*vel < 0)) {
*vel *= -1;
(*overshooting)--;
} else if ((*overshooting > 1) && (*vel > 0)) {
(*overshooting)--;
- /* we add the MIN in order to avoid very small speeds */
+ /* we add the MAX in order to avoid very small speeds */
*vel = MAX ((((gdouble)*overshot_dist)/overshoot_max) * (*vel) * -1, 10.0);
}
gdouble delta,
gdouble dist,
gdouble vmax,
+ gdouble drag_inertia,
+ gdouble force,
guint sps)
{
gdouble rawvel;
if (ABS (dist) >= RATIO_TOLERANCE) {
- rawvel = ((dist / ABS (delta)) *
- (gdouble) sps) * FORCE;
- *vel = *vel * (1 - SMOOTH_FACTOR) +
- rawvel * SMOOTH_FACTOR;
+ rawvel = (dist / ABS (delta)) *
+ ((gdouble) sps) * force;
+ *vel = *vel * (1 - drag_inertia) +
+ rawvel * drag_inertia;
*vel = *vel > 0 ? MIN (*vel, vmax)
: MAX (*vel, -1 * vmax);
}
y = event->y - priv->y;
if (priv->first_drag && (!priv->moved) &&
- ((ABS (x) > (PANNING_THRESHOLD))
- || (ABS (y) > (PANNING_THRESHOLD)))) {
+ ((ABS (x) > (priv->panning_threshold))
+ || (ABS (y) > (priv->panning_threshold)))) {
priv->moved = TRUE;
x = 0;
y = 0;
/* even in case we do not have to move we check if this
could be a fake horizontal movement */
if (ABS (priv->iy - event->y) -
- ABS (priv->ix - event->x) >= DIRECTION_ERROR_MARGIN)
+ ABS (priv->ix - event->x) >= priv->direction_error_margin)
priv->moved = FALSE;
}
} else {
/* even in case we do not have to move we check if this
could be a fake vertical movement */
if (ABS (priv->ix - event->x) -
- ABS (priv->iy - event->y) >= DIRECTION_ERROR_MARGIN)
+ ABS (priv->iy - event->y) >= priv->direction_error_margin)
priv->moved = FALSE;
}
}
delta,
dist,
priv->vmax,
+ priv->drag_inertia,
+ priv->force,
priv->sps);
} else {
y = 0;
delta,
dist,
priv->vmax,
+ priv->drag_inertia,
+ priv->force,
priv->sps);
} else {
x = 0;
return TRUE;
priv->scroll_indicator_event_interrupt = 0;
- priv->scroll_delay_counter = SCROLLBAR_FADE_DELAY;
+ priv->scroll_delay_counter = priv->scrollbar_fade_delay;
+
+ if ((priv->last_type == 2)&&
+ (event->time - priv->last_time > CURSOR_STOPPED_TIMEOUT)) {
+ priv->vel_y = 0.0;
+ priv->vel_x = 0.0;
+ }
if ((ABS (priv->vel_y) > 1.0)||
(ABS (priv->vel_x) > 1.0)) {
/* If overshoot has been initiated with a finger down, on release set max speed */
if (priv->overshot_dist_y != 0) {
- priv->overshooting_y = BOUNCE_STEPS; /* Hack to stop a bounce in the finger down case */
+ priv->overshooting_y = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */
priv->vel_y = priv->vmax;
}
if (priv->overshot_dist_x != 0) {
- priv->overshooting_x = BOUNCE_STEPS; /* Hack to stop a bounce in the finger down case */
+ priv->overshooting_x = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */
priv->vel_x = priv->vmax;
}
return TRUE;
priv->scroll_indicator_event_interrupt = 0;
- priv->scroll_delay_counter = SCROLLBAR_FADE_DELAY + 20;
+ priv->scroll_delay_counter = priv->scrollbar_fade_delay + 20;
hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0);