+static Evas_Coord
+_elm_smart_scroller_x_mirrored_get(Evas_Object *obj, Evas_Coord x)
+{
+ API_ENTRY return x;
+
+ Evas_Coord cw, ch, w, ret;
+ elm_smart_scroller_child_viewport_size_get(obj, &w, NULL);
+ sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+ ret = (cw - (x + w));
+ return (ret >= 0) ? ret : 0;
+}
+
+void
+elm_smart_scroller_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
+{
+ API_ENTRY return;
+ Evas_Coord wx;
+ if (sd->is_mirrored == mirrored)
+ return;
+
+ sd->is_mirrored = mirrored;
+ edje_object_mirrored_set(sd->edje_obj, mirrored);
+
+ if (sd->is_mirrored)
+ wx = _elm_smart_scroller_x_mirrored_get(sd->smart_obj, sd->wx);
+ else
+ wx = sd->wx;
+
+ elm_smart_scroller_child_pos_set(sd->smart_obj, wx, sd->wy);
+}
+
- o = _elm_smart_pan_add(evas_object_evas_get(obj));
- sd->pan_obj = o;
- evas_object_smart_callback_add(o, "changed", _smart_pan_changed_hook, sd);
- evas_object_smart_callback_add(o, "pan_changed", _smart_pan_pan_changed_hook, sd);
- evas_object_show(o);
- edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", o);
+ o = _elm_smart_pan_add(evas_object_evas_get(obj));
+ sd->pan_obj = o;
+ evas_object_smart_callback_add(o, "changed", _smart_pan_changed_hook, sd);
+ evas_object_smart_callback_add(o, "pan_changed", _smart_pan_pan_changed_hook, sd);
+ edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", o);
+Eina_Bool
+elm_smart_scroller_wheel_disabled_get(Evas_Object *obj)
+{
+ API_ENTRY return EINA_FALSE;
+ return sd->wheel_disabled;
+}
+
+void
+elm_smart_scroller_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled)
+{
+ API_ENTRY return;
+ if ((!sd->wheel_disabled) && (disabled))
+ evas_object_event_callback_del_full(sd->event_obj, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
+ else if ((sd->wheel_disabled) && (!disabled))
+ evas_object_event_callback_add(sd->event_obj, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
+ sd->wheel_disabled = disabled;
+}
+
+/* Update the wanted coordinates according to the x, y passed
+ * widget directionality, child size and etc. */
+static void
+_update_wanted_coordinates(Smart_Data *sd, Evas_Coord x, Evas_Coord y)
+{
+ Evas_Coord cw, ch;
+
+ sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+
+ /* Update wx/y/w/h - and if the requested positions aren't legal
+ * adjust a bit. */
+ elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &sd->ww, &sd->wh);
+ if (x < 0)
+ sd->wx = 0;
+ else if ((x + sd->ww) > cw)
+ sd->wx = cw - sd->ww;
+ else if (sd->is_mirrored)
+ sd->wx = _elm_smart_scroller_x_mirrored_get(sd->smart_obj, x);
+ else
+ sd->wx = x;
+ if (y < 0) sd->wy = 0;
+ else if ((y + sd->wh) > ch) sd->wy = ch - sd->wh;
+ else sd->wy = y;
+}
+
sd->pan_func.max_get(sd->pan_obj, &mx, &my);
sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
sd->pan_func.get(sd->pan_obj, &px, &py);
sd->pan_func.max_get(sd->pan_obj, &mx, &my);
sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
sd->pan_func.get(sd->pan_obj, &px, &py);
- sd->pan_func.max_get(sd->pan_obj, &mx, &my);
- sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
- sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
- sd->pan_func.get(sd->pan_obj, &px, &py);
-
- nx = px;
- if ((x < px) && ((x + w) < (px + (cw - mx)))) nx = x;
- else if ((x > px) && ((x + w) > (px + (cw - mx)))) nx = x + w - (cw - mx);
- ny = py;
- if ((y < py) && ((y + h) < (py + (ch - my)))) ny = y;
- else if ((y > py) && ((y + h) > (py + (ch - my)))) ny = y + h - (ch - my);
-// if ((nx == px) && (ny == py)) return;
- if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
- (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
- {
- _smart_anim_stop(sd->smart_obj);
- }
- if (sd->scrollto.x.animator)
+ if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
- if (sd->scrollto.y.animator)
- {
- ecore_animator_del(sd->scrollto.y.animator);
- sd->scrollto.y.animator = NULL;
- }
- if (sd->down.bounce_x_animator)
- {
- ecore_animator_del(sd->down.bounce_x_animator);
- sd->down.bounce_x_animator = NULL;
- sd->bouncemex = 0;
- }
- if (sd->down.bounce_y_animator)
- {
- ecore_animator_del(sd->down.bounce_y_animator);
- sd->down.bounce_y_animator = NULL;
- sd->bouncemey = 0;
- }
- if (sd->down.hold_animator)
- {
- ecore_animator_del(sd->down.hold_animator);
- sd->down.hold_animator = NULL;
- _smart_drag_stop(sd->smart_obj);
- }
- if (sd->down.momentum_animator)
- {
- ecore_animator_del(sd->down.momentum_animator);
- sd->down.momentum_animator = NULL;
- sd->down.bounce_x_hold = 0;
- sd->down.bounce_y_hold = 0;
- sd->down.ax = 0;
- sd->down.ay = 0;
- sd->down.pdx = 0;
- sd->down.pdy = 0;
- }
- x = nx;
- if (x < minx) x = minx;
- else if ((x + w) > cw) x = cw - w;
- y = ny;
- if (y < miny) y = miny;
- else if ((y + h) > ch) y = ch - h;
- _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, nx);
- _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, ny);
- }
- if (ev->button == 1)
- {
- sd->down.now = 1;
- sd->down.dragged = 0;
- sd->down.dir_x = 0;
- sd->down.dir_y = 0;
- sd->down.x = ev->canvas.x;
- sd->down.y = ev->canvas.y;
- elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
- sd->down.sx = x;
- sd->down.sy = y;
- sd->down.locked = 0;
- memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 20);
+ }
+ if (ev->button == 1)
+ {
+ sd->down.hist.est_timestamp_diff =
+ ecore_loop_time_get() - ((double)ev->timestamp / 1000.0);
+ sd->down.hist.tadd = 0.0;
+ sd->down.hist.dxsum = 0.0;
+ sd->down.hist.dysum = 0.0;
+ sd->down.now = 1;
+ sd->down.dragged = 0;
+ sd->down.dir_x = 0;
+ sd->down.dir_y = 0;
+ sd->down.x = ev->canvas.x;
+ sd->down.y = ev->canvas.y;
+ elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+ sd->down.sx = x;
+ sd->down.sy = y;
+ sd->down.locked = 0;
+ memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 60);
+static void
+_down_coord_eval(Smart_Data *sd, Evas_Coord *x, Evas_Coord *y)
+{
+ Evas_Coord minx, miny;
+
+ if (sd->down.dir_x) *x = sd->down.sx - (*x - sd->down.x);
+ else *x = sd->down.sx;
+ if (sd->down.dir_y) *y = sd->down.sy - (*y - sd->down.y);
+ else *y = sd->down.sy;
+
+ if ((sd->down.dir_x) || (sd->down.dir_y))
+ {
+ if (!((sd->down.dir_x) && (sd->down.dir_y)))
+ {
+ if (sd->down.dir_x) *y = sd->down.locked_y;
+ else *x = sd->down.locked_x;
+ }
+ }
+
+ sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+
+ if (*x < minx)
+ *x += (minx - *x) * _elm_config->thumbscroll_border_friction;
+ else if (sd->child.w <= sd->w)
+ *x += (sd->down.sx - *x) * _elm_config->thumbscroll_border_friction;
+ else if ((sd->child.w - sd->w + minx) < *x)
+ *x += (sd->child.w - sd->w + minx - *x) *
+ _elm_config->thumbscroll_border_friction;
+
+ if (*y < miny)
+ *y += (miny - *y) * _elm_config->thumbscroll_border_friction;
+ else if (sd->child.h <= sd->h)
+ *y += (sd->down.sy - *y) * _elm_config->thumbscroll_border_friction;
+ else if ((sd->child.h - sd->h + miny) < *y)
+ *y += (sd->child.h - sd->h + miny - *y) *
+ _elm_config->thumbscroll_border_friction;
+}
+
+ Evas_Coord ox = 0, oy = 0, fx = 0, fy= 0;
+
+ fx = sd->down.hold_x;
+ fy = sd->down.hold_y;
+
+ if ((!sd->hold) && (!sd->freeze) && (_elm_config->scroll_smooth_time_interval > 0.0))
+ {
+ int i, count = 0; //count for the real event number we have to deal with
+ int queue_size = 10; //for event queue size
+ int src_index = 0, dst_index = 0;
+ int xsum = 0, ysum=0;
+ Evas_Coord x=0, y=0;
+
+ struct {
+ Evas_Coord x, y;
+ double t;
+ } pos[queue_size];
+
+ double tdiff, tnow;
+ double time_interval=_elm_config->scroll_smooth_time_interval;
+ // FIXME: assume server and client have the same "timezone"
+ // (0 timepoint) for now. this needs to be figured out in advance
+ // though.
+ tdiff = sd->down.hist.est_timestamp_diff;
+ tnow = ecore_time_get() - tdiff;
+
+ for(i = 0; i < queue_size; i++)
+ {
+ x = sd->down.history[i].x;
+ y = sd->down.history[i].y;
+
+ //if there is no history value , we don't deal with it
+ //if there is better wat to know existance of history value , I will modify this code to it
+ if ( (x == 0) && (y == 0) )
+ {
+ break;
+ }
+ _down_coord_eval(sd, &x, &y);
+
+ pos[i].x = x;
+ pos[i].y = y;
+ pos[i].t = tnow - sd->down.history[i].timestamp;
+ }
+ count = --i;
+
+ // we only deal with smooth scroll there is enough history
+ for(i = 0; i < queue_size; i++)
+ {
+ if (src_index > count) break;
+ if (i == 0)
+ {
+ xsum = pos[i].x;
+ ysum = pos[i].y;
+ dst_index++;
+ continue;
+ }
+ while ((pos[src_index].t < time_interval *i) &&
+ (src_index <= count))
+ {
+ src_index++;
+ }
+ if (src_index <= count)
+ {
+ xsum += pos[src_index].x;
+ ysum += pos[src_index].y;
+ dst_index++;
+ }
+ }
+ fx = xsum / dst_index;
+ fy = ysum / dst_index;
+ }
+
- edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
- edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
+ edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
+ edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
+ }
+ if (sd->pan_obj)
+ {
+ sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+ sd->pan_func.get(sd->pan_obj, &px, &py);
+ sd->pan_func.set(sd->pan_obj, minx, miny);
- Evas_Coord x, y, w, h, mx = 0, my = 0, vw = 0, vh = 0, px, py, minx = 0, miny = 0;
- double vx, vy, size;
-
- edje_object_part_geometry_get(sd->edje_obj, "elm.swallow.content",
- NULL, NULL, &vw, &vh);
- w = sd->child.w;
- if (w < 1) w = 1;
- size = (double)vw / (double)w;
- if (size > 1.0)
- {
- size = 1.0;
- edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
- }
- edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", size, 1.0);
-
- h = sd->child.h;
- if (h < 1) h = 1;
- size = (double)vh / (double)h;
- if (size > 1.0)
- {
- size = 1.0;
- edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
- }
- edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, size);
-
- edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
- edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
- sd->pan_func.max_get(sd->pan_obj, &mx, &my);
- sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
- x = vx * mx + minx;
- y = vy * my + miny;
-
- edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->step.x / (double)w, 0.0);
- edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->step.y / (double)h);
- if (sd->page.x > 0)
- edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->page.x / (double)w, 0.0);
- else
- edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", -((double)sd->page.x * ((double)vw / (double)w)) / 100.0, 0.0);
- if (sd->page.y > 0)
- edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->page.y / (double)h);
- else
- edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, -((double)sd->page.y * ((double)vh / (double)h)) / 100.0);
-
- sd->pan_func.get(sd->pan_obj, &px, &py);
+ Evas_Coord x, y, w, h, mx = 0, my = 0, vw = 0, vh = 0, px, py, minx = 0, miny = 0;
+ double vx, vy, size;
+
+ edje_object_part_geometry_get(sd->edje_obj, "elm.swallow.content",
+ NULL, NULL, &vw, &vh);
+ w = sd->child.w;
+ if (w < 1) w = 1;
+ size = (double)vw / (double)w;
+ if (size > 1.0)
+ {
+ size = 1.0;
+ edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
+ }
+ edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", size, 1.0);
+
+ h = sd->child.h;
+ if (h < 1) h = 1;
+ size = (double)vh / (double)h;
+ if (size > 1.0)
+ {
+ size = 1.0;
+ edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
+ }
+ edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, size);
+
+ edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
+ edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
+ sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+ sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
+ x = vx * mx + minx;
+ y = vy * my + miny;
+
+ edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->step.x / (double)w, 0.0);
+ edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->step.y / (double)h);
+ if (sd->page.x > 0)
+ edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->page.x / (double)w, 0.0);
+ else
+ edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", -((double)sd->page.x * ((double)vw / (double)w)) / 100.0, 0.0);
+ if (sd->page.y > 0)
+ edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->page.y / (double)h);
+ else
+ edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, -((double)sd->page.y * ((double)vh / (double)h)) / 100.0);
+
+ sd->pan_func.get(sd->pan_obj, &px, &py);
elm_smart_scroller_object_theme_set(NULL, obj, "scroller", "base", "default");
edje_object_signal_callback_add(o, "drag", "elm.dragable.vbar", _smart_edje_drag_v, sd);
edje_object_signal_callback_add(o, "drag,start", "elm.dragable.vbar", _smart_edje_drag_v_start, sd);
elm_smart_scroller_object_theme_set(NULL, obj, "scroller", "base", "default");
edje_object_signal_callback_add(o, "drag", "elm.dragable.vbar", _smart_edje_drag_v, sd);
edje_object_signal_callback_add(o, "drag,start", "elm.dragable.vbar", _smart_edje_drag_v_start, sd);