Efl.Ui.List_View: precise layout async
authorLarry Lira <larry@expertisesolutions.com.br>
Fri, 11 Jan 2019 07:24:14 +0000 (16:24 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Wed, 16 Jan 2019 02:26:52 +0000 (11:26 +0900)
Summary:
fixed precise layouter to work with create asynchronous
fixed example theme signal

Reviewers: cedric, felipealmeida, SanghyeonLee, lauromoura

Reviewed By: SanghyeonLee

Subscribers: #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D7476

src/examples/elementary/efl_ui_list_view_example_1.c
src/lib/elementary/efl_ui_list_view.c
src/lib/elementary/efl_ui_list_view_precise_layouter.c
src/lib/elementary/efl_ui_list_view_precise_layouter.eo
src/lib/elementary/efl_ui_list_view_relayout.eo

index dc30026..e432fe1 100644 (file)
@@ -87,7 +87,7 @@ elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
    );
 
    factory = efl_add(EFL_UI_LAYOUT_FACTORY_CLASS, win);
-   efl_ui_model_connect(factory, "signal/elm,state,%v", "odd_style");
+   efl_ui_model_connect(factory, "signal/efl,state,%v", "odd_style");
    efl_ui_model_connect(factory, "signal/efl,state,%{selected;unselected}", "selected");
    efl_ui_model_connect(factory, "efl.text", "name");
    efl_ui_layout_factory_theme_config(factory, "list_item", NULL, "default");
index a4a9ab9..57ff394 100644 (file)
@@ -32,7 +32,6 @@ static const Evas_Smart_Cb_Description _smart_callbacks[] = {
 
 void _efl_ui_list_view_custom_layout(Efl_Ui_List_View *);
 void _efl_ui_list_view_item_select_set(Efl_Ui_List_View_Layout_Item*, Eina_Bool);
-static void _layout(Efl_Ui_List_View_Data* pd);
 
 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params);
