diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index bef62b6350..f09bec9e2a 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -1129,6 +1129,40 @@ my_anchorblock_anchor(void *data, Evas_Object *obj, void *event_info) } } +static void +my_anchorblock_edge_left(void *data, Evas_Object *obj, void *event_info) +{ + printf("left\n"); +} + +static void +my_anchorblock_edge_right(void *data, Evas_Object *obj, void *event_info) +{ + printf("right\n"); +} + +static void +my_anchorblock_edge_top(void *data, Evas_Object *obj, void *event_info) +{ + printf("top\n"); +} + +static void +my_anchorblock_edge_bottom(void *data, Evas_Object *obj, void *event_info) +{ + printf("bottom\n"); +} + +static void +my_anchorblock_scroll(void *data, Evas_Object *obj, void *event_info) +{ + Evas_Coord x, y, w, h, vw, vh; + + elm_scroller_region_get(obj, &x, &y, &w, &h); + elm_scroller_child_size_get(obj, &vw, &vh); + printf("scroll %ix%i +%i+%i in %ix%i\n", w, h, x, y, vw, vh); +} + static void my_bt_17(void *data, Evas_Object *obj, void *event_info) { @@ -1147,6 +1181,12 @@ my_bt_17(void *data, Evas_Object *obj, void *event_info) sc = elm_scroller_add(win); evas_object_size_hint_weight_set(sc, 1.0, 1.0); elm_win_resize_object_add(win, sc); + + evas_object_smart_callback_add(sc, "edge_left", my_anchorblock_edge_left, NULL); + evas_object_smart_callback_add(sc, "edge_right", my_anchorblock_edge_right, NULL); + evas_object_smart_callback_add(sc, "edge_top", my_anchorblock_edge_top, NULL); + evas_object_smart_callback_add(sc, "edge_bottom", my_anchorblock_edge_bottom, NULL); + evas_object_smart_callback_add(sc, "scroll", my_anchorblock_scroll, NULL); bx = elm_box_add(win); evas_object_size_hint_weight_set(bx, 1.0, 0.0); @@ -1575,10 +1615,16 @@ my_bt_20(void *data, Evas_Object *obj, void *event_info) evas_object_show(win); } +static void +my_li2_clear(void *data, Evas_Object *obj, void *event_info) +{ + elm_list_clear(data); +} + static void my_bt_21(void *data, Evas_Object *obj, void *event_info) { - Evas_Object *win, *bg, *li, *ic, *ic2, *bx; + Evas_Object *win, *bg, *li, *ic, *ic2, *bx, *bx2, *bt; char buf[PATH_MAX]; win = elm_win_add(NULL, "list-2", ELM_WIN_BASIC); @@ -1586,12 +1632,19 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info) elm_win_autodel_set(win, 1); bg = elm_bg_add(win); + snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR); + elm_bg_file_set(bg, buf, NULL); elm_win_resize_object_add(win, bg); evas_object_size_hint_weight_set(bg, 1.0, 1.0); evas_object_show(bg); + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, 1.0, 1.0); + elm_win_resize_object_add(win, bx); + evas_object_show(bx); + li = elm_list_add(win); - elm_win_resize_object_add(win, li); + evas_object_size_hint_align_set(li, -1.0, -1.0); evas_object_size_hint_weight_set(li, 1.0, 1.0); elm_list_horizontal_mode_set(li, ELM_LIST_LIMIT); elm_list_multi_select_set(li, 1); @@ -1618,15 +1671,15 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info) elm_icon_scale_set(ic2, 0, 0); elm_list_item_append(li, "How", ic, ic2, NULL, NULL); - bx = elm_box_add(win); - elm_box_horizontal_set(bx, 1); + bx2 = elm_box_add(win); + elm_box_horizontal_set(bx2, 1); ic = elm_icon_add(win); snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR); elm_icon_file_set(ic, buf, NULL); elm_icon_scale_set(ic, 0, 0); evas_object_size_hint_align_set(ic, 0.5, 0.5); - elm_box_pack_end(bx, ic); + elm_box_pack_end(bx2, ic); evas_object_show(ic); ic = elm_icon_add(win); @@ -1634,9 +1687,9 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info) elm_icon_file_set(ic, buf, NULL); elm_icon_scale_set(ic, 0, 0); evas_object_size_hint_align_set(ic, 0.5, 0.0); - elm_box_pack_end(bx, ic); + elm_box_pack_end(bx2, ic); evas_object_show(ic); - elm_list_item_append(li, "are", bx, NULL, NULL, NULL); + elm_list_item_append(li, "are", bx2, NULL, NULL, NULL); elm_list_item_append(li, "you", NULL, NULL, NULL, NULL); elm_list_item_append(li, "doing", NULL, NULL, NULL, NULL); @@ -1653,8 +1706,26 @@ my_bt_21(void *data, Evas_Object *obj, void *event_info) elm_list_go(li); + elm_box_pack_end(bx, li); evas_object_show(li); + bx2 = elm_box_add(win); + elm_box_horizontal_set(bx2, 1); + elm_box_homogenous_set(bx2, 1); + evas_object_size_hint_weight_set(bx2, 1.0, 0.0); + evas_object_size_hint_align_set(bx2, -1.0, -1.0); + + bt = elm_button_add(win); + elm_button_label_set(bt, "Clear"); + evas_object_smart_callback_add(bt, "clicked", my_li2_clear, li); + evas_object_size_hint_align_set(bt, -1.0, -1.0); + evas_object_size_hint_weight_set(bt, 1.0, 0.0); + elm_box_pack_end(bx2, bt); + evas_object_show(bt); + + elm_box_pack_end(bx, bx2); + evas_object_show(bx2); + evas_object_resize(win, 320, 300); evas_object_show(win); } @@ -2216,6 +2287,7 @@ my_bt_30(void *data, Evas_Object *obj, void *event_info) { Evas_Object *win, *bg, *gl, *bx, *bx2, *bt; Elm_Genlist_Item *gli[10]; + char buf[PATH_MAX]; int i; win = elm_win_add(NULL, "genlist-2", ELM_WIN_BASIC); @@ -2223,6 +2295,8 @@ my_bt_30(void *data, Evas_Object *obj, void *event_info) elm_win_autodel_set(win, 1); bg = elm_bg_add(win); + snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", PACKAGE_DATA_DIR); + elm_bg_file_set(bg, buf, NULL); elm_win_resize_object_add(win, bg); evas_object_size_hint_weight_set(bg, 1.0, 1.0); evas_object_show(bg); diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index c417520d22..4ce4877cd2 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -337,7 +337,14 @@ extern "C" { EAPI void elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); EAPI void elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v); EAPI void elm_scroller_region_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); + EAPI void elm_scroller_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h); + EAPI void elm_scroller_bounce_set(Evas_Object *obj, Evas_Bool h_bounce, Evas_Bool v_bounce); /* smart callbacks called: + * "edge_left" + * "edge_right" + * "edge_top" + * "edge_bottom" + * "scroll" */ EAPI Evas_Object *elm_label_add(Evas_Object *parent); diff --git a/legacy/elementary/src/lib/elm_genlist.c b/legacy/elementary/src/lib/elm_genlist.c index 0d1cf7dd04..a016d44767 100644 --- a/legacy/elementary/src/lib/elm_genlist.c +++ b/legacy/elementary/src/lib/elm_genlist.c @@ -623,10 +623,10 @@ _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) if (ow < 0) ow = 0; oh = sd->wd->minh - oh; if (oh < 0) oh = 0; - if (x < 0) x = 0; - if (y < 0) y = 0; - if (x > ow) x = ow; - if (y > oh) y = oh; +// if (x < 0) x = 0; +// if (y < 0) y = 0; +// if (x > ow) x = ow; +// if (y > oh) y = oh; if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return; sd->wd->pan_x = x; sd->wd->pan_y = y; @@ -751,6 +751,8 @@ elm_genlist_add(Evas_Object *parent) wd->scr = elm_smart_scroller_add(e); elm_widget_resize_object_set(obj, wd->scr); + elm_smart_scroller_bounce_allow_set(wd->scr, 0, 1); + wd->obj = obj; wd->mode = ELM_LIST_SCROLL; diff --git a/legacy/elementary/src/lib/elm_list.c b/legacy/elementary/src/lib/elm_list.c index b00e33d779..92a974ecb0 100644 --- a/legacy/elementary/src/lib/elm_list.c +++ b/legacy/elementary/src/lib/elm_list.c @@ -370,6 +370,8 @@ elm_list_add(Evas_Object *parent) wd->scroller = elm_scroller_add(parent); elm_widget_resize_object_set(obj, wd->scroller); + elm_scroller_bounce_set(wd->scroller, 0, 1); + wd->box = elm_box_add(parent); elm_box_homogenous_set(wd->box, 1); evas_object_size_hint_weight_set(wd->box, 1.0, 0.0); diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index b98b427b3a..a5a57bb64f 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -91,6 +91,8 @@ elm_shutdown(void) static const char *elm_engine, *elm_scale, *elm_theme, *elm_prefix, *elm_data_dir; static const char *elm_font_hinting, *elm_font_path, *elm_image_cache; static const char *elm_font_cache, *elm_finger_size, *elm_fps; +static const char *elm_thumbscroll_enabled, *elm_thumbscroll_threshhold; +static const char *elm_thumbscroll_momentum_threshhold, *elm_thumbscroll_friction; EAPI void elm_quicklaunch_init(int argc, char **argv) @@ -121,6 +123,10 @@ elm_quicklaunch_init(int argc, char **argv) elm_font_cache = getenv("ELM_FONT_CACHE"); elm_finger_size = getenv("ELM_FINGER_SIZE"); elm_fps = getenv("ELM_FPS"); + elm_thumbscroll_enabled = getenv("ELM_THUMBSCROLL_ENABLE"); + elm_thumbscroll_threshhold = getenv("ELM_THUMBSCROLL_THRESHOLD"); + elm_thumbscroll_momentum_threshhold = getenv("ELM_THUMBSCROLL_MOMENTUM_THRESHOLD"); + elm_thumbscroll_friction = getenv("ELM_THUMBSCROLL_FRICTION"); if (!_elm_data_dir) { @@ -174,7 +180,9 @@ elm_quicklaunch_init(int argc, char **argv) _elm_config->thumbscroll_enable = 1; _elm_config->thumbscroll_threshhold = 24; _elm_config->thumbscroll_momentum_threshhold = 100.0; - _elm_config->thumbscroll_friction = 20.0; + _elm_config->thumbscroll_friction = 1.0; + _elm_config->thumbscroll_bounce_friction = 0.5; + _elm_config->thumbscroll_bounce_enable = 1; _elm_config->scale = 1.0; _elm_config->font_hinting = 2; _elm_config->font_dirs = NULL; @@ -221,6 +229,16 @@ elm_quicklaunch_init(int argc, char **argv) _elm_config->engine = ELM_SOFTWARE_16_WINCE; } + if (elm_thumbscroll_enabled) + _elm_config->thumbscroll_enable = atoi(elm_thumbscroll_enabled); + if (elm_thumbscroll_threshhold) + _elm_config->thumbscroll_threshhold = atoi(elm_thumbscroll_threshhold); + // FIXME: floatformat locale issues here 1.0 vs 1,0 - should just be 1.0 + if (elm_thumbscroll_momentum_threshhold) + _elm_config->thumbscroll_momentum_threshhold = atof(elm_thumbscroll_momentum_threshhold); + if (elm_thumbscroll_friction) + _elm_config->thumbscroll_friction = atof(elm_thumbscroll_friction); + if (elm_theme) _elm_theme_parse(elm_theme); else @@ -349,7 +367,8 @@ elm_quicklaunch_sub_shutdown(void) ecore_event_handler_del(_elm_event_property_change); _elm_event_property_change = NULL; ecore_x_disconnect(); -#endif +#endif + evas_cserve_disconnect(); } } diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index b88d9a007c..47765789f7 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -41,6 +41,8 @@ struct _Elm_Config int thumbscroll_threshhold; double thumbscroll_momentum_threshhold; double thumbscroll_friction; + double thumbscroll_bounce_friction; + int thumbscroll_bounce_enable; double scale; int bgpixmap; int compositing; diff --git a/legacy/elementary/src/lib/elm_scroller.c b/legacy/elementary/src/lib/elm_scroller.c index c26d6091bc..2800f54f44 100644 --- a/legacy/elementary/src/lib/elm_scroller.c +++ b/legacy/elementary/src/lib/elm_scroller.c @@ -137,6 +137,36 @@ _resize(void *data, Evas *e, Evas_Object *obj, void *event_info) _sizing_eval(data); } +static void +_edge_left(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + evas_object_smart_callback_call(data, "edge_left", NULL); +} + +static void +_edge_right(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + evas_object_smart_callback_call(data, "edge_right", NULL); +} + +static void +_edge_top(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + evas_object_smart_callback_call(data, "edge_top", NULL); +} + +static void +_edge_bottom(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + evas_object_smart_callback_call(data, "edge_bottom", NULL); +} + +static void +_scroll(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + evas_object_smart_callback_call(data, "scroll", NULL); +} + EAPI Evas_Object * elm_scroller_add(Evas_Object *parent) { @@ -167,6 +197,12 @@ elm_scroller_add(Evas_Object *parent) evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj); + evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj); + evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj); + evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj); + evas_object_smart_callback_add(wd->scr, "scroll", _scroll, obj); + _sizing_eval(obj); return obj; } @@ -232,3 +268,19 @@ elm_scroller_region_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coo if ((x) && (y)) elm_smart_scroller_child_pos_get(wd->scr, x, y); if ((w) && (h)) elm_smart_scroller_child_viewport_size_get(wd->scr, w, h); } + +EAPI void +elm_scroller_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + evas_object_geometry_get(wd->content, NULL, NULL, w, h); +} + +EAPI void +elm_scroller_bounce_set(Evas_Object *obj, Evas_Bool h_bounce, Evas_Bool v_bounce) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce); +} diff --git a/legacy/elementary/src/lib/elm_toolbar.c b/legacy/elementary/src/lib/elm_toolbar.c index 87db110f42..ac4424bd56 100644 --- a/legacy/elementary/src/lib/elm_toolbar.c +++ b/legacy/elementary/src/lib/elm_toolbar.c @@ -185,6 +185,7 @@ elm_toolbar_add(Evas_Object *parent) elm_widget_can_focus_set(obj, 0); wd->scr = elm_smart_scroller_add(e); + elm_scroller_bounce_set(wd->scr, 1, 0); elm_smart_scroller_theme_set(wd->scr, "toolbar", "base", "default"); elm_widget_resize_object_set(obj, wd->scr); elm_smart_scroller_policy_set(wd->scr, diff --git a/legacy/elementary/src/lib/els_box.c b/legacy/elementary/src/lib/els_box.c index 2fa9d97398..941cab3493 100644 --- a/legacy/elementary/src/lib/els_box.c +++ b/legacy/elementary/src/lib/els_box.c @@ -162,7 +162,12 @@ _els_smart_box_unpack(Evas_Object *obj) if (!sd) return; sd->items = eina_list_remove(sd->items, obj); _smart_disown(obj); - if (!sd->deleting) _smart_reconfigure(sd); + if (!sd->deleting) + { + if (!evas_object_clipees_get(sd->clip)) + evas_object_hide(sd->clip); + _smart_reconfigure(sd); + } } /* local subsystem functions */ diff --git a/legacy/elementary/src/lib/els_icon.c b/legacy/elementary/src/lib/els_icon.c index 4e81078c10..78175a395b 100644 --- a/legacy/elementary/src/lib/els_icon.c +++ b/legacy/elementary/src/lib/els_icon.c @@ -356,6 +356,7 @@ _smart_add(Evas_Object *obj) sd = calloc(1, sizeof(Smart_Data)); if (!sd) return; sd->obj = evas_object_image_add(evas_object_evas_get(obj)); + evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC); sd->x = 0; sd->y = 0; sd->w = 0; diff --git a/legacy/elementary/src/lib/els_pan.c b/legacy/elementary/src/lib/els_pan.c index b63420a56d..f032b5af93 100644 --- a/legacy/elementary/src/lib/els_pan.c +++ b/legacy/elementary/src/lib/els_pan.c @@ -87,10 +87,10 @@ void _elm_smart_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { API_ENTRY return; - if (x > (sd->child_w - sd->w)) x = sd->child_w - sd->w; - if (y > (sd->child_h - sd->h)) y = sd->child_h - sd->h; - if (x < 0) x = 0; - if (y < 0) y = 0; +// if (x > (sd->child_w - sd->w)) x = sd->child_w - sd->w; +// if (y > (sd->child_h - sd->h)) y = sd->child_h - sd->h; +// if (x < 0) x = 0; +// if (y < 0) y = 0; if ((x == sd->px) && (y == sd->py)) return; sd->px = x; sd->py = y; diff --git a/legacy/elementary/src/lib/els_scroller.c b/legacy/elementary/src/lib/els_scroller.c index 8a00f9a99f..e1cdf3a85a 100644 --- a/legacy/elementary/src/lib/els_scroller.c +++ b/legacy/elementary/src/lib/els_scroller.c @@ -22,22 +22,34 @@ struct _Smart_Data Evas_Coord x, y; Evas_Coord sx, sy; Evas_Coord dx, dy; + Evas_Coord bx, by; + Evas_Coord ax, ay; + Evas_Coord bx0, by0; + Evas_Coord b0x, b0y; + Evas_Coord b2x, b2y; struct { Evas_Coord x, y; double timestamp; } history[20]; double anim_start; + double anim_start2; + double anim_start3; double onhold_vx, onhold_vy, onhold_tlast, onhold_vxe, onhold_vye; Evas_Coord hold_x, hold_y; Ecore_Animator *hold_animator; - Ecore_Animator *momentum_animator; Ecore_Animator *onhold_animator; + Ecore_Animator *momentum_animator; + Ecore_Animator *bounce_x_animator; + Ecore_Animator *bounce_y_animator; Evas_Coord locked_x, locked_y; unsigned char now : 1; unsigned char dragged : 1; unsigned char dir_x : 1; unsigned char dir_y : 1; + unsigned char dir_none : 1; unsigned char locked : 1; + unsigned char bounce_x_hold : 1; + unsigned char bounce_y_hold : 1; } down; struct { @@ -61,6 +73,10 @@ struct _Smart_Data unsigned char one_dir_at_a_time : 1; unsigned char hold : 1; unsigned char freeze : 1; + unsigned char bouncemex : 1; + unsigned char bouncemey : 1; + unsigned char bounce_horiz : 1; + unsigned char bounce_vert : 1; }; /* local subsystem functions */ @@ -215,6 +231,173 @@ elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *grou edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm"); } +static int +_smart_bounce_x_animator(void *data) +{ + Smart_Data *sd; + Evas_Coord x, y, dx, dy/*, ox, oy*/; + double t, p, dt; + + sd = data; + t = ecore_loop_time_get(); + dt = t - sd->down.anim_start2; + if (dt >= 0.0) + { + dt = dt / _elm_config->thumbscroll_bounce_friction; + if (dt > 1.0) dt = 1.0; + p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt)); + elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); + dx = sd->down.b2x - sd->down.bx; + dx = (dx * p); + x = sd->down.bx + dx; + elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); + if (dt >= 1.0) + { + if (sd->down.momentum_animator) + sd->down.bounce_x_hold = 1; + sd->down.bounce_x_animator = NULL; + sd->bouncemex = 0; + return 0; + } + } + return 1; +} + +static int +_smart_bounce_y_animator(void *data) +{ + Smart_Data *sd; + Evas_Coord x, y, dx, dy; + double t, p, dt; + + sd = data; + t = ecore_loop_time_get(); + dt = t - sd->down.anim_start3; + if (dt >= 0.0) + { + dt = dt / _elm_config->thumbscroll_bounce_friction; + if (dt > 1.0) dt = 1.0; + p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt)); + elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); + dy = sd->down.b2y - sd->down.by; + dy = (dy * p); + y = sd->down.by + dy; + elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); + if (dt >= 1.0) + { + if (sd->down.momentum_animator) + sd->down.bounce_y_hold = 1; + sd->down.bounce_y_animator = NULL; + sd->bouncemey = 0; + return 0; + } + } + return 1; +} + +static int +_smart_momentum_animator(void *data) +{ + Smart_Data *sd; + double t, dt, p; + Evas_Coord x, y, dx, dy, px, py; + + sd = data; + t = ecore_loop_time_get(); + dt = t - sd->down.anim_start; + if (dt >= 0.0) + { + dt = dt / _elm_config->thumbscroll_friction; + if (dt > 1.0) dt = 1.0; + p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt)); + dx = (sd->down.dx * _elm_config->thumbscroll_friction * p); + dy = (sd->down.dy * _elm_config->thumbscroll_friction * p); + sd->down.ax = dx; + sd->down.ay = dy; + x = sd->down.sx - dx; + y = sd->down.sy - dy; + elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py); + if ((sd->down.bounce_x_animator) || + (sd->down.bounce_x_hold)) + { + sd->down.bx = sd->down.bx0 - dx + sd->down.b0x; + x = px; + } + if ((sd->down.bounce_y_animator) || + (sd->down.bounce_y_hold)) + { + sd->down.by = sd->down.by0 - dy + sd->down.b0y; + y = py; + } + elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); + if (dt >= 1.0) + { + 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; + return 0; + } + } + return 1; +} + +static void +bounce_eval(Smart_Data *sd) +{ + Evas_Coord mx, my, px, py, bx, by, b2x, b2y; + + if ((!sd->bouncemex) && (!sd->bouncemey)) return; + if (sd->down.now) return; // down bounce while still held down + if (sd->down.onhold_animator) + { + ecore_animator_del(sd->down.onhold_animator); + sd->down.onhold_animator = NULL; + } + if (sd->down.hold_animator) + { + ecore_animator_del(sd->down.hold_animator); + sd->down.hold_animator = NULL; + } + sd->pan_func.max_get(sd->pan_obj, &mx, &my); + sd->pan_func.get(sd->pan_obj, &px, &py); + bx = px; + by = py; + if (px < 0) px = 0; + if (px > mx) px = mx; + if (py < 0) py = 0; + if (py > my) py = my; + b2x = px; + b2y = py; + if (!sd->down.bounce_x_animator) + { + if (sd->bouncemex) + { + sd->down.bounce_x_animator = ecore_animator_add(_smart_bounce_x_animator, sd); + sd->down.anim_start2 = ecore_loop_time_get(); + sd->down.bx = bx; + sd->down.bx0 = bx; + sd->down.b2x = b2x; + if (sd->down.momentum_animator) sd->down.b0x = sd->down.ax; + else sd->down.b0x = 0; + } + } + if (!sd->down.bounce_y_animator) + { + if (sd->bouncemey) + { + sd->down.bounce_y_animator = ecore_animator_add(_smart_bounce_y_animator, sd); + sd->down.anim_start3 = ecore_loop_time_get(); + sd->down.by = by; + sd->down.by0 = by; + sd->down.b2y = b2y; + if (sd->down.momentum_animator) sd->down.b0y = sd->down.ay; + else sd->down.b0y = 0; + } + } +} + void elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { @@ -235,9 +418,62 @@ elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, vy); edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", vx, 0.0); sd->pan_func.get(sd->pan_obj, &px, &py); + if (!_elm_config->thumbscroll_bounce_enable) + { + if (x < 0) x = 0; + if (x > mx) x = mx; + if (y < 0) y = 0; + if (y > my) y = my; + } + + if (!sd->bounce_horiz) + { + if (x < 0) x = 0; + if (x > mx) x = mx; + } + if (!sd->bounce_vert) + { + if (y < 0) y = 0; + if (y > my) y = my; + } + sd->pan_func.set(sd->pan_obj, x, y); if ((px != x) || (py != y)) edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm"); + if (!sd->down.bounce_x_animator) + { + if ((x < 0) || (x > mx)) + { + sd->bouncemex = 1; + bounce_eval(sd); + } + } + if (!sd->down.bounce_y_animator) + { + if ((y < 0) || (y > my)) + { + sd->bouncemey = 1; + bounce_eval(sd); + } + } + if ((x != px) || (y != py)) + { + evas_object_smart_callback_call(obj, "scroll", NULL); + } + if ((x != px)/* && (!sd->bouncemex)*/) + { + if (x == 0) + evas_object_smart_callback_call(obj, "edge,left", NULL); + if (x == mx) + evas_object_smart_callback_call(obj, "edge,right", NULL); + } + if ((y != py)/* && (!sd->bouncemey)*/) + { + if (y == 0) + evas_object_smart_callback_call(obj, "edge,top", NULL); + if (y == my) + evas_object_smart_callback_call(obj, "edge,bottom", NULL); + } } void @@ -272,6 +508,18 @@ elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord if (ny > y) ny = y; } if ((nx == px) && (ny == py)) return; + 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; + } elm_smart_scroller_child_pos_set(obj, nx, ny); } @@ -404,6 +652,14 @@ elm_smart_scroller_freeze_set(Evas_Object *obj, Evas_Bool freeze) } } +void +elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Evas_Bool horiz, Evas_Bool vert) +{ + API_ENTRY return; + sd->bounce_horiz = horiz; + sd->bounce_vert = vert; +} + /* local subsystem functions */ static void _smart_edje_drag_v(void *data, Evas_Object *obj, const char *emission, const char *source) @@ -437,10 +693,24 @@ _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info) static void _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info) { + Evas_Coord x, y; Evas_Coord w, h; Smart_Data *sd; sd = data; + 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; + } + sd->pan_func.get(sd->pan_obj, &x, &y); sd->pan_func.child_size_get(sd->pan_obj, &w, &h); if ((w != sd->child.w) || (h != sd->child.h)) { @@ -448,6 +718,7 @@ _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info) sd->child.h = h; _smart_scrollbar_size_adjust(sd); evas_object_size_hint_min_set(sd->smart_obj, sd->child.w, sd->child.h); + elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); } } @@ -459,6 +730,18 @@ _smart_pan_pan_changed_hook(void *data, Evas_Object *obj, void *event_info) sd = data; sd->pan_func.get(sd->pan_obj, &x, &y); + 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; + } elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); } @@ -473,6 +756,12 @@ _smart_event_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info) ev = event_info; elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); y += ev->z * sd->step.y; + if (sd->down.bounce_y_animator) + { + ecore_animator_del(sd->down.bounce_y_animator); + sd->down.bounce_y_animator = NULL; + sd->bouncemey = 0; + } elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); } @@ -487,6 +776,18 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info) ev = event_info; if (_elm_config->thumbscroll_enable) { + 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); @@ -496,6 +797,10 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info) { 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; } if (ev->button == 1) { @@ -503,6 +808,7 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info) sd->down.dragged = 0; sd->down.dir_x = 0; sd->down.dir_y = 0; + sd->down.dir_none = 0; sd->down.x = ev->canvas.x; sd->down.y = ev->canvas.y; elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); @@ -510,7 +816,7 @@ _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info) sd->down.sy = y; sd->down.locked = 0; memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 20); - sd->down.history[0].timestamp = ecore_time_get(); + sd->down.history[0].timestamp = ecore_loop_time_get(); sd->down.history[0].x = ev->canvas.x; sd->down.history[0].y = ev->canvas.y; } @@ -528,35 +834,6 @@ _smart_hold_animator(void *data) return 0; } -static int -_smart_momentum_animator(void *data) -{ - Smart_Data *sd; - double t, dt, p; - Evas_Coord x, y, dx, dy; - - sd = data; - t = ecore_time_get(); - dt = t - sd->down.anim_start; - if (dt >= 0.0) - { - dt = dt / _elm_config->thumbscroll_friction; - if (dt > 1.0) dt = 1.0; - p = 1.0 - ((1.0 - dt) * (1.0 - dt) * (1.0 - dt)); - dx = (sd->down.dx * _elm_config->thumbscroll_friction * p); - dy = (sd->down.dy * _elm_config->thumbscroll_friction * p); - x = sd->down.sx - dx; - y = sd->down.sy - dy; - elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); - if (dt >= 1.0) - { - sd->down.momentum_animator = NULL; - return 0; - } - } - return 1; -} - static void _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info) { @@ -586,7 +863,7 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info) int i; Evas_Coord ax, ay, dx, dy, vel; - t = ecore_time_get(); + t = ecore_loop_time_get(); ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; ax = ev->canvas.x; ay = ev->canvas.y; @@ -624,6 +901,8 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info) elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); sd->down.sx = x; sd->down.sy = y; + sd->down.b0x = 0; + sd->down.b0y = 0; } } } @@ -631,6 +910,9 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info) } sd->down.dragged = 0; sd->down.now = 0; + elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); + elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); + bounce_eval(sd); } } } @@ -677,9 +959,11 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info) { if (sd->down.now) { + int faildir = 0; + memmove(&(sd->down.history[1]), &(sd->down.history[0]), sizeof(sd->down.history[0]) * 19); - sd->down.history[0].timestamp = ecore_time_get(); + sd->down.history[0].timestamp = ecore_loop_time_get(); sd->down.history[0].x = ev->cur.canvas.x; sd->down.history[0].y = ev->cur.canvas.y; @@ -688,24 +972,27 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info) y = ev->cur.canvas.y - sd->down.y; if (y < 0) y = -y; if ((sd->one_dir_at_a_time) && - (!sd->down.dir_x) && (!sd->down.dir_y)) + (!sd->down.dir_x) && (!sd->down.dir_y) && (!sd->down.dir_none)) { - if (x > y) - { - if (x > _elm_config->thumbscroll_threshhold) - { + if (x > _elm_config->thumbscroll_threshhold) + { + if (x > (y * 2)) + { sd->down.dir_x = 1; sd->down.dir_y = 0; } + else faildir++; } - else + if (y > _elm_config->thumbscroll_threshhold) { - if (y > _elm_config->thumbscroll_threshhold) + if (y > (x * 2)) { sd->down.dir_x = 0; sd->down.dir_y = 1; - } + } + else faildir++; } + if (faildir) sd->down.dir_none = 1; } if (!sd->hold) { @@ -809,6 +1096,7 @@ _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) Evas_Event_Key_Down *ev; Smart_Data *sd; Evas_Coord x = 0, y = 0, vw = 0, vh = 0, mx = 0, my = 0; + int xch = 0, ych = 0; sd = data; ev = event_info; @@ -817,23 +1105,42 @@ _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) sd->pan_func.max_get(sd->pan_obj, &mx, &my); evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh); if (!strcmp(ev->keyname, "Left")) - x -= sd->step.x; + { + x -= sd->step.x; + xch = 1; + } else if (!strcmp(ev->keyname, "Right")) - x += sd->step.x; + { + x += sd->step.x; + xch = 1; + } else if (!strcmp(ev->keyname, "Up")) - y -= sd->step.y; + { + y -= sd->step.y; + ych = 1; + } else if (!strcmp(ev->keyname, "Home")) - y = 0; + { + y = 0; + ych = 1; + } else if (!strcmp(ev->keyname, "End")) - y = my; + { + y = my; + ych = 1; + } else if (!strcmp(ev->keyname, "Down")) - y += sd->step.y; + { + y += sd->step.y; + ych = 1; + } else if (!strcmp(ev->keyname, "Prior")) { if (sd->page.y < 0) y -= -(sd->page.y * vh) / 100; else y -= sd->page.y; + ych = 1; } else if (!strcmp(ev->keyname, "Next")) { @@ -841,7 +1148,27 @@ _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) y += -(sd->page.y * vh) / 100; else y += sd->page.y; + ych = 1; } + if (xch) + { + if (sd->down.bounce_x_animator) + { + ecore_animator_del(sd->down.bounce_x_animator); + sd->down.bounce_x_animator = NULL; + sd->bouncemex = 0; + } + } + if (ych) + { + if (sd->down.bounce_y_animator) + { + ecore_animator_del(sd->down.bounce_y_animator); + sd->down.bounce_y_animator = NULL; + sd->bouncemey = 0; + } + } + elm_smart_scroller_child_pos_set(sd->smart_obj, x, y); } @@ -1135,6 +1462,11 @@ _smart_add(Evas_Object *obj) sd->hbar_visible = 1; sd->vbar_visible = 1; + sd->bounce_horiz = 1; + sd->bounce_vert = 1; + + sd->one_dir_at_a_time = 1; + evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _smart_event_key_down, sd); evas_object_propagate_events_set(obj, 0); @@ -1180,7 +1512,10 @@ _smart_del(Evas_Object *obj) evas_object_del(sd->edje_obj); evas_object_del(sd->event_obj); if (sd->down.hold_animator) ecore_animator_del(sd->down.hold_animator); + if (sd->down.onhold_animator) ecore_animator_del(sd->down.onhold_animator); if (sd->down.momentum_animator) ecore_animator_del(sd->down.momentum_animator); + if (sd->down.bounce_x_animator) ecore_animator_del(sd->down.bounce_x_animator); + if (sd->down.bounce_y_animator) ecore_animator_del(sd->down.bounce_y_animator); free(sd); evas_object_smart_data_set(obj, NULL); } diff --git a/legacy/elementary/src/lib/els_scroller.h b/legacy/elementary/src/lib/els_scroller.h index 0d9c9362d2..007614830c 100644 --- a/legacy/elementary/src/lib/els_scroller.h +++ b/legacy/elementary/src/lib/els_scroller.h @@ -26,3 +26,4 @@ Evas_Bool elm_smart_scroller_single_dir_get (Evas_Object *obj); void elm_smart_scroller_theme_set (Evas_Object *obj, const char *clas, const char *group, const char *style); void elm_smart_scroller_hold_set (Evas_Object *obj, Evas_Bool hold); void elm_smart_scroller_freeze_set (Evas_Object *obj, Evas_Bool freeze); +void elm_smart_scroller_bounce_allow_set (Evas_Object *obj, Evas_Bool horiz, Evas_Bool vert);