[elm_genlist] add zoom effect while item is added or deleted.
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
index 309cdc2..616dd88 100644 (file)
@@ -22,7 +22,8 @@ EAPI const char ELM_GENLIST_PAN_SMART_NAME[] = "elm_genlist_pan";
 #define GL_IT(_it) (_it->item)
 
 #define IS_ROOT_PARENT_IT(_it) \
-   ((_it->group) || (GL_IT(_it)->items && GL_IT(_it)->expanded_depth == 0)) \
+   ((_it->group) || ((GL_IT(_it)->items && GL_IT(_it)->expanded_depth == 0)  \
+                      &&(!(GL_IT(_it)->type & ELM_GENLIST_ITEM_TREE)))) \
 
 static const Evas_Smart_Interface *_smart_interfaces[] =
 {
@@ -144,15 +145,16 @@ static void _item_select(Elm_Gen_Item *it);
 static void     _expand_toggle_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__);
 static void     _expand_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__);
 static void     _contract_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__);
-static void _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *ic);
+static void _elm_genlist_item_state_update(Elm_Gen_Item *it);
 static void _decorate_item_unrealize(Elm_Gen_Item *it);
 static void _decorate_all_item_unrealize(Elm_Gen_Item *it);
 static void _decorate_item_set(Elm_Gen_Item *it);
+static void _changed_job(Elm_Genlist_Smart_Data *sd);
 
 #if GENLIST_FX_SUPPORT
 static Eina_Bool      _elm_genlist_fx_capture(Evas_Object *obj, int level);
 static void           _elm_genlist_fx_play(Evas_Object *obj);
-static void           _elm_genlist_fx_clear(Evas_Object *obj);
+static void           _elm_genlist_fx_clear(Evas_Object *obj, Eina_Bool force);
 static void           _elm_genlist_proxy_item_del(const Elm_Object_Item *item);
 #endif
 
@@ -185,10 +187,6 @@ _item_cache_push(Elm_Gen_Item *it)
    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
    Item_Cache *ic = NULL;
 
-#if GENLIST_FX_SUPPORT
-   if (sd->pending_del_items) return;
-#endif
-
    if (sd->item_cache_count >= sd->item_cache_max)
     {
         ic = EINA_INLIST_CONTAINER_GET(sd->item_cache->last, Item_Cache);
@@ -218,7 +216,11 @@ _item_cache_push(Elm_Gen_Item *it)
                                         _contract_signal_cb, it);
    _item_mouse_callbacks_del(it, VIEW(it));
 
+#if GENLIST_FX_SUPPORT
+   if ((it->item->nocache_once) || (it->item->nocache) || (sd->pending_del_items))
+#else
    if ((it->item->nocache_once) || (it->item->nocache))
+#endif
      {
         if (VIEW(it)) evas_object_del(VIEW(it));
         if (it->spacer) evas_object_del(it->spacer);
@@ -455,42 +457,27 @@ _elm_genlist_pan_smart_move(Evas_Object *obj,
 }
 
 static void
-_elm_genlist_pan_smart_resize_job(void *data)
-{
-   Elm_Genlist_Pan_Smart_Data *psd = data;
-
-   elm_layout_sizing_eval(ELM_WIDGET_DATA(psd->wsd)->obj);
-   psd->resize_job = NULL;
-}
-
-static void
 _elm_genlist_pan_smart_resize(Evas_Object *obj,
                               Evas_Coord w,
                               Evas_Coord h)
 {
-   Evas_Coord ow, oh;
+   Evas_Coord ow = 0, oh = 0, vw = 0;
 
    ELM_GENLIST_PAN_DATA_GET(obj, psd);
 
    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
    if ((ow == w) && (oh == h)) return;
-   if ((psd->wsd->mode == ELM_LIST_COMPRESS) && (ow != w))
-     {
-        /* fix me later */
-        if (psd->resize_job) ecore_job_del(psd->resize_job);
-        psd->resize_job =
-          ecore_job_add(_elm_genlist_pan_smart_resize_job, psd);
-     }
+
+   psd->wsd->s_iface->content_viewport_size_get(ELM_WIDGET_DATA(psd->wsd)->obj,
+                                                &vw, NULL);
+   if (psd->wsd->mode == ELM_LIST_COMPRESS &&
+       vw != psd->wsd->prev_viewport_w)
+     psd->wsd->size_changed = EINA_TRUE;
+   if (vw != 0) psd->wsd->prev_viewport_w = vw;
+
    psd->wsd->pan_changed = EINA_TRUE;
-   evas_object_smart_changed(obj);
    if (psd->wsd->calc_job) ecore_job_del(psd->wsd->calc_job);
-   // if the widht changed we may have to resize content if scrollbar went
-   // away or appesared to queue a job to deal with it. it should settle in
-   // the end to a steady-state
-   if (ow != w)
-     psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wsd);
-   else
-     psd->wsd->calc_job = NULL;
+   psd->wsd->calc_job = ecore_job_add(_calc_job, psd->wsd);
 }
 
 static void