@@ -166,7 +165,7 @@ _on_item_mouse_up(void *data, Evas *evas EINA_UNUSED, Evas_Object *o EINA_UNUSED
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
 
    v = efl_model_property_get(item->children, SELECTED_PROP);
-   if (!eina_value_get(v, &select)) 
+   if (!eina_value_get(v, &select))
      {
         WRN("Could not get the select value");
         eina_value_free(v);
@@ -239,7 +238,11 @@ _efl_ui_list_view_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_List_View_Data *pd, Ei
 EOLIAN static void
 _efl_ui_list_view_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Efl_Ui_List_View_Data *pd)
 {
-   _layout(pd);
+   if (!pd->model)
+     return;
+
+   efl_ui_list_view_relayout_layout_do(pd->relayout, pd->obj, pd->seg_array_first, pd->seg_array);
+
 }
 
 EOLIAN static void
@@ -840,15 +843,6 @@ _efl_ui_list_view_relayout_get(const Eo *obj EINA_UNUSED, Efl_Ui_List_View_Data
    return pd->relayout;
 }
 
-static void
-_layout(Efl_Ui_List_View_Data *pd)
-{
-   if (!pd->model)
-     return;
-
-   efl_ui_list_view_relayout_layout_do(pd->relayout, pd->obj, pd->seg_array_first, pd->seg_array);
-}
-
 static Eina_Value
 _children_slice_then(void * data, const Eina_Value v, const Eina_Future *dead_future EINA_UNUSED)
 {
@@ -946,8 +940,11 @@ _content_created(Eo *obj, void *data, const Eina_Value value)
    evt.layout = item->layout;
    evt.index = efl_ui_list_view_item_index_get(item);
    efl_event_callback_call(obj, EFL_UI_LIST_VIEW_EVENT_ITEM_REALIZED, &evt);
-   efl_ui_focus_composition_dirty(obj);
 
+   tracking->item->layout_request = NULL;
+   efl_ui_list_view_relayout_content_created(tracking->pd->relayout, item);
+
+   efl_ui_focus_composition_dirty(obj);
    evas_object_show(item->layout);
 
    return value;
index 9b6ba9f..156662c 100644 (file)
@@ -22,7 +22,6 @@ typedef struct _Efl_Ui_List_View_Precise_Layouter_Data
 
    unsigned int calc_progress;
 
-   int first;
    int count_total;
 
    Eina_Bool initialized : 1;
@@ -118,21 +117,26 @@ _item_size_calc(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Lay
      }
 }
 
-static void
-_item_min_calc(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Layout_Item* item
-                , Eina_Size2D min, Efl_Ui_List_View_Seg_Array_Node *itemnode)
+static Eina_Size2D
+_item_min_calc(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Layout_Item* item)
 {
-   Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata = itemnode->layout_data;
+   Efl_Ui_List_View_Seg_Array_Node *itemnode = item->tree_node;
+   Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata;
    Efl_Ui_List_View_Layout_Item *layout_item;
    int i, pad[4];
 
-   efl_gfx_size_hint_margin_get(item->layout, &pad[0], &pad[1], &pad[2], &pad[3]);
+   Eina_Size2D min = efl_gfx_size_hint_combined_min_get(item->layout);
 
+   efl_gfx_size_hint_margin_get(item->layout, &pad[0], &pad[1], &pad[2], &pad[3]);
    min.w += pad[0] + pad[1];
    min.h += pad[2] + pad[3];
 
    if (item->min.h == min.h && item->min.w == min.w)
-     return;
+     return min;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(itemnode, min);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(itemnode->layout_data, min);
+   nodedata = itemnode->layout_data;
 
    pd->min.h += min.h - item->min.h;
    nodedata->min.h += min.h - item->min.h;
@@ -175,13 +179,12 @@ _item_min_calc(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Layo
 
    item->min.w = min.w;
    item->min.h = min.h;
-
-   _item_size_calc(pd, item);
+   return item->min;
 }
 
 static void
 _on_item_size_hint_change(void *data, Evas *e EINA_UNUSED,
-                    Evas_Object *obj, void *event_info EINA_UNUSED)
+                    Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Efl_Ui_List_View_Precise_Layouter_Callback_Data *cb_data = data;
    Efl_Ui_List_View_Precise_Layouter_Data *pd = cb_data->pd;
@@ -189,8 +192,7 @@ _on_item_size_hint_change(void *data, Evas *e EINA_UNUSED,
    Efl_Ui_List_View_Seg_Array_Node *node = item->tree_node;
    Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata = node->layout_data;
 
-   Eina_Size2D min = efl_gfx_size_hint_combined_min_get(obj);
-   _item_min_calc(pd, item, min, node);
+   _item_min_calc(pd, item);
    if (!nodedata->realized)
      {
         free(evas_object_event_callback_del(item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change));
@@ -273,17 +275,17 @@ _child_removed_cb(void *data, const Efl_Event *event)
      nodedata->min.w = 0;
 
    for (i = 0; i != itemnode->length; ++i)
-       {
-          layout_item = (Efl_Ui_List_View_Layout_Item *)itemnode->pointers[i];
-          if (nodedata->min.w < layout_item->min.w)
-            nodedata->min.w = layout_item->min.w;
-
-          if (litem->min.w == layout_item->min.w)
-            {
-               nodedata->min.w = layout_item->min.w;
-               break;
-            }
-       }
+     {
+        layout_item = (Efl_Ui_List_View_Layout_Item *)itemnode->pointers[i];
+        if (nodedata->min.w < layout_item->min.w)
+          nodedata->min.w = layout_item->min.w;
+
+        if (litem->min.w == layout_item->min.w)
+          {
+             nodedata->min.w = layout_item->min.w;
+             break;
+          }
+     }
 
    if (pd->min.w == litem->min.w)
      {
@@ -300,9 +302,8 @@ _child_removed_cb(void *data, const Efl_Event *event)
              if (litem->min.w == nodedata2->min.w)
                break;
           }
-       eina_accessor_free(nodes);
+        eina_accessor_free(nodes);
      }
-
    efl_ui_list_view_model_unrealize(pd->modeler, litem);
 
    free(litem);
@@ -391,7 +392,6 @@ static void
 _node_realize(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Seg_Array_Node *node)
 {
    Efl_Ui_List_View_Layout_Item* layout_item;
-   Efl_Ui_List_View_Precise_Layouter_Callback_Data *cb_data;
    Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata = node->layout_data;
    int i;
 
@@ -405,15 +405,6 @@ _node_realize(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Seg_A
      {
        layout_item = (Efl_Ui_List_View_Layout_Item *)node->pointers[i];
        efl_ui_list_view_model_realize(pd->modeler, layout_item);
-
-       if (layout_item->layout)
-         {
-            cb_data = calloc(1, sizeof(Efl_Ui_List_View_Precise_Layouter_Callback_Data));
-            cb_data->pd = pd;
-            cb_data->item = layout_item;
-            evas_object_event_callback_add(layout_item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change, cb_data);
-            _item_size_calc(pd, layout_item);
-         }
      }
 }
 
@@ -438,8 +429,8 @@ _node_unrealize(Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Seg
          {
             cb_data = evas_object_event_callback_del(layout_item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change);
             free(cb_data);
+            efl_ui_list_view_model_unrealize(pd->modeler, layout_item);
          }
-       efl_ui_list_view_model_unrealize(pd->modeler, layout_item);
      }
 }
 
@@ -485,8 +476,8 @@ _calc_size_job(void *data)
    Efl_Ui_List_View_Precise_Layouter_Data *pd;
    Efl_Ui_List_View_Seg_Array_Node *node;
    Efl_Ui_List_View_Layout_Item *layout_item;
+   Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata;
    Eo *obj = data;
-   Eina_Size2D min;
    int i;
    double start_time = ecore_time_get();
 
@@ -501,52 +492,36 @@ _calc_size_job(void *data)
         if (!node->layout_data)
           node->layout_data = calloc(1, sizeof(Efl_Ui_List_View_Precise_Layouter_Node_Data));
 
+        nodedata = node->layout_data;
+        if (pd->calc_progress == 1)
+          nodedata->realized = EINA_TRUE;
+
         for (i = 0; i != node->length; ++i)
           {
             layout_item = (Efl_Ui_List_View_Layout_Item *)node->pointers[i];
             EINA_SAFETY_ON_NULL_RETURN(layout_item);
 
             // cache size of new items
-            if ((layout_item->min.w == 0) && (layout_item->min.h == 0))
-              {
-                if (!layout_item->layout)
-                  {
-                    efl_ui_list_view_model_realize(pd->modeler, layout_item);
-                  }
-
-                min = efl_gfx_size_hint_combined_min_get(layout_item->layout);
-                if (min.w && min.h)
-                  {
-                    _item_min_calc(pd, layout_item, min, node);
-                    efl_ui_list_view_model_unrealize(pd->modeler, layout_item);
-                  }
-                else
-                  {
-                     Efl_Ui_List_View_Precise_Layouter_Callback_Data *cb_data = calloc(1, sizeof(Efl_Ui_List_View_Precise_Layouter_Callback_Data));
-                     cb_data->pd = pd;
-                     cb_data->item = layout_item;
-                     evas_object_event_callback_add(layout_item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change, cb_data);
-                  }
-              }
+            if ((layout_item->min.w == 0) && (layout_item->min.h == 0) && (!layout_item->layout))
+              efl_ui_list_view_model_realize(pd->modeler, layout_item);
           }
+
         if ( (ecore_time_get() - start_time ) > 0.01 )
           {
             ecore_job_del(pd->calc_job);
             pd->calc_job = ecore_job_add(_calc_size_job, obj);
             eina_accessor_free(nodes);
             return;
-         }
+          }
      }
    eina_accessor_free(nodes);
    pd->calc_progress = 0;
    pd->calc_job = NULL;
    pd->recalc = EINA_FALSE;
-
-   evas_object_smart_changed(pd->modeler);
 }
 
 EOLIAN static Efl_Object *
