From d6a594790198d157c43c15ecf4c15efcecb73a06 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Tue, 8 Sep 2009 06:20:32 +0000 Subject: [PATCH] fix scroll freeze and propagate to built-in scrollers. also genlist now knows about dragging items. callbacks for that. SVN revision: 42342 --- src/bin/test_genlist.c | 1 + src/lib/elc_notepad.c | 47 +++++++++++++++++-- src/lib/elm_genlist.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/elm_list.c | 62 +++++++++++++++++++------ src/lib/els_scroller.c | 8 +++- 5 files changed, 219 insertions(+), 20 deletions(-) diff --git a/src/bin/test_genlist.c b/src/bin/test_genlist.c index c6271be..3b3dc31 100644 --- a/src/bin/test_genlist.c +++ b/src/bin/test_genlist.c @@ -802,6 +802,7 @@ test_genlist5(void *data, Evas_Object *obj, void *event_info) NULL/* func data */); elm_box_pack_end(bx, gl); + elm_object_scroll_freeze_push(gl); evas_object_show(bx2); bx2 = elm_box_add(win); diff --git a/src/lib/elc_notepad.c b/src/lib/elc_notepad.c index 54da6ad..abf96c4 100644 --- a/src/lib/elc_notepad.c +++ b/src/lib/elc_notepad.c @@ -20,7 +20,7 @@ typedef struct _Widget_Data Widget_Data; struct _Widget_Data { - Evas_Object *scroller, *entry; + Evas_Object *scr, *entry; const char *file; Elm_Text_Format format; Ecore_Timer *delay_write; @@ -220,6 +220,38 @@ _entry_changed(void *data, Evas_Object *obj, void *event_info) wd->delay_write = ecore_timer_add(2.0, _delay_write, data); } +static void +_hold_on(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_push(wd->scr); +} + +static void +_hold_off(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_pop(wd->scr); +} + +static void +_freeze_on(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_push(wd->scr); +} + +static void +_freeze_off(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_pop(wd->scr); +} + /** * Add a new notepad to the parent * @@ -245,17 +277,22 @@ elm_notepad_add(Evas_Object *parent) elm_widget_del_hook_set(obj, _del_hook); elm_widget_can_focus_set(obj, 1); - wd->scroller = elm_scroller_add(parent); - elm_widget_resize_object_set(obj, wd->scroller); + wd->scr = elm_scroller_add(parent); + elm_widget_resize_object_set(obj, wd->scr); wd->entry = elm_entry_add(parent); evas_object_size_hint_weight_set(wd->entry, 1.0, 1.0); evas_object_size_hint_align_set(wd->entry, -1.0, -1.0); - elm_scroller_content_set(wd->scroller, wd->entry); + elm_scroller_content_set(wd->scr, wd->entry); evas_object_show(wd->entry); elm_entry_entry_set(wd->entry, ""); evas_object_smart_callback_add(wd->entry, "changed", _entry_changed, obj); - + + evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); + evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + wd->auto_write = EINA_TRUE; _sizing_eval(obj); diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c index ad9bb99..f4585e2 100644 --- a/src/lib/elm_genlist.c +++ b/src/lib/elm_genlist.c @@ -50,6 +50,21 @@ * not use the object pointer from elm_genlist_item_object_get() in a way * where it may point to freed objects. * + * drag,start,up - This is called when the item in the list has been dragged + * (not scrolled) up. + * + * drag,start,down - This is called when the item in the list has been dragged + * (not scrolled) down. + * + * drag,start,left - This is called when the item in the list has been dragged + * (not scrolled) left. + * + * drag,start,right - This is called when the item in the list has been dragged + * (not scrolled) right. + * + * drag,stop - This is called when the item in the list has stopped being + * dragged. + * * Genlist has a fairly large API, mostly because it's relatively complex, * trying to be both expansive, powerful and efficient. First we will begin * an overview o the theory behind genlist. @@ -281,6 +296,7 @@ struct _Elm_Genlist_Item Eina_List *labels, *icons, *states; Eina_List *icon_objs; Ecore_Timer *long_timer; + Evas_Coord dx, dy; Elm_Genlist_Item *rel; int relcount; @@ -295,6 +311,8 @@ struct _Elm_Genlist_Item Eina_Bool queued : 1; Eina_Bool showme : 1; Eina_Bool delete_me : 1; + Eina_Bool down : 1; + Eina_Bool dragging : 1; }; struct _Pan @@ -466,6 +484,7 @@ _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info) { Elm_Genlist_Item *it = data; Evas_Event_Mouse_Move *ev = event_info; + Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) { if (!it->wd->on_hold) @@ -474,6 +493,57 @@ _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info) _item_unselect(it); } } + if (!it->down) return; + if (it->wd->on_hold) return; + if (it->wd->longpressed) return; + elm_coords_finger_size_adjust(1, &minw, 1, &minh); + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + x = ev->cur.canvas.x - x; + y = ev->cur.canvas.y - y; + dx = x - it->dx; + adx = dx; + if (adx < 0) adx = -dx; + dy = y - it->dy; + ady = dy; + if (ady < 0) ady = -dy; + minw /= 2; + minh /= 2; + if ((adx > minw) || (ady > minh)) + { + it->dragging = 1; + if (it->long_timer) + { + ecore_timer_del(it->long_timer); + it->long_timer = NULL; + } + if (!it->wd->wasselected) + _item_unselect(it); + it->wd->wasselected = 0; + if (dy < 0) + { + if (ady > adx) + evas_object_smart_callback_call(it->wd->obj, "drag,start,up", it); + else + { + if (dx < 0) + evas_object_smart_callback_call(it->wd->obj, "drag,start,left", it); + else + evas_object_smart_callback_call(it->wd->obj, "drag,start,right", it); + } + } + else + { + if (ady > adx) + evas_object_smart_callback_call(it->wd->obj, "drag,start,down", it); + else + { + if (dx < 0) + evas_object_smart_callback_call(it->wd->obj, "drag,start,left", it); + else + evas_object_smart_callback_call(it->wd->obj, "drag,start,right", it); + } + } + } } static int @@ -482,6 +552,7 @@ _long_press(void *data) Elm_Genlist_Item *it = data; it->long_timer = NULL; if (it->disabled) return 0; + if (it->dragging) return 0; it->wd->longpressed = EINA_TRUE; evas_object_smart_callback_call(it->wd->obj, "longpressed", it); return 0; @@ -492,7 +563,13 @@ _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info) { Elm_Genlist_Item *it = data; Evas_Event_Mouse_Down *ev = event_info; + Evas_Coord x, y; if (ev->button != 1) return; + it->down = 1; + it->dragging = 0; + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + it->dx = ev->canvas.x - x; + it->dy = ev->canvas.y - y; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE; else it->wd->on_hold = EINA_FALSE; it->wd->wasselected = it->selected; @@ -510,6 +587,7 @@ _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info) Evas_Event_Mouse_Up *ev = event_info; Eina_List *l; if (ev->button != 1) return; + it->down = 0; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE; else it->wd->on_hold = EINA_FALSE; if (it->long_timer) @@ -517,8 +595,14 @@ _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info) ecore_timer_del(it->long_timer); it->long_timer = NULL; } + if (it->dragging) + { + it->dragging = 0; + evas_object_smart_callback_call(it->wd->obj, "drag,stop", it); + } if (it->wd->on_hold) { + it->wd->longpressed = EINA_FALSE; it->wd->on_hold = EINA_FALSE; return; } @@ -1050,6 +1134,38 @@ _pan_calculate(Evas_Object *obj) } } +static void +_hold_on(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_smart_scroller_hold_set(wd->scr, 1); +} + +static void +_hold_off(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_smart_scroller_hold_set(wd->scr, 0); +} + +static void +_freeze_on(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_smart_scroller_freeze_set(wd->scr, 1); +} + +static void +_freeze_off(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_smart_scroller_freeze_set(wd->scr, 0); +} + /** * Add a new Genlist object * @@ -1084,6 +1200,11 @@ elm_genlist_add(Evas_Object *parent) wd->obj = obj; wd->mode = ELM_LIST_SCROLL; + evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); + evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + if (!smart) { static Evas_Smart_Class sc; diff --git a/src/lib/elm_list.c b/src/lib/elm_list.c index 46e7ebf..463f56d 100644 --- a/src/lib/elm_list.c +++ b/src/lib/elm_list.c @@ -5,7 +5,7 @@ typedef struct _Widget_Data Widget_Data; struct _Widget_Data { - Evas_Object *scroller, *box; + Evas_Object *scr, *box; Eina_List *items; Eina_List *selected; Elm_List_Mode mode; @@ -73,8 +73,8 @@ _sizing_eval(Evas_Object *obj) Widget_Data *wd = elm_widget_data_get(obj); Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; - evas_object_size_hint_min_get(wd->scroller, &minw, &minh); - evas_object_size_hint_max_get(wd->scroller, &maxw, &maxh); + evas_object_size_hint_min_get(wd->scr, &minw, &minh); + evas_object_size_hint_max_get(wd->scr, &maxw, &maxh); evas_object_size_hint_min_set(obj, minw, minh); evas_object_size_hint_max_set(obj, maxw, maxh); } @@ -429,12 +429,44 @@ _fix_items(Evas_Object *obj) mw = 0; mh = 0; evas_object_size_hint_min_get(wd->box, &mw, &mh); if (wd->mode == ELM_LIST_LIMIT) - elm_scroller_content_min_limit(wd->scroller, 1, 0); + elm_scroller_content_min_limit(wd->scr, 1, 0); else - elm_scroller_content_min_limit(wd->scroller, 0, 0); + elm_scroller_content_min_limit(wd->scr, 0, 0); _sizing_eval(obj); } +static void +_hold_on(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_push(wd->scr); +} + +static void +_hold_off(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_pop(wd->scr); +} + +static void +_freeze_on(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_push(wd->scr); +} + +static void +_freeze_off(void *data, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + elm_widget_scroll_hold_pop(wd->scr); +} + EAPI Evas_Object * elm_list_add(Evas_Object *parent) { @@ -452,22 +484,26 @@ elm_list_add(Evas_Object *parent) elm_widget_del_hook_set(obj, _del_hook); elm_widget_can_focus_set(obj, 1); - wd->scroller = elm_scroller_add(parent); - elm_widget_resize_object_set(obj, wd->scroller); + wd->scr = elm_scroller_add(parent); + elm_widget_resize_object_set(obj, wd->scr); - elm_scroller_bounce_set(wd->scroller, 0, 1); + elm_scroller_bounce_set(wd->scr, 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); evas_object_size_hint_align_set(wd->box, -1.0, 0.0); - elm_scroller_content_set(wd->scroller, wd->box); + elm_scroller_content_set(wd->scr, wd->box); evas_object_show(wd->box); wd->mode = ELM_LIST_SCROLL; evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); - + evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); + evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + _sizing_eval(obj); return obj; } @@ -555,9 +591,9 @@ elm_list_horizontal_mode_set(Evas_Object *obj, Elm_List_Mode mode) if (wd->mode == mode) return; wd->mode = mode; if (wd->mode == ELM_LIST_LIMIT) - elm_scroller_content_min_limit(wd->scroller, 1, 0); + elm_scroller_content_min_limit(wd->scr, 1, 0); else - elm_scroller_content_min_limit(wd->scroller, 0, 0); + elm_scroller_content_min_limit(wd->scr, 0, 0); } EAPI void @@ -621,7 +657,7 @@ elm_list_item_show(Elm_List_Item *it) evas_object_geometry_get(it->base, &x, &y, &w, &h); x -= bx; y -= by; - elm_scroller_region_show(wd->scroller, x, y, w, h); + elm_scroller_region_show(wd->scr, x, y, w, h); } EAPI void diff --git a/src/lib/els_scroller.c b/src/lib/els_scroller.c index be00f33..29e2249 100644 --- a/src/lib/els_scroller.c +++ b/src/lib/els_scroller.c @@ -305,6 +305,7 @@ _smart_scrollto_x(Smart_Data *sd, double t_in, Evas_Coord pos_x) Evas_Coord px, py, x, y, w, h; double t; + if (sd->freeze) return; if (t_in <= 0.0) { elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); @@ -369,6 +370,7 @@ _smart_scrollto_y(Smart_Data *sd, double t_in, Evas_Coord pos_y) Evas_Coord px, py, x, y, w, h; double t; + if (sd->freeze) return; if (t_in <= 0.0) { elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y); @@ -598,6 +600,7 @@ bounce_eval(Smart_Data *sd) { Evas_Coord mx, my, px, py, bx, by, b2x, b2y; + if (sd->freeze) return; if ((!sd->bouncemex) && (!sd->bouncemey)) return; if (sd->down.now) return; // down bounce while still held down if (sd->down.onhold_animator) @@ -1359,7 +1362,8 @@ _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info) { vel = sqrt((dx * dx) + (dy * dy)) / at; if ((_elm_config->thumbscroll_friction > 0.0) && - (vel > _elm_config->thumbscroll_momentum_threshhold)) + (vel > _elm_config->thumbscroll_momentum_threshhold) && + (!sd->freeze)) { sd->down.dx = ((double)dx / at); sd->down.dy = ((double)dy / at); @@ -1504,7 +1508,7 @@ _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info) } if (faildir) sd->down.dir_none = 1; } - if (!sd->hold) + if ((!sd->hold) && (!sd->freeze)) { if ((sd->down.dragged) || (((x * x) + (y * y)) > -- 2.7.4