@@ -632,6 +619,12 @@ _item_unrealize(Elm_Gen_Item *it,
    _decorate_item_unrealize(it);
    _decorate_all_item_unrealize(it);
 
+   edje_object_signal_emit
+     (VIEW(it), "elm,state,decorate,disabled", "elm");
+   edje_object_signal_emit
+     (VIEW(it), "elm,state,reorder,mode_unset", "elm");
+   edje_object_message_signal_process(VIEW(it));
+
    it->realized = EINA_FALSE;
    _item_cache_push(it);
 
@@ -698,13 +691,9 @@ _calc_job(void *data)
    Elm_Genlist_Smart_Data *sd = data;
    Eina_Bool minw_change = EINA_FALSE;
    Eina_Bool did_must_recalc = EINA_FALSE;
-   Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw = 0;
+   Evas_Coord minw = -1, minh = 0, y = 0, dy = 0, vw = 0;
 
-   evas_object_geometry_get(sd->pan_obj, NULL, NULL, &ow, &sd->h);
-   if (sd->mode == ELM_LIST_COMPRESS)
-     sd->s_iface->content_viewport_size_get(ELM_WIDGET_DATA(sd)->obj, &vw, NULL);
-
-   if (sd->w != ow) sd->w = ow;
+   sd->s_iface->content_viewport_size_get(ELM_WIDGET_DATA(sd)->obj, &sd->w, &sd->h);
 
    //evas_event_freeze(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
    EINA_INLIST_FOREACH(sd->blocks, itb)
@@ -846,51 +835,25 @@ _calc_job(void *data)
 static void
 _elm_genlist_smart_sizing_eval(Evas_Object *obj)
 {
-   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
-   Evas_Coord vmw = 0, vmh = 0;
+   Evas_Coord minw = 0, minh = 0, maxw = -1, maxh = -1, vw = 0;
 
    ELM_GENLIST_DATA_GET(obj, sd);
 
    /* parent class' early call */
    if (!sd->s_iface) return;
-
    if (sd->on_sub_del) return;;
 
    evas_object_size_hint_min_get(obj, &minw, NULL);
    evas_object_size_hint_max_get(obj, &maxw, &maxh);
+   edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh);
 
-   edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &vmw, &vmh);
+   sd->s_iface->content_viewport_size_get(obj, &vw, NULL);
+   if (vw != 0) sd->prev_viewport_w = vw;
 
-   if (sd->mode == ELM_LIST_COMPRESS)
-     {
-        Evas_Coord vw, vh;
-
-        sd->s_iface->content_viewport_size_get(obj, &vw, &vh);
-        if ((vw != 0) && (vw != sd->prev_viewport_w))
-          {
-             Item_Block *itb;
-
-             sd->prev_viewport_w = vw;
-
-             EINA_INLIST_FOREACH(sd->blocks, itb)
-               {
-                  itb->must_recalc = EINA_TRUE;
-               }
-             if (sd->calc_job) ecore_job_del(sd->calc_job);
-             sd->calc_job = ecore_job_add(_calc_job, sd);
-          }
-        minw = vmw;
-        minh = vmh;
-     }
-   else if (sd->mode == ELM_LIST_LIMIT)
+   if (sd->mode == ELM_LIST_LIMIT)
      {
         maxw = -1;
-        minw = vmw + sd->realminw;
-     }
-   else
-     {
-        minw = vmw;
-        minh = vmh;
+        minw = minw + sd->realminw;
      }
 
    evas_object_size_hint_min_set(obj, minw, minh);
@@ -915,7 +878,7 @@ _item_position(Elm_Gen_Item *it,
 }
 
 static void