-_efl_ui_list_view_precise_layouter_efl_object_constructor(Eo *obj EINA_UNUSED, Efl_Ui_List_View_Precise_Layouter_Data *pd)
+_efl_ui_list_view_precise_layouter_efl_object_constructor(Eo *obj, Efl_Ui_List_View_Precise_Layouter_Data *pd)
 {
    obj = efl_constructor(efl_super(obj, MY_CLASS));
    pd->initialized = EINA_FALSE;
@@ -554,6 +529,31 @@ _efl_ui_list_view_precise_layouter_efl_object_constructor(Eo *obj EINA_UNUSED, E
    return obj;
 }
 
+EOLIAN static void
+_efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_content_created(Eo *obj EINA_UNUSED, Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Ui_List_View_Layout_Item *item)
+{
+   Efl_Ui_List_View_Precise_Layouter_Callback_Data *cb_data;
+   EINA_SAFETY_ON_NULL_RETURN(item);
+   EINA_SAFETY_ON_NULL_RETURN(item->layout);
+   Efl_Ui_List_View_Seg_Array_Node *node = item->tree_node;
+   Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata = node->layout_data;
+
+   Eina_Size2D min = _item_min_calc(pd, item);
+
+   if (min.w && min.h && !nodedata->realized)
+     {
+        efl_ui_list_view_model_unrealize(pd->modeler, item);
+        return;
+     }
+
+   cb_data = calloc(1, sizeof(Efl_Ui_List_View_Precise_Layouter_Callback_Data));
+   cb_data->pd = pd;
+   cb_data->item = item;
+   evas_object_event_callback_add(item->layout, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_item_size_hint_change, cb_data);
+
+   _item_size_calc(pd, item);
+}
+
 EOLIAN static Eina_List *
 _efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_elements_get(const Eo *obj EINA_UNUSED, Efl_Ui_List_View_Precise_Layouter_Data *pd)
 {
@@ -569,7 +569,7 @@ _efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_elements_get(const
         if (!nodedata || !nodedata->realized)
             continue;
 
-        for(j = 0; j != items_node->length;++j)
+        for (j = 0; j != items_node->length;++j)
           {
              layout_item = (Efl_Ui_List_View_Layout_Item *)items_node->pointers[j];
              if (layout_item->layout)
@@ -582,7 +582,7 @@ _efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_elements_get(const
 }
 
 EOLIAN static void
-_efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_model_set(Eo *obj EINA_UNUSED, Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Model *model)
+_efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_model_set(Eo *obj, Efl_Ui_List_View_Precise_Layouter_Data *pd, Efl_Model *model)
 {
    _finalize(obj, pd);
 
@@ -607,11 +607,11 @@ _efl_ui_list_view_relayout_layout_do(Efl_Ui_List_View_Precise_Layouter_Data *pd)
    Efl_Ui_List_View_Layout_Item* layout_item;
    Efl_Ui_List_View_Seg_Array_Node *items_node;
    int i, j = 0;
+   int boxx, boxy, boxw, boxh, extra = 0, rounding = 0;
+   int boxl = 0, boxr = 0, boxt = 0, boxb = 0;
 
    _calc_range(pd);
 
-   int boxx, boxy, boxw, boxh, extra = 0, rounding = 0;
-   int boxl = 0, boxr = 0, boxt = 0, boxb = 0;
    evas_object_geometry_get(pd->modeler, &boxx, &boxy, &boxw, &boxh);
    efl_gfx_size_hint_margin_get(pd->modeler, &boxl, &boxr, &boxt, &boxb);
 
@@ -621,13 +621,6 @@ _efl_ui_list_view_relayout_layout_do(Efl_Ui_List_View_Precise_Layouter_Data *pd)
    boxx += boxl;
    boxy += boxt;
 
-    //padding can not be squeezed (note: could make it an option)
-//   int pad;
-//   double scale;
-//   scale = evas_object_scale_get(pd->modeler);
-//   pad = 0;//pd->pad.scalable ? (pd->pad.v * scale) : pd->pad.v;
-//   length -= pad * (pd->count_total - 1);
-
    // available space. if <0 we overflow
    extra = boxh - pd->min.h;
    if (extra < 0) extra = 0;
@@ -641,46 +634,50 @@ _efl_ui_list_view_relayout_layout_do(Efl_Ui_List_View_Precise_Layouter_Data *pd)
    EINA_ACCESSOR_FOREACH(nodes, i, items_node)
      {
         Efl_Ui_List_View_Precise_Layouter_Node_Data *nodedata = items_node->layout_data;
-        if (!nodedata)
+        if (!items_node->layout_data)
+          continue;
+
+        if (!nodedata->realized)
           {
-            continue;
+             cur_pos += nodedata->min.h;
+             continue;
           }
 
-        if (nodedata->realized)
+        for (j = 0; j != items_node->length;++j)
           {
-             for(j = 0; j != items_node->length;++j)
+             layout_item = (Efl_Ui_List_View_Layout_Item *)items_node->pointers[j];
+             double x, y, w, h;
+             double weight_x, weight_y;
+             if (!(layout_item->min.w && layout_item->min.h))
+               continue;
+
+             // extra rounding up (compensate cumulative error)
+             if ((i == (pd->count_total - 1)) && (cur_pos - floor(cur_pos) >= 0.5))
+               rounding = 1;
+
+             if (layout_item->layout)
                {
-                  layout_item = (Efl_Ui_List_View_Layout_Item *)items_node->pointers[j];
-                  double x, y, w, h;
-                  double weight_x, weight_y;
-
-                  if (layout_item->min.w && layout_item->min.h)
-                    {
-                       assert(layout_item->layout != NULL);
-                       if (pd->resize)
-                         _item_size_calc(pd, layout_item);
-
-                       efl_gfx_size_hint_weight_get(layout_item->layout, &weight_x, &weight_y);
-                       // extra rounding up (compensate cumulative error)
-                       if ((i == (pd->count_total - 1)) && (cur_pos - floor(cur_pos) >= 0.5))
-                         rounding = 1;
-
-                       x = layout_item->pos.x;
-                       y = layout_item->pos.y + cur_pos;
-                       w = layout_item->size.w;
-                       h = layout_item->size.h + rounding + weight_y * extra;
-                       cur_pos += h;
-
-                       if (w < pd->min.w) w = pd->min.w;
-                       if (w > vgmt.w) w = vgmt.w;
-
-                       evas_object_geometry_set(layout_item->layout, (x + 0 - spos.x), (y + 0 - spos.y), w, h);
-                    }
+                  if (pd->resize)
+                    _item_size_calc(pd, layout_item);
+
+                  efl_gfx_size_hint_weight_get(layout_item->layout, &weight_x, &weight_y);
                }
-          }
-        else
-          {
-             cur_pos += nodedata->min.h;
+             else
+               {
+                  cur_pos += layout_item->size.h;
+                  continue;
+               }
+
+             x = layout_item->pos.x;
+             y = layout_item->pos.y + cur_pos;
+             w = layout_item->size.w;
+             h = layout_item->size.h + rounding + weight_y * extra;
+             cur_pos += h;
+
+             if (w < pd->min.w) w = pd->min.w;
+             if (w > vgmt.w) w = vgmt.w;
+
+             evas_object_geometry_set(layout_item->layout, (x + 0 - spos.x), (y + 0 - spos.y), w, h);
           }
      }
    eina_accessor_free(nodes);
@@ -691,18 +688,15 @@ _efl_ui_list_view_relayout_layout_do(Efl_Ui_List_View_Precise_Layouter_Data *pd)
 EOLIAN static void
 _efl_ui_list_view_precise_layouter_efl_ui_list_view_relayout_layout_do
   (Eo *obj EINA_UNUSED, Efl_Ui_List_View_Precise_Layouter_Data *pd
-   , Efl_Ui_List_View_Model *modeler, int first, Efl_Ui_List_View_Seg_Array *seg_array)
+   , Efl_Ui_List_View_Model *modeler, int first EINA_UNUSED, Efl_Ui_List_View_Seg_Array *seg_array)
 {
    if (!_initilize(obj, pd, modeler, seg_array) || !pd->seg_array)
      return;
 
-   pd->first = first;
-
-   if (pd->recalc && efl_ui_list_view_seg_array_count(seg_array) > 0)
+   if (!pd->calc_job && pd->recalc && efl_ui_list_view_seg_array_count(seg_array) > 0)
      {
         // cache size of new items
         pd->calc_progress = 0;
-        ecore_job_del(pd->calc_job);
         pd->calc_job = ecore_job_add(_calc_size_job, obj);
         return;
      }
index 9f953aa..9100f69 100644 (file)
@@ -3,6 +3,7 @@ class Efl.Ui.List_View_Precise_Layouter (Efl.Object, Efl.Ui.List_View_Relayout)
    implements {
       Efl.Object.constructor;
       Efl.Ui.List_View_Relayout.layout_do;
+      Efl.Ui.List_View_Relayout.content_created;
       Efl.Ui.List_View_Relayout.model { set; }
       Efl.Ui.List_View_Relayout.elements { get; }
    }
index ac6cd78..e5359b7 100644 (file)
@@ -8,6 +8,11 @@ interface Efl.Ui.List_View_Relayout (Efl.Interface)
             children: Efl.Ui.List_View_Seg_Array;
          }
       }
+      content_created {
+         params {
+            item: ptr(Efl.Ui.List_View_Layout_Item);
+         }
+      }
       @property model {
          [[Model that is/will be ]]
          set {}