sanghyeonlee pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=0496b7988ab8df1c20874ebc81c8ff909aee58e1

commit 0496b7988ab8df1c20874ebc81c8ff909aee58e1
Author: Godly T.Alias <[email protected]>
Date:   Wed Nov 1 16:11:30 2017 +0900

    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 <[email protected]>
    
    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
---
 src/bin/elementary/test_genlist.c       |   7 ++
 src/lib/elementary/elm_genlist.c        | 129 ++++++++++++++++++++++++++++----
 src/lib/elementary/elm_genlist_item.eo  |  17 +++++
 src/lib/elementary/elm_widget_genlist.h |   3 +-
 4 files changed, 142 insertions(+), 14 deletions(-)

diff --git a/src/bin/elementary/test_genlist.c 
b/src/bin/elementary/test_genlist.c
index 2e5c093bd7..789b7b0486 100644
--- a/src/bin/elementary/test_genlist.c
+++ b/src/bin/elementary/test_genlist.c
@@ -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);
 
diff --git a/src/lib/elementary/elm_genlist.c b/src/lib/elementary/elm_genlist.c
index a0706abc2b..19e2a0c02b 100644
--- a/src/lib/elementary/elm_genlist.c
+++ b/src/lib/elementary/elm_genlist.c
@@ -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]);
@@ -2321,6 +2338,33 @@ _reorder_item_space_get(Elm_Gen_Item *it)
 }
 
 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)
 {
    Elm_Gen_Item *it;
@@ -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)
 {
diff --git a/src/lib/elementary/elm_genlist_item.eo 
b/src/lib/elementary/elm_genlist_item.eo
index a8076618a6..28a5beaead 100644
--- a/src/lib/elementary/elm_genlist_item.eo
+++ b/src/lib/elementary/elm_genlist_item.eo
@@ -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;
diff --git a/src/lib/elementary/elm_widget_genlist.h 
b/src/lib/elementary/elm_widget_genlist.h
index 5a1f4e8008..5e81cbe8ac 100644
--- a/src/lib/elementary/elm_widget_genlist.h
+++ b/src/lib/elementary/elm_widget_genlist.h
@@ -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;

-- 


Reply via email to