-_item_subitems_clear(Elm_Gen_Item *it)
+_item_sub_items_clear(Elm_Gen_Item *it)
 {
    Eina_List *l, *ll;
    Elm_Object_Item *it2;
@@ -999,65 +962,30 @@ _item_order_update(const Eina_Inlist *l,
 }
 
 static void
-_elm_genlist_item_state_update(Elm_Gen_Item *it,
-                               Item_Cache *itc)
+_elm_genlist_item_state_update(Elm_Gen_Item *it)
 {
-   if (itc)
+   if (it->selected)
      {
-        if (it->selected != itc->selected)
-          {
-             if (it->selected)
-               {
-                  if (it->deco_all_view)
-                    edje_object_signal_emit
-                      (it->deco_all_view, "elm,state,selected", "elm,nosound");
-                  edje_object_signal_emit
-                    (VIEW(it), "elm,state,selected", "elm,nosound");
-                  evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
-               }
-          }
-        if (elm_widget_item_disabled_get(it) != itc->disabled)
-          {
-             if (elm_widget_item_disabled_get(it))
-               edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
-             if (it->deco_all_view)
-               edje_object_signal_emit
-                 (it->deco_all_view, "elm,state,disabled", "elm");
-          }
-        if (it->item->expanded != itc->expanded)
-          {
-             if (it->item->expanded)
-               edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
-             if (it->deco_all_view)
-               edje_object_signal_emit
-                 (it->deco_all_view, "elm,state,expanded", "elm");
-          }
+        if (it->deco_all_view)
+           edje_object_signal_emit
+              (it->deco_all_view, "elm,state,selected", "elm");
+        edje_object_signal_emit
+           (VIEW(it), "elm,state,selected", "elm");
+        evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
      }
-   else
+   if (elm_widget_item_disabled_get(it))
      {
-        if (it->selected)
-          {
-             if (it->deco_all_view)
-               edje_object_signal_emit
-                 (it->deco_all_view, "elm,state,selected", "elm,nosound");
-             edje_object_signal_emit
-               (VIEW(it), "elm,state,selected", "elm,nosound");
-             evas_object_smart_callback_call(WIDGET(it), SIG_HIGHLIGHTED, it);
-          }
-        if (elm_widget_item_disabled_get(it))
-          {
-             edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
-             if (it->deco_all_view)
-               edje_object_signal_emit
-                 (it->deco_all_view, "elm,state,disabled", "elm");
-          }
-        if (it->item->expanded)
-          {
-             edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
-             if (it->deco_all_view)
-               edje_object_signal_emit
-                 (it->deco_all_view, "elm,state,expanded", "elm");
-          }
+        edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
+        if (it->deco_all_view)
+           edje_object_signal_emit
+              (it->deco_all_view, "elm,state,disabled", "elm");
+     }
+   if (it->item->expanded)
+     {
+        edje_object_signal_emit(VIEW(it), "elm,state,expanded", "elm");
+        if (it->deco_all_view)
+           edje_object_signal_emit
+              (it->deco_all_view, "elm,state,expanded", "elm");
      }
 }
 
@@ -1158,16 +1086,8 @@ _item_mode_content_realize(Elm_Gen_Item *it,
                        // 1. Add resize callback for multiline entry.
                        // 2. Do not unrealize it for focus issue
                        // ps. Only for entry because of performnace
-                       if (!strcmp("elm_layout", evas_object_type_get(ic)))
-                         {
-                            // If editfield style, it can have entry.
-                            const char *group;
-                            edje_object_file_get(elm_layout_edje_get(ic), NULL, &group);
-                            if (group && !strncmp("elm/layout/editfield/", group, 20))
-                              it->item->unrealize_disabled = EINA_TRUE;
-                         }
-                       else if (!strcmp("elm_entry", evas_object_type_get(ic)))
-                          it->item->unrealize_disabled = EINA_TRUE;
+                       if (!strcmp("elm_entry", evas_object_type_get(ic)))
+                         it->item->unrealize_disabled = EINA_TRUE;
                     }
 #endif
 #if 0
@@ -1306,16 +1226,15 @@ _decorate_all_item_realize(Elm_Gen_Item *it,
      (it->deco_all_view, elm_widget_mirrored_get(WIDGET(it)));
 
    _elm_genlist_item_odd_even_update(it);
-   _elm_genlist_item_state_update(it, NULL);
+   _elm_genlist_item_state_update(it);
 
 #if 1 // FIXME: difference from upstream
    if (GL_IT(it)->wsd->reorder_mode)
-     {
-        edje_object_signal_emit
-          (VIEW(it), "elm,state,reorder,mode_unset", "elm");
-        edje_object_signal_emit
-          (it->deco_all_view, "elm,state,reorder,mode_set", "elm");
-     }
+     edje_object_signal_emit
+       (it->deco_all_view, "elm,state,reorder,mode_set", "elm");
+   else
+     edje_object_signal_emit
+       (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
 #endif
    if (effect_on)
      {
@@ -1408,8 +1327,6 @@ _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
    Elm_Gen_Item *it = data;
    if (!it) return;
    if (it->want_unrealize) return;
-   it->item->mincalcd = EINA_FALSE;
-   it->item->block->changeme = EINA_TRUE;
    GL_IT(it)->wsd->size_changed = EINA_TRUE;
    evas_object_smart_changed(GL_IT(it)->wsd->pan_obj);
 }
@@ -1452,25 +1369,12 @@ _item_content_realize(Elm_Gen_Item *it,
                   // 1. Add resize callback for multiline entry.
                   // 2. Do not unrealize it for focus issue
                   // ps. Only for entry because of performnace
-                  if (!strcmp("elm_layout", evas_object_type_get(ic)))
+                  if (!strcmp("elm_entry", evas_object_type_get(ic)))
                     {
-                       // If editfield style, it can have entry.
-                       const char *group;
-                       edje_object_file_get(elm_layout_edje_get(ic), NULL, &group);
-                       if (group && !strncmp("elm/layout/editfield/", group, 20))
-                         {
-                            evas_object_event_callback_add
-                               (ic, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
-                                _changed_size_hints, it);
-                            it->item->unrealize_disabled = EINA_TRUE;
-                         }
-
-                    }
-                  else if (!strcmp("elm_entry", evas_object_type_get(ic)))
-                    {
-                       evas_object_event_callback_add
-                          (ic, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
-                           _changed_size_hints, it);
+                       if (!elm_entry_single_line_get(ic))
+                         evas_object_event_callback_add
+                            (ic, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                             _changed_size_hints, it);
                        it->item->unrealize_disabled = EINA_TRUE;
                     }
 #endif
@@ -1584,7 +1488,6 @@ _item_realize(Elm_Gen_Item *it,
               int in,
               Eina_Bool calc)
 {
-   Item_Cache *itc = NULL;
    const char *treesize;
    char buf[1024];
    int tsize = 20;
@@ -1594,7 +1497,7 @@ _item_realize(Elm_Gen_Item *it,
         if (it->item->order_num_in != in)
           {
              _item_order_update(EINA_INLIST_GET(it), in);
-             _elm_genlist_item_state_update(it, NULL);
+             _elm_genlist_item_state_update(it);
              _elm_genlist_item_index_update(it);
           }
         return;
@@ -1630,8 +1533,10 @@ _item_realize(Elm_Gen_Item *it,
           (WIDGET(it), VIEW(it), "genlist", buf,
           elm_widget_style_get(WIDGET(it)));
 
+#if 1 // FIXME: difference from upstream
         if (it->item->expanded_depth > 0)
           edje_object_signal_emit(VIEW(it), "bg_color_change", "elm");
+#endif
 
         stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
         if (!stacking_even) stacking_even = "above";
@@ -1659,7 +1564,7 @@ _item_realize(Elm_Gen_Item *it,
 
    _item_order_update(EINA_INLIST_GET(it), in);
 #if 1 // FIXME: difference from upstream
-   if (!(it->deco_all_view) && (it->item->type != ELM_GENLIST_ITEM_GROUP))
+   if (it->item->type != ELM_GENLIST_ITEM_GROUP)
      {
         if (GL_IT(it)->wsd->reorder_mode)
           edje_object_signal_emit
@@ -1671,7 +1576,8 @@ _item_realize(Elm_Gen_Item *it,
 #endif
    treesize = edje_object_data_get(VIEW(it), "treesize");
    if (treesize) tsize = atoi(treesize);
-   if (!it->spacer && treesize)
+   if (it->parent && GL_IT(it->parent)->type == ELM_GENLIST_ITEM_TREE &&
+       !it->spacer && treesize)
      {
         it->spacer =
           evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
@@ -1691,7 +1597,7 @@ _item_realize(Elm_Gen_Item *it,
             (it->itc->decorate_all_item_style))
           _decorate_all_item_realize(it, EINA_FALSE);
 
-        _elm_genlist_item_state_update(it, itc);
+        _elm_genlist_item_state_update(it);
         _elm_genlist_item_index_update(it);
      }
 
@@ -1748,13 +1654,20 @@ _item_realize(Elm_Gen_Item *it,
         if (!it->item->mincalcd)
 #endif
           {
-             Evas_Coord mw = -1, mh = -1;
+             Evas_Coord mw = 0, mh = 0;
 
              if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
-             if (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS)
-               mw = GL_IT(it)->wsd->prev_viewport_w;
+             if ((GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS) &&
+                 (GL_IT(it)->wsd->prev_viewport_w != 0) &&
+                 (mw < GL_IT(it)->wsd->prev_viewport_w))
+                mw = GL_IT(it)->wsd->prev_viewport_w;
              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
+             if ((GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS) &&
+                 (GL_IT(it)->wsd->prev_viewport_w != 0) &&
+                 (mw > GL_IT(it)->wsd->prev_viewport_w))
+                mw = GL_IT(it)->wsd->prev_viewport_w;
+
 
              it->item->w = it->item->minw = mw;
              it->item->h = it->item->minh = mh;
@@ -2077,8 +1990,8 @@ _item_block_position(Item_Block *itb,
                               }
                             it->item->old_scrl_y = it->item->scrl_y;
 #if GENLIST_PINCH_ZOOM_SUPPORT
-                            if ((GL_IT(it)->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
-                                && (!IS_ROOT_PARENT_IT(it)))
+                            if (((GL_IT(it)->wsd->pinch_zoom_mode == ELM_GEN_PINCH_ZOOM_CONTRACT)
+                                 && (!IS_ROOT_PARENT_IT(it))) || (GL_IT(it)->wsd->sorting))
                               {
                                  if (it->deco_all_view) evas_object_hide(it->deco_all_view);
                                  else evas_object_hide(VIEW(it));
@@ -2125,7 +2038,6 @@ _item_block_realize(Item_Block *itb)
    itb->want_unrealize = EINA_FALSE;
 }
 
-#if GENLIST_ENTRY_SUPPORT
 static void
 _changed_job(Elm_Genlist_Smart_Data *sd)
 {
@@ -2136,42 +2048,37 @@ _changed_job(Elm_Genlist_Smart_Data *sd)
    Eina_Bool anything_changed = EINA_FALSE;
    Eina_Bool width_changed = EINA_FALSE;
    Eina_Bool height_changed = EINA_FALSE;
-   sd->size_changed = EINA_FALSE;
 
    EINA_INLIST_FOREACH(sd->blocks, itb)
      {
         Elm_Gen_Item *it;
 
-        if (!itb->changeme)
-          {
-             num += itb->count;
-             if (anything_changed)
-               _item_block_position(itb, num);
-             continue;
-          }
         num0 = num;
         width_changed = height_changed = EINA_FALSE;
         EINA_LIST_FOREACH(itb->items, l2, it)
           {
-             if ((!it->item->mincalcd) && (it->realized))
+             if (it->realized)
                {
-                  Evas_Coord fw = -1, fh = -1;
-                  Evas_Coord mw = -1, mh = -1;
+                  Evas_Coord mw = 0, mh = 0;
 
                   if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
-                     elm_coords_finger_size_adjust(1, &fw, 1, &fh);
-
-                  // FIXME: why compressmode do this?
-                  if (sd->mode == ELM_LIST_COMPRESS) mw = sd->prev_viewport_w;
-
-                  edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, fw, fh);
-
-                  if (it->item->w != mw)
+                     elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+                  if ((GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS) &&
+                      (GL_IT(it)->wsd->prev_viewport_w != 0) &&
+                      (mw < GL_IT(it)->wsd->prev_viewport_w))
+                     mw = GL_IT(it)->wsd->prev_viewport_w;
+                  edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
+                  if ((GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS) &&
+                      (GL_IT(it)->wsd->prev_viewport_w != 0) &&
+                      (mw > GL_IT(it)->wsd->prev_viewport_w))
+                     mw = GL_IT(it)->wsd->prev_viewport_w;
+
+                  if (it->item->minw != mw)
                     {
                        it->item->w = it->item->minw = mw;
                        width_changed = EINA_TRUE;
                     }
-                  if (it->item->h != mh)
+                  if (it->item->minh != mh)
                     {
                        it->item->h = it->item->minh = mh;
                        height_changed = EINA_TRUE;
@@ -2181,14 +2088,13 @@ _changed_job(Elm_Genlist_Smart_Data *sd)
                        itb->w = mw;
                     }
 
-                  it->item->mincalcd = EINA_TRUE;
-
                   if ((!sd->group_item_width) && (it->group))
                     {
                        sd->group_item_width = mw;
                        sd->group_item_height = mh;
                     }
-                  else if ((!sd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
+                  else if ((!sd->item_width) &&
+                           (it->item->type == ELM_GENLIST_ITEM_NONE))
                     {
                        sd->item_width = mw;
                        sd->item_height = mh;
@@ -2196,7 +2102,6 @@ _changed_job(Elm_Genlist_Smart_Data *sd)
                }
              num++;
           }
-        itb->changeme = EINA_FALSE;
         if (height_changed)
           {
              anything_changed = EINA_TRUE;
@@ -2215,7 +2120,6 @@ _changed_job(Elm_Genlist_Smart_Data *sd)
         sd->calc_job = ecore_job_add(_calc_job, sd);
      }
 }
-#endif
 
 static void
 _elm_genlist_pan_smart_calculate(Evas_Object *obj)
@@ -2247,7 +2151,7 @@ _elm_genlist_pan_smart_calculate(Evas_Object *obj)
 #if GROUP_ITEMS_FEATURE
        git->item->want_realize = EINA_FALSE;
 #else
-       _item_unrealize(git, EINA_TRUE);
+       evas_object_hide(VIEW(git));
 #endif
     }
 
@@ -2308,9 +2212,11 @@ _elm_genlist_pan_smart_calculate(Evas_Object *obj)
      psd->wsd->s_iface->content_region_show(ELM_WIDGET_DATA(psd->wsd)->obj,
                                             vx, vy + 10, vw, vh);
 
-#if GENLIST_ENTRY_SUPPORT
-   if (psd->wsd->size_changed) _changed_job(psd->wsd);
-#endif
+   if (psd->wsd->size_changed)
+     {
+        _changed_job(psd->wsd);
+        psd->wsd->size_changed = EINA_FALSE;
+     }
 
 #if GENLIST_FX_SUPPORT
    psd->wsd->rendered = EINA_TRUE;
@@ -3056,20 +2962,14 @@ _decorate_all_item_unrealize(Elm_Gen_Item *it)
    evas_object_smart_member_add(VIEW(it), GL_IT(it)->wsd->pan_obj);
    elm_widget_sub_object_add(WIDGET(it), VIEW(it));
    _elm_genlist_item_odd_even_update(it);
-   _elm_genlist_item_state_update(it, NULL);
+   _elm_genlist_item_state_update(it);
 
    edje_object_signal_emit
      (it->deco_all_view, "elm,state,decorate,disabled", "elm");
    edje_object_signal_emit
      (VIEW(it), "elm,state,decorate,disabled", "elm");
-   if (it->item->wsd->reorder_mode)
-     {
-        edje_object_signal_emit
-          (VIEW(it), "elm,state,reorder,mode_set", "elm");
-        edje_object_signal_emit
-          (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
-     }
-
+   edje_object_signal_emit
+     (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
    edje_object_message_signal_process(VIEW(it));
    edje_object_message_signal_process(it->deco_all_view);
 
@@ -3115,7 +3015,7 @@ _item_free_common(Elm_Gen_Item *it)
         Elm_Gen_Item *tmp;
         EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = NULL;
      }
-   _item_subitems_clear(it);
+   _item_sub_items_clear(it);
 
 #if GENLIST_ENTRY_SUPPORT
    it->item->unrealize_disabled = EINA_FALSE;
@@ -3149,43 +3049,6 @@ _item_free_common(Elm_Gen_Item *it)
 }
 
 static void
-_item_free(Elm_Gen_Item *it)
-{
-   Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
-
-#if GENLIST_FX_SUPPORT
-   if (sd->fx_mode) GL_IT(it)->has_proxy_it = EINA_FALSE;
-   _elm_genlist_proxy_item_del((Elm_Object_Item *)it);
-   if ((!sd->fx_mode) || (sd->genlist_clearing))
-#endif
-     {
-        _item_free_common(it);
-     }
-   _item_unrealize(it, EINA_FALSE);
-   elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
-   free(it->item);
-
-   if (sd->calc_job) ecore_job_del(sd->calc_job);
-   sd->calc_job = ecore_job_add(_calc_job, sd);
-}
-
-#if GENLIST_FX_SUPPORT
-static void
-_item_del_pre_fx_process(Elm_Gen_Item *it)
-{
-   Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
-
-   sd->fx_items_deleted = EINA_TRUE;
-   _elm_genlist_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
-   if (!eina_list_data_find(sd->pending_del_items, it))
-     sd->pending_del_items = eina_list_append(sd->pending_del_items, it);
-
-   _item_free_common(it);
-
-}
-#endif
-
-static void
 _item_mouse_move_cb(void *data,
                     Evas *evas __UNUSED__,
                     Evas_Object *obj,
@@ -3875,19 +3738,7 @@ newblock:
    it->item->block = itb;
    if (itb->sd->calc_job) ecore_job_del(itb->sd->calc_job);
    itb->sd->calc_job = ecore_job_add(_calc_job, itb->sd);
-/*
-   if (it->item->rel)
-     {
-        it->item->rel->relcount--;
-        // FIXME: relcount should be removed.
-        if (((Elm_Widget_Item *)it->item->rel)->on_deletion &&
-            (!it->item->rel->relcount))
-          {
-             elm_widget_item_del(it->item->rel);
-          }
-        it->item->rel = NULL;
-     }
-*/
+
    if (itb->count > itb->sd->max_items_per_block)
      {
         int newc;
@@ -4061,39 +3912,28 @@ _queue_process(Elm_Genlist_Smart_Data *sd)
 }
 
 static Eina_Bool
-_idle_process(void *data,
-              Eina_Bool *wakeup)
-{
-   Elm_Genlist_Smart_Data *sd = data;
-
-   if (_queue_process(sd) > 0) *wakeup = EINA_TRUE;
-   if (!sd->queue)
-     {
-        return ECORE_CALLBACK_CANCEL;
-     }
-#if GENLIST_FX_SUPPORT
-   if (sd->fx_first_captured)
-     _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj);
-#endif
-   return ECORE_CALLBACK_RENEW;
-}
-
-static Eina_Bool
 _item_idle_enterer(void *data)
 {
-   Eina_Bool wakeup = EINA_FALSE;
    Elm_Genlist_Smart_Data *sd = data;
-   Eina_Bool ok = _idle_process(data, &wakeup);
 
-   if (wakeup)
+   if (sd->prev_viewport_w == 0) return ECORE_CALLBACK_RENEW;
+   if (_queue_process(sd) > 0)
      {
         // wake up mainloop
+        // Job always be alive because idle_enterer should be alive
         if (sd->calc_job) ecore_job_del(sd->calc_job);
         sd->calc_job = ecore_job_add(_calc_job, sd);
      }
-   if (ok == ECORE_CALLBACK_CANCEL) sd->queue_idle_enterer = NULL;
+   if (!sd->queue)
+     {
+        sd->queue_idle_enterer = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
 
-   return ok;
+#if GENLIST_FX_SUPPORT
+   _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
+#endif
+   return ECORE_CALLBACK_RENEW;
 }
 
 static void
@@ -4102,38 +3942,26 @@ _item_queue(Elm_Genlist_Smart_Data *sd,
             Eina_Compare_Cb cb)
 {
    if (it->item->queued) return;
+
    it->item->queued = EINA_TRUE;
    if (cb && !sd->requeued)
      sd->queue = eina_list_sorted_insert(sd->queue, cb, it);
    else
      sd->queue = eina_list_append(sd->queue, it);
-// FIXME: why does a freeze then thaw here cause some genlist
-// elm_genlist_item_append() to be much much slower?
-//   evas_event_freeze(evas_object_evas_get(sd->obj));
-   while ((sd->queue) && ((!sd->blocks) || (!sd->blocks->next)))
-     {
-        if (sd->queue_idle_enterer)
-          {
-             ecore_idle_enterer_del(sd->queue_idle_enterer);
-             sd->queue_idle_enterer = NULL;
-          }
-        _queue_process(sd);
-     }
-   while ((sd->queue) && (sd->blocks) &&
-          (sd->homogeneous) && (sd->mode == ELM_LIST_COMPRESS))
+
+   if (sd->queue_idle_enterer)
+      ecore_idle_enterer_del(sd->queue_idle_enterer);
+   sd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, sd);
+
+   if (sd->prev_viewport_w != 0)
      {
-        if (sd->queue_idle_enterer)
-          {
-             ecore_idle_enterer_del(sd->queue_idle_enterer);
-             sd->queue_idle_enterer = NULL;
-          }
-        _queue_process(sd);
-     }
+        while ((sd->queue) && ((!sd->blocks) || (!sd->blocks->next)))
+          _queue_process(sd);
 
-//   evas_event_thaw(evas_object_evas_get(sd->obj));
-//   evas_event_thaw_eval(evas_object_evas_get(sd->obj));
-   if (!sd->queue_idle_enterer)
-     sd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, sd);
+        while ((sd->queue) && (sd->blocks) &&
+               (sd->homogeneous) && (sd->mode == ELM_LIST_COMPRESS))
+          _queue_process(sd);
+     }
 }
 
 /* If the application wants to know the relative item, use
@@ -4586,6 +4414,9 @@ static void
 _scroll_animate_start_cb(Evas_Object *obj,
                          void *data __UNUSED__)
 {
+#if GENLIST_FX_SUPPORT
+   _elm_genlist_fx_clear(obj, EINA_FALSE);
+#endif
    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
 }
 
@@ -4593,6 +4424,9 @@ static void
 _scroll_animate_stop_cb(Evas_Object *obj,
                         void *data __UNUSED__)
 {
+#if GENLIST_FX_SUPPORT
+   _elm_genlist_fx_clear(obj, EINA_FALSE);
+#endif
    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
 }
 
@@ -5172,6 +5006,43 @@ _item_disable_hook(Elm_Object_Item *item)
      }
 }
 
+static void
+_item_free(Elm_Gen_Item *it)
+{
+   Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
+
+#if GENLIST_FX_SUPPORT
+   if (sd->fx_mode) GL_IT(it)->has_proxy_it = EINA_FALSE;
+   _elm_genlist_proxy_item_del((Elm_Object_Item *)it);
+   if ((!sd->fx_mode) || (sd->genlist_clearing))
+#endif
+     {
+        _item_free_common(it);
+     }
+   _item_unrealize(it, EINA_FALSE);
+   elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
+   free(it->item);
+
+   if (sd->calc_job) ecore_job_del(sd->calc_job);
+   sd->calc_job = ecore_job_add(_calc_job, sd);
+}
+
+#if GENLIST_FX_SUPPORT
+static void
+_item_del_pre_fx_process(Elm_Gen_Item *it)
+{
+   Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
+
+   sd->fx_items_deleted = EINA_TRUE;
+   _elm_genlist_fx_capture(ELM_WIDGET_DATA(sd)->obj, 0);
+   if (!eina_list_data_find(sd->pending_del_items, it))
+     sd->pending_del_items = eina_list_append(sd->pending_del_items, it);
+
+   _item_free_common(it);
+
+}
+#endif
+
 static Eina_Bool
 _item_del_pre_hook(Elm_Object_Item *item)
 {
@@ -5575,7 +5446,7 @@ elm_genlist_item_sorted_insert(Evas_Object *obj,
 }
 
 static void
-_elm_genlist_fx_clear(Evas_Object *obj)
+_elm_genlist_fx_clear(Evas_Object *obj, Eina_Bool force)
 {
    ELM_GENLIST_DATA_GET(obj, sd);
 
@@ -5583,6 +5454,8 @@ _elm_genlist_fx_clear(Evas_Object *obj)
    Proxy_Item *pi;
    Elm_Gen_Item *it;
 
+   if ((!force) && (!sd->fx_first_captured)) return;
+
    EINA_LIST_FREE(sd->capture_before_items, pi)
      {
         if ((pi->it) && (GL_IT(pi->it))) GL_IT(pi->it)->has_proxy_it = EINA_FALSE;
@@ -5617,9 +5490,12 @@ _elm_genlist_fx_clear(Evas_Object *obj)
      }
    if (sd->alpha_bg) evas_object_del(sd->alpha_bg);
    sd->alpha_bg = NULL;
+   if (sd->fx_timer) ecore_timer_del(sd->fx_timer);
+   sd->fx_timer = NULL;
 
    sd->genlist_clearing = EINA_TRUE;
    sd->fx_playing = EINA_FALSE;
+   sd->sorting = EINA_FALSE;
    sd->fx_first_captured = EINA_FALSE;
    sd->fx_items_deleted = EINA_FALSE;
 }
@@ -5640,7 +5516,7 @@ elm_genlist_clear(Evas_Object *obj)
 #if GENLIST_FX_SUPPORT
    if (sd->fx_mode)
      {
-        _elm_genlist_fx_clear(obj);
+        _elm_genlist_fx_clear(obj, EINA_TRUE);
         sd->genlist_clearing = EINA_TRUE;
         sd->rendered = EINA_FALSE;
      }
@@ -5658,6 +5534,7 @@ elm_genlist_clear(Evas_Object *obj)
    while (sd->items)
      {
         it = EINA_INLIST_CONTAINER_GET(sd->items->last, Elm_Gen_Item);
+        it->item->nocache_once = EINA_TRUE;
         elm_widget_item_del(it);
      }
    sd->items = NULL;
@@ -5926,7 +5803,7 @@ elm_genlist_item_subitems_clear(Elm_Object_Item *item)
    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
 
    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item);
-   _item_subitems_clear(it);
+   _item_sub_items_clear(it);
 }
 
 EAPI void
@@ -6175,8 +6052,7 @@ elm_genlist_item_update(Elm_Object_Item *item)
 #endif
 
 #if GENLIST_FX_SUPPORT
-   if (GL_IT(it)->wsd->fx_first_captured)
-     _elm_genlist_fx_clear(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj);
+     _elm_genlist_fx_clear(ELM_WIDGET_DATA(GL_IT(it)->wsd)->obj, EINA_FALSE);
 #endif
 
    if (GL_IT(it)->wsd->update_job) ecore_job_del(GL_IT(it)->wsd->update_job);
@@ -6486,14 +6362,18 @@ elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
 EAPI int
 elm_genlist_item_index_get(const Elm_Object_Item *item)
 {
+   int cnt = 0;
+   Elm_Gen_Item *tmp;
    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
 
    ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, -1);
 
-   if (it->item->block)
-     return it->position + (it->item->block->position *
-                            GL_IT(it)->wsd->max_items_per_block);
-   return -1;
+   EINA_INLIST_FOREACH(GL_IT(it)->wsd->items, tmp)
+     {
+        if (tmp == it) break;
+        cnt++;
+     }
+   return cnt;
 }
 
 EAPI void
@@ -6743,9 +6623,7 @@ elm_genlist_decorate_mode_set(Evas_Object *obj,
           }
      }
 #if GENLIST_FX_SUPPORT
-   if (sd->fx_first_captured)
-     _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj);
-
+     _elm_genlist_fx_clear(ELM_WIDGET_DATA(sd)->obj, EINA_FALSE);
 #endif
    if (sd->calc_job) ecore_job_del(sd->calc_job);
    sd->calc_job = ecore_job_add(_calc_job, sd);
@@ -6770,16 +6648,21 @@ elm_genlist_reorder_mode_set(Evas_Object *obj,
      {
         if (it->item->type != ELM_GENLIST_ITEM_GROUP)
           {
-             Evas_Object *view;
-             if (it->deco_all_view) view = it->deco_all_view;
-             else view = VIEW(it);
-
              if (sd->reorder_mode)
                edje_object_signal_emit
-                 (view, "elm,state,reorder,mode_set", "elm");
+                 (VIEW(it), "elm,state,reorder,mode_set", "elm");
              else
                edje_object_signal_emit
-                 (view, "elm,state,reorder,mode_unset", "elm");
+                 (VIEW(it), "elm,state,reorder,mode_unset", "elm");
+          }
+        if (sd->decorate_all_mode)
+          {
+             if (sd->reorder_mode)
+               edje_object_signal_emit
+                  (it->deco_all_view, "elm,state,reorder,mode_set", "elm");
+             else
+               edje_object_signal_emit
+                  (it->deco_all_view, "elm,state,reorder,mode_unset", "elm");
           }
      }
    eina_list_free(list);
@@ -7053,7 +6936,7 @@ static void
 _elm_genlist_proxy_item_del(const Elm_Object_Item *item)
 {
    Elm_Gen_Item *it = (Elm_Gen_Item *)item;
-   if ((!it) || (!it->item)) return EINA_FALSE;
+   if ((!it) || (!it->item)) return;
 
    Elm_Genlist_Smart_Data *sd = GL_IT(it)->wsd;
    Proxy_Item *pi;
@@ -7121,10 +7004,12 @@ _elm_genlist_fx_capture(Evas_Object *obj, int level)
    Proxy_Item *pi;
    Evas_Coord ox, oy, ow, oh;
 
-   if ((!sd->rendered) || (sd->fx_playing)) return EINA_FALSE;
-   if ((!level) && (sd->fx_first_captured)) return EINA_FALSE;
-   if ((level) && (!sd->fx_first_captured)) return EINA_FALSE;
-
+   if (!sd->sorting)
+     {
+        if ((!sd->rendered) || (sd->fx_playing)) return EINA_FALSE;
+        if ((!level) && (sd->fx_first_captured)) return EINA_FALSE;
+        if ((level) && (!sd->fx_first_captured)) return EINA_FALSE;
+     }
    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
 
    if (!level)
@@ -7519,6 +7404,7 @@ _item_fx_del_cb(void *data, Elm_Transit *transit __UNUSED__)
            evas_object_hide(pi->proxy);
 
         sd->fx_playing = EINA_FALSE;
+        sd->sorting = EINA_FALSE;
         sd->fx_first_captured = EINA_FALSE;
         evas_object_hide(sd->alpha_bg);
 
@@ -7528,6 +7414,44 @@ _item_fx_del_cb(void *data, Elm_Transit *transit __UNUSED__)
      }
 }
 
+static Eina_Bool
+_sorting_effect_animator_cb(void *data)
+{
+   Elm_Genlist_Smart_Data *sd = data;
+   Elm_Gen_FX_Item *fi;
+   Eina_List *l;
+
+   Evas_Coord ox, oy, ow, oh;
+   evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
+
+   sd->fx_timer = NULL;
+   EINA_LIST_FOREACH(sd->fx_items, l, fi)
+     {
+        if (!fi->changed)
+          {
+             fi->changed = EINA_TRUE;
+             evas_object_resize(fi->proxy, ow, fi->to.h);
+
+             fi->trans = elm_transit_add();
+             elm_transit_object_add(fi->trans, fi->proxy);
+             evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
+             elm_transit_tween_mode_set(fi->trans, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
+
+             elm_transit_effect_translation_add(fi->trans, fi->to.x, fi->to.y - 30 * elm_config_scale_get(), fi->to.x, fi->to.y);
+             elm_transit_effect_color_add(fi->trans,0, 0, 0, 0, 255,255,255,255);
+
+             elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
+             elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
+             elm_transit_duration_set(fi->trans,0.3);
+             elm_transit_objects_final_state_keep_set(fi->trans, EINA_FALSE);
+             elm_transit_go(fi->trans);
+
+             return ECORE_CALLBACK_RENEW;
+          }
+     }
+   return ECORE_CALLBACK_CANCEL;
+}
+
 static void
 _elm_genlist_fx_play(Evas_Object *obj)
 {
@@ -7550,7 +7474,7 @@ _elm_genlist_fx_play(Evas_Object *obj)
    _elm_genlist_fx_items_make(obj);
    if (!eina_list_count(sd->fx_items) || (sd->queue))
      {
-        _elm_genlist_fx_clear(obj);
+        _elm_genlist_fx_clear(obj, EINA_TRUE);
         return;
      }
 
@@ -7562,6 +7486,15 @@ _elm_genlist_fx_play(Evas_Object *obj)
    evas_object_geometry_get(sd->pan_obj, &ox, &oy, &ow, &oh);
    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
 
+   if (sd->sorting)
+     {
+        EINA_LIST_FOREACH(sd->fx_items, l, fi)
+           evas_object_image_source_visible_set(fi->proxy, EINA_FALSE);
+        if (sd->fx_timer) ecore_timer_del(sd->fx_timer);
+        sd->fx_timer = ecore_timer_add(0.05, _sorting_effect_animator_cb, sd);
+        return;
+     }
+
    EINA_LIST_FOREACH(sd->fx_items, l, fi)
      {
         if (!fi->proxy) continue;
@@ -7600,11 +7533,16 @@ _elm_genlist_fx_play(Evas_Object *obj)
           {
              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
              elm_transit_effect_color_add(fi->trans, 0, 0, 0, 0, 255, 255, 255, 255);
+             if ((!sd->pinch_zoom_mode) && (!sd->expanded_item))
+               elm_transit_effect_zoom_add(fi->trans, 0.8, 1.0);
           }
         else if (fi->type == ELM_GEN_ITEM_FX_TYPE_DEL)
           {
+             _item_unhighlight(fi->it);
              elm_transit_effect_translation_add(fi->trans, fi->from.x, fi->from.y, fi->to.x, fi->to.y);
              elm_transit_effect_color_add(fi->trans, 255, 255, 255, 255, 0, 0, 0, 0);
+             if ((!sd->pinch_zoom_mode) && (!sd->expanded_item))
+               elm_transit_effect_zoom_add(fi->trans, 1.0, 0.8);
           }
         elm_transit_effect_add(fi->trans, _item_fx_op, fi, _item_fx_done);
         elm_transit_del_cb_set(fi->trans, _item_fx_del_cb, fi);
@@ -7660,3 +7598,123 @@ elm_genlist_pinch_zoom_mode_set(Evas_Object *obj, Elm_Gen_Pinch_Zoom_Mode mode)
    return EINA_TRUE;
 }
 #endif
+
+static Eina_List *
+eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func)
+{
+   Eina_List *first, *last;
+
+   if (func(a->data, b->data) > 0)
+     {
+        _item_move_after(a->data, b->data);
+        a = (last = first = a)->next;
+
+     }
+   else
+     b = (last = first = b)->next;
+
+   while (a && b)
+     if (func(a->data, b->data) > 0)
+       {
+          _item_move_after(a->data, b->data);
+          a = (last = last->next = a)->next;
+       }
+     else
+       b = (last = last->next = b)->next;
+
+   last->next = a ? a : b;
+
+   return first;
+}
+
+EAPI Eina_List *
+elm_genlist_sort(Evas_Object *obj, Eina_Compare_Cb func)
+{
+   ELM_GENLIST_CHECK(obj) NULL;
+   ELM_GENLIST_DATA_GET(obj, sd);
+   Eina_List *list = NULL;
+   Elm_Gen_Item  *it, *next;
+   unsigned int limit = 0, i = 0, n = 0;
+   Eina_List *tail = NULL, *unsort = NULL, *stack[32], *prev = NULL;
+
+   sd->sorting = EINA_TRUE;
+
+   it = (Elm_Gen_Item*)elm_genlist_first_item_get(obj);
+   while(1)
+     {
+        list = eina_list_append(list, it);
+        next = (Elm_Gen_Item*)elm_genlist_item_next_get((Elm_Object_Item *)it);
+        if (!next) break;
+        it = next;
+     }
+
+   if (!list)
+     return NULL;
+
+   limit = eina_list_count(list);
+   tail = list;
+
+   if ((limit == 0) ||
+       (limit > list->accounting->count))
+     limit = list->accounting->count;
+
+   if (limit != list->accounting->count)
+     {
+        unsort = eina_list_nth_list(list, limit);
+        if (unsort)
+          unsort->prev->next = NULL;
+     }
+
+   while (tail)
+     {
+        unsigned int idx, tmp;
+
+        Eina_List *a = tail;
+        Eina_List *b = tail->next;
+
+        if (!b)
+          {
+             stack[i++] = a;
+             break;
+          }
+
+        tail = b->next;
+
+        if (func(a->data, b->data) > 0)
+          ((stack[i++] = a)->next = b)->next = 0;
+        else
+             ((stack[i++] = b)->next = a)->next = 0;
+
+        tmp = n++;
+        for (idx = n ^ tmp; idx &= idx - 1; i--)
+          stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func);
+     }
+
+   while (i-- > 1)
+     stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func);
+
+   list = stack[0];
+
+   for (; stack[0]; stack[0] = stack[0]->next)
+     {
+        stack[0]->prev = prev;
+        prev = stack[0];
+     }
+   tail = prev;
+
+   if (unsort)
+     {
+        tail->next = unsort;
+        unsort->prev = tail;
+     }
+   else
+     list->accounting->last = tail;
+
+   if (!sd->fx_mode) sd->sorting = EINA_FALSE;
+   if (sd->decorate_all_mode) sd->sorting = EINA_FALSE;
+   sd->s_iface->content_region_show(obj, 0,0,0,0);
+   sd->pan_changed = EINA_TRUE;
+   evas_object_smart_changed(sd->pan_obj);
+
+   return list;
+}