elm genlist: Fixed genlist auto scroll bug. Patch by Chanwook Jung <joey.jung@samsung.com>

2011/12/23 Chan-Wook Jung <joey.jung@samsung.com>:
>
> I attached 2nd patch. There are some changes about auto scroll.
> In previous version did not support various bring_in mode in calc_job. So I added scrollto_type value.
> I changed the code to fix this promblem,
> If the bring_in item is in the queue and did not changed pan size, Bring_in function is not working properly.
> When using expandable list, If the last item is in the screen, The last item is located at the bottom and
> If the last item is out of the screen, the expanded_item is located at the top.
>
> Thanks
> Chanwook Jung

SVN revision: 66488
This commit is contained in:
Daniel Juyung Seo 2011-12-24 04:20:18 +00:00
parent 2e8969d27f
commit 57213b618b
2 changed files with 112 additions and 31 deletions

View File

@ -135,6 +135,9 @@ static void _item_move_before(Elm_Gen_Item *it,
Elm_Gen_Item *before);
static void _item_auto_scroll(Widget_Data *wd);
static void _elm_genlist_clear(Evas_Object *obj, Eina_Bool standby);
static void _pan_child_size_get(Evas_Object *obj,
Evas_Coord *w,
Evas_Coord *h);
static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
@ -2283,12 +2286,67 @@ _must_recalc_idler(void *data)
return ECORE_CALLBACK_CANCEL;
}
static void
_scroll_item(Widget_Data *wd)
{
Elm_Genlist_Item *it = NULL;
Evas_Coord gith = 0;
Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
it = wd->show_item;
dx = it->x + it->item->block->x;
dy = it->y + it->item->block->y;
dw = it->item->block->w;
dh = oh;
switch (wd->scrollto_type)
{
case ELM_GENLIST_ITEM_SCROLLTO_TOP:
if (it->item->group_item) gith = it->item->group_item->item->h;
dy -= gith;
break;
case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
dy += (it->item->h / 2 - oh / 2);
break;
case ELM_GENLIST_ITEM_SCROLLTO_IN:
default:
if ((wd->expanded_item) &&
((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
- (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
{
it = wd->expanded_item;
if (it->item->group_item) gith = it->item->group_item->item->h;
dx = it->x + it->item->block->x;
dy = it->y + it->item->block->y - gith;
dw = it->item->block->w;
}
else
{
if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
gith = it->item->group_item->item->h;
dy -= gith;
dh = it->item->h;
}
break;
}
if (wd->bring_in)
elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
else
elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
it->item->showme = EINA_FALSE;
wd->show_item = NULL;
wd->auto_scroll_enabled = EINA_FALSE;
wd->check_scroll = EINA_FALSE;
}
static void
_calc_job(void *data)
{
Widget_Data *wd = data;
Item_Block *itb, *chb = NULL;
Evas_Coord minw = -1, minh = 0, y = 0, ow;
Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0;
Evas_Coord pan_w = 0, pan_h = 0;
int in = 0;
Eina_Bool minw_change = EINA_FALSE;
Eina_Bool did_must_recalc = EINA_FALSE;
@ -2340,26 +2398,7 @@ _calc_job(void *data)
y += itb->h;
in += itb->count;
if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
{
wd->show_item->item->showme = EINA_FALSE;
if (wd->bring_in)
elm_smart_scroller_region_bring_in(wd->scr,
wd->show_item->x +
wd->show_item->item->block->x,
wd->show_item->y +
wd->show_item->item->block->y,
wd->show_item->item->block->w,
wd->show_item->item->h);
else
elm_smart_scroller_child_region_show(wd->scr,
wd->show_item->x +
wd->show_item->item->block->x,
wd->show_item->y +
wd->show_item->item->block->y,
wd->show_item->item->block->w,
wd->show_item->item->h);
wd->show_item = NULL;
}
wd->check_scroll = EINA_TRUE;
}
if (minw_change)
{
@ -2402,6 +2441,30 @@ _calc_job(void *data)
if (!wd->must_recalc_idler)
wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
}
if (wd->check_scroll)
{
_pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
switch (wd->scrollto_type)
{
case ELM_GENLIST_ITEM_SCROLLTO_TOP:
dy = wd->h;
break;
case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
dy = wd->h / 2;
break;
case ELM_GENLIST_ITEM_SCROLLTO_IN:
default:
dy = 0;
break;
}
if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
(pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
{
_scroll_item(wd);
}
}
wd->calc_job = NULL;
evas_object_smart_changed(wd->pan_smart);
evas_event_thaw(evas_object_evas_get(wd->obj));
@ -2959,19 +3022,22 @@ static void
_item_auto_scroll(Widget_Data *wd)
{
if (!wd) return;
Elm_Gen_Item *it;
Eina_List *l;
Evas_Coord ox, oy, ow, oh;
Elm_Gen_Item *tmp_item = NULL;
if ((wd->expanded_item) && (wd->auto_scroll_enabled))
{
evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
if (wd->expanded_item->item->scrl_y > (oh + oy) / 2)
tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
if (!tmp_item) return;
wd->show_item = tmp_item;
wd->bring_in = EINA_TRUE;
wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
{
EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
elm_genlist_item_bring_in(it);
wd->show_item->item->showme = EINA_TRUE;
wd->auto_scroll_enabled = EINA_FALSE;
}
wd->auto_scroll_enabled = EINA_FALSE;
else
_scroll_item(wd);
}
}
@ -4243,6 +4309,7 @@ elm_genlist_item_show(Elm_Gen_Item *it)
{
it->wd->show_item = it;
it->wd->bring_in = EINA_FALSE;
it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
it->item->showme = EINA_TRUE;
return;
}
@ -4285,6 +4352,7 @@ elm_genlist_item_bring_in(Elm_Gen_Item *it)
{
it->wd->show_item = it;
it->wd->bring_in = EINA_TRUE;
it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
it->item->showme = EINA_TRUE;
return;
}
@ -4313,6 +4381,7 @@ elm_genlist_item_top_show(Elm_Gen_Item *it)
{
it->wd->show_item = it;
it->wd->bring_in = EINA_FALSE;
it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
it->item->showme = EINA_TRUE;
return;
}
@ -4341,6 +4410,7 @@ elm_genlist_item_top_bring_in(Elm_Gen_Item *it)
{
it->wd->show_item = it;
it->wd->bring_in = EINA_TRUE;
it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_TOP;
it->item->showme = EINA_TRUE;
return;
}
@ -4368,6 +4438,7 @@ elm_genlist_item_middle_show(Elm_Gen_Item *it)
{
it->wd->show_item = it;
it->wd->bring_in = EINA_FALSE;
it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
it->item->showme = EINA_TRUE;
return;
}
@ -4394,6 +4465,7 @@ elm_genlist_item_middle_bring_in(Elm_Gen_Item *it)
{
it->wd->show_item = it;
it->wd->bring_in = EINA_TRUE;
it->wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_MIDDLE;
it->item->showme = EINA_TRUE;
return;
}

View File

@ -14,6 +14,14 @@ typedef struct Elm_Gen_Item_Type Elm_Gen_Item_Type;
typedef struct Elm_Gen_Item_Tooltip Elm_Gen_Item_Tooltip;
typedef struct _Widget_Data Widget_Data;
typedef enum _Elm_Genlist_Item_Scrollto_Type
{
ELM_GENLIST_ITEM_SCROLLTO_NONE = 0, /**< no scrollto */
ELM_GENLIST_ITEM_SCROLLTO_IN = (1 << 0), /**< show, bring in */
ELM_GENLIST_ITEM_SCROLLTO_TOP = (1 << 1), /**< top show, top bring in */
ELM_GENLIST_ITEM_SCROLLTO_MIDDLE = (1 << 2) /**< middle show, middle bring in */
} Elm_Genlist_Item_Scrollto_Type;
struct Elm_Gen_Item_Tooltip
{
const void *data;
@ -125,7 +133,7 @@ struct _Widget_Data
Eina_Bool multi_timeout : 1;
Eina_Bool multitouched : 1;
Eina_Bool longpressed : 1;
Eina_Bool bring_in : 1;
Eina_Bool bring_in : 1; /* a flag to describe the scroll animation. (show, bring in) */
Eina_Bool compress : 1;
Eina_Bool height_for_width : 1;
Eina_Bool homogeneous : 1;
@ -134,6 +142,7 @@ struct _Widget_Data
Eina_Bool auto_scroll_enabled : 1;
Eina_Bool pan_changed : 1;
Eina_Bool requeued : 1; /* this is set to EINA_TRUE when the item is re-queued. this happens when the item is un-queued but the rel item is still in the queue. this item will be processed later. */
Eina_Bool check_scroll : 1; /* this flag means genlist is supposed to be scrolled. if this flag is set to EINA_TRUE, genlist checks whether it's ok to scroll genlist now or not. */
struct
{
Evas_Coord x, y;
@ -145,9 +154,9 @@ struct _Widget_Data
int max_items_per_block; /* maximum number of items per block */
double longpress_timeout; /* longpress timeout. this value comes from _elm_config by default. this can be changed by elm_genlist_longpress_timeout_set() */
int generation; /* a generation of genlist. when genlist is cleared, this value will be increased and a new generation will start */
Eina_Compare_Cb item_compare_cb;
Eina_Compare_Cb item_compare_data_cb;
Elm_Genlist_Item_Scrollto_Type scrollto_type; /* a scrollto type which remembers where to scroll ex) in, top, middle */
/* The stuff below directly come from gengrid without any thinking */
unsigned int nmax;