fix scroll freeze and propagate to built-in scrollers. also genlist now knows

about dragging items. callbacks for that.



SVN revision: 42342
This commit is contained in:
Carsten Haitzler 2009-09-08 06:20:32 +00:00
parent fa8fac0c23
commit 3167305fa7
5 changed files with 219 additions and 20 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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)) >