Genlist Item Pin Feature

Summary:
**@feature** T6241

This feature enables genlist to pin an item to viewport which will
be available always for user to view/select.

**Use Case**:
In a big list of music, most times when user finds a song which they
like, before playing that they may want to go through the entire list
to check whether there is some other good songs, but
after seeing the entire list user have to again scroll back to the
position of item which they liked to play it then.
In this case item pinning can be used, so that the item
which they want to keep for future selection can be pinned
and then it will remain in viewport, finally when user want to do
operation on item, it will be readily available in viewport.

Signed-off-by: Godly T.Alias <godlytalias@yahoo.co.in>

Test Plan: Elementary Test -> Genlist -> Double click on items to enable/disable pinning

Reviewers: raster, cedric, prince.dubey, SanghyeonLee

Subscribers: rajeshps, jpeg, shilpasingh

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D5340
This commit is contained in:
Godly T.Alias 2017-11-01 16:11:30 +09:00 committed by SangHyeon Jade Lee
parent 9d946fa839
commit 0496b7988a
4 changed files with 142 additions and 14 deletions

View File

@ -287,6 +287,11 @@ static void
_gl_double_clicked(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
printf("double clicked: %p\n", event_info);
Elm_Object_Item *it = event_info;
if (!elm_genlist_item_pin_get(it))
elm_genlist_item_pin_set(it, EINA_TRUE);
else
elm_genlist_item_pin_set(it, EINA_FALSE);
}
static void
@ -750,6 +755,7 @@ test_genlist2(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_
evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
api->gl = gl;
evas_object_smart_callback_add(gl, "clicked,double", _gl_double_clicked, NULL);
evas_object_show(gl);
api->itc1 = elm_genlist_item_class_new();
@ -2439,6 +2445,7 @@ test_genlist_reorder(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
elm_object_text_set(tg, "Reorder Mode:");
elm_check_state_set(tg, elm_config_mirrored_get());
evas_object_smart_callback_add(tg, "changed", _reorder_tg_changed_cb, gl);
evas_object_smart_callback_add(gl, "clicked,double", _gl_double_clicked, NULL);
elm_box_pack_end(bx, tg);
evas_object_show(tg);

View File

@ -717,7 +717,7 @@ _item_block_unrealize(Item_Block *itb)
dragging = EINA_TRUE;
it->want_unrealize = EINA_TRUE;
}
else
else if (it != itb->sd->pin_item)
_elm_genlist_item_unrealize(it, EINA_FALSE);
}
}
@ -2202,6 +2202,7 @@ _group_items_recalc(void *data)
Eina_List *l;
Elm_Gen_Item *git;
Elm_Genlist_Data *sd = data;
Evas_Coord vy;
evas_event_freeze(evas_object_evas_get(sd->obj));
EINA_LIST_FOREACH(sd->group_items, l, git)
@ -2209,6 +2210,22 @@ _group_items_recalc(void *data)
if (git->item->want_realize)
{
if (!git->realized) _item_realize(git, git->item->order_num_in, EINA_FALSE);
if (sd->pin_item && git == sd->pin_item->item->group_item &&
sd->pin_item->item->scrl_y <= (git->item->scrl_y + git->item->h))
{
elm_interface_scrollable_content_viewport_geometry_get
(sd->obj, NULL, &vy, NULL, NULL);
if ((git->item->scrl_y + git->item->h) > vy)
{
sd->pin_item->item->scrl_y = git->item->scrl_y + git->item->h;
evas_object_move(VIEW(sd->pin_item),
sd->pin_item->item->scrl_x, sd->pin_item->item->scrl_y);
}
}
else if (sd->pin_item && sd->pin_item_top && git != sd->pin_item->item->group_item &&
(git->item->scrl_y < (sd->pin_item->item->scrl_y + sd->pin_item->item->h)))
git->item->scrl_y = sd->pin_item->item->scrl_y + sd->pin_item->item->h;
evas_object_resize(VIEW(git), sd->minw, git->item->h);
evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
evas_object_stack_above(VIEW(git), sd->stack[1]);
@ -2320,6 +2337,33 @@ _reorder_item_space_get(Elm_Gen_Item *it)
return 0;
}
static void
_pin_item_recalc(Elm_Gen_Item *it)
{
Evas_Coord vx, vy, vw, vh;
ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
sd->pin_item_top = EINA_FALSE;
elm_interface_scrollable_content_viewport_geometry_get
(sd->obj, &vx, &vy, &vw, &vh);
if (it->item->scrl_x < vx)
it->item->scrl_x = vx;
else if (it->item->scrl_x + it->item->w > vx + vw)
it->item->scrl_x = vx + vw - it->item->w;
if (it->item->scrl_y < vy)
{
sd->pin_item_top = EINA_TRUE;
it->item->scrl_y = vy;
}
else if (it->item->scrl_y + it->item->h > vy + vh)
it->item->scrl_y = vy + vh - it->item->h;
evas_object_resize(VIEW(it), it->item->w, it->item->h);
evas_object_move(VIEW(it), it->item->scrl_x, it->item->scrl_y);
evas_object_show(VIEW(it));
}
static void
_item_block_position(Item_Block *itb, const int blk_idx)
{
@ -2429,7 +2473,7 @@ _item_block_position(Item_Block *itb, const int blk_idx)
}
else
{
if (!sd->tree_effect_animator)
if (!sd->tree_effect_animator && (it != sd->pin_item))
_elm_genlist_item_unrealize(it, EINA_FALSE);
}
}
@ -2440,7 +2484,11 @@ _item_block_position(Item_Block *itb, const int blk_idx)
}
y += it->item->h;
vis_count++;
if (it == sd->pin_item)
_pin_item_recalc(it);
}
evas_event_thaw(evas_object_evas_get((itb->sd)->obj));
evas_event_thaw_eval(evas_object_evas_get((itb->sd)->obj));
}
@ -2527,6 +2575,15 @@ _elm_genlist_pan_efl_canvas_group_group_calculate(Eo *obj, Elm_Genlist_Pan_Data
else
{
if (itb->realized) _item_block_unrealize(itb);
if (sd->pin_item && itb == sd->pin_item->item->block)
{
if (!sd->pin_item->realized)
_item_realize(sd->pin_item, sd->pin_item->item->order_num_in, EINA_FALSE);
sd->pin_item->item->w = itb->w;
sd->pin_item->item->scrl_x = itb->x - sd->pan_x + ox;
sd->pin_item->item->scrl_y = itb->y - sd->pan_y + oy;
_pin_item_recalc(sd->pin_item);
}
}
in += itb->vis_count;
}
@ -2566,6 +2623,8 @@ _elm_genlist_pan_efl_canvas_group_group_calculate(Eo *obj, Elm_Genlist_Pan_Data
if (git->realized) evas_object_raise(VIEW(git));
}
if (sd->pin_item)
evas_object_raise(VIEW(sd->pin_item));
//update item before the render to prevent delayed update by job.
if (sd->update_job)
{
@ -2746,18 +2805,21 @@ _elm_genlist_item_focused(Elm_Object_Item *eo_it)
(elm_wdg_item_disabled_get(eo_it)))
return;
switch (_elm_config->focus_autoscroll_mode)
if (it != sd->pin_item)
{
case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
elm_genlist_item_show(eo_it,
ELM_GENLIST_ITEM_SCROLLTO_IN);
break;
case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
elm_genlist_item_bring_in(eo_it,
ELM_GENLIST_ITEM_SCROLLTO_IN);
break;
default:
break;
switch (_elm_config->focus_autoscroll_mode)
{
case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
elm_genlist_item_show(eo_it,
ELM_GENLIST_ITEM_SCROLLTO_IN);
break;
case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
elm_genlist_item_bring_in(eo_it,
ELM_GENLIST_ITEM_SCROLLTO_IN);
break;
default:
break;
}
}
sd->focused_item = eo_it;
@ -3438,6 +3500,8 @@ _item_highlight(Elm_Gen_Item *it)
else evas_object_stack_below(VIEW(it), sd->stack[1]);
if ((it->item->group_item) && (it->item->group_item->realized))
evas_object_stack_above(it->item->VIEW(group_item), sd->stack[1]);
if (sd->pin_item && sd->pin_item->realized)
evas_object_stack_above(VIEW(sd->pin_item), sd->stack[1]);
}
it->highlighted = EINA_TRUE;
}
@ -3696,6 +3760,7 @@ _item_del(Elm_Gen_Item *it)
}
elm_genlist_item_subitems_clear(EO_OBJ(it));
if (sd->show_item == it) sd->show_item = NULL;
if (sd->pin_item == it) sd->pin_item = NULL;
if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
if (it->item->decorate_all_item_realized) _decorate_all_item_unrealize(it);
if (it->item->block) _item_block_del(it);
@ -5587,6 +5652,8 @@ _elm_genlist_efl_canvas_group_group_add(Eo *obj, Elm_Genlist_Data *priv)
priv->item_cache_max = priv->max_items_per_block * 2;
priv->longpress_timeout = _elm_config->longpress_timeout;
priv->highlight = EINA_TRUE;
priv->pin_item = NULL;
priv->pin_item_top = EINA_FALSE;
priv->pan_obj = efl_add(MY_PAN_CLASS, evas_object_evas_get(obj));
pan_data = efl_data_scope_get(priv->pan_obj, MY_PAN_CLASS);
@ -7999,6 +8066,7 @@ _elm_genlist_reorder_mode_set(Eo *obj EINA_UNUSED, Elm_Genlist_Data *sd, Eina_Bo
Elm_Object_Item *eo_it;
if (sd->reorder_mode == !!reorder_mode) return;
if (sd->pin_item) elm_genlist_item_pin_set(EO_OBJ(sd->pin_item), EINA_FALSE);
sd->reorder_mode = !!reorder_mode;
realized = elm_genlist_realized_items_get(obj);
EINA_LIST_FREE(realized, eo_it)
@ -8039,6 +8107,41 @@ _elm_genlist_item_type_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
return it->item->type;
}
EOLIAN static void
_elm_genlist_item_pin_set(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it, Eina_Bool pin)
{
ELM_GENLIST_ITEM_CHECK_OR_RETURN(it);
ELM_GENLIST_DATA_GET(WIDGET(it), sd);
if (sd->reorder_mode) return;
if (it->item->type & ELM_GENLIST_ITEM_GROUP) return;
if (pin ^ (sd->pin_item == it))
{
if (sd->pin_item)
{
if (sd->pin_item->item->block)
sd->pin_item->item->block->realized = EINA_TRUE;
evas_object_smart_changed(sd->pan_obj);
}
if (pin)
sd->pin_item = it;
else
sd->pin_item = NULL;
}
}
EOLIAN static Eina_Bool
_elm_genlist_item_pin_get(Eo *eo_it EINA_UNUSED, Elm_Gen_Item *it)
{
ELM_GENLIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
ELM_GENLIST_DATA_GET(WIDGET(it), sd);
if (sd->pin_item == it)
return EINA_TRUE;
else
return EINA_FALSE;
}
EAPI Elm_Genlist_Item_Class *
elm_genlist_item_class_new(void)
{

View File

@ -270,6 +270,23 @@ class Elm.Genlist.Item(Elm.Widget.Item)
type: Elm.Genlist.Item.Type(Elm.Genlist.Item.Type.max); [[Item type.]]
}
}
@property pin {
get {
[[Get whether a given genlist item is pinned or not.]]
}
set {
[[Set whether a given genlist item is pinned or not
This sets a genlist item as pinned so that it will be always available in
the viewport available for user interaction. Group items cannot be pinned.
Also when a new item is pinned, the current pinned item will get unpinned.
Item pinning cannot be done in reorder mode too.
]]
}
values {
pin: bool; [[The item pin state state ($true pin item, $false unpin item).]]
}
}
/* init { FIXME
params {
Evas_Smart_Cb func;

View File

@ -89,7 +89,7 @@ struct _Elm_Genlist_Data
Ecore_Idler *must_recalc_idler;
Eina_List *queue;
Elm_Gen_Item *show_item, *anchor_item, *mode_item,
*reorder_rel, *expanded_item;
*reorder_rel, *expanded_item, *pin_item;
Eina_Inlist *item_cache; /* an inlist of
* edje object it
* cache. */
@ -201,6 +201,7 @@ struct _Elm_Genlist_Data
Eina_Bool item_looping_on : 1;
Eina_Bool tree_effect_animator : 1;
Eina_Bool pin_item_top : 1;
};
typedef struct _Item_Block Item_Block;