Elementary migration revision 70375
[framework/uifw/elementary.git] / src / lib / elm_genlist.c
index c8e5c69..66fcdd0 100644 (file)
@@ -98,6 +98,7 @@ struct _Item_Block
    Eina_Bool    realized : 1;
    Eina_Bool    changed : 1;
    Eina_Bool    updateme : 1;
+   Eina_Bool    changeme : 1;
    Eina_Bool    showme : 1;
    Eina_Bool    must_recalc : 1;
 };
@@ -133,6 +134,8 @@ static void      _item_block_unrealize(Item_Block *itb);
 static void      _calc_job(void *data);
 static void      _on_focus_hook(void        *data,
                                 Evas_Object *obj);
+static void      _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void      _changed_job(void *data);
 static Eina_Bool _item_multi_select_up(Widget_Data *wd);
 static Eina_Bool _item_multi_select_down(Widget_Data *wd);
 static Eina_Bool _item_single_select_up(Widget_Data *wd);
@@ -160,7 +163,10 @@ static void      _decorate_item_unset(Widget_Data *wd);
 static void      _decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity);
 static void      _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on);
 static void      _decorate_all_item_unrealize(Elm_Gen_Item *it);
+//FIXME: group raise
+#if 0
 static void      _group_items_recalc(void *data);
+#endif
 static void      _item_move_after(Elm_Gen_Item *it,
                                   Elm_Gen_Item *after);
 static void      _item_move_before(Elm_Gen_Item *it,
@@ -535,7 +541,7 @@ _on_focus_hook(void        *data __UNUSED__,
      {
         elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
         evas_object_focus_set(wd->obj, EINA_TRUE);
-        if ((wd->selected) && (!wd->last_selected_item))
+        if ((wd->items) && (wd->selected) && (!wd->last_selected_item))
           wd->last_selected_item = eina_list_data_get(wd->selected);
      }
    else
@@ -554,6 +560,7 @@ _del_hook(Evas_Object *obj)
    if (wd->calc_job) ecore_job_del(wd->calc_job);
    if (wd->update_job) ecore_job_del(wd->update_job);
    if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
+   if (wd->changed_job) ecore_job_del(wd->changed_job);
    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
    if (wd->decorate_it_type) eina_stringshare_del(wd->decorate_it_type);
@@ -595,7 +602,7 @@ _theme_hook(Evas_Object *obj)
    _mirrored_set(obj, elm_widget_mirrored_get(obj));
    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
                                        elm_widget_style_get(obj));
-   edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
+   //edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
    wd->item_width = wd->item_height = 0;
    wd->group_item_width = wd->group_item_height = 0;
    wd->minw = wd->minh = wd->realminw = 0;
@@ -668,6 +675,8 @@ _sizing_eval(Evas_Object *obj)
              if (wd->calc_job) ecore_job_del(wd->calc_job);
              wd->calc_job = ecore_job_add(_calc_job, wd);
           }
+        edje_object_size_min_calc
+          (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
         minw = vmw;
         minh = vmh;
      }
@@ -714,8 +723,11 @@ _item_highlight(Elm_Gen_Item *it)
      {
         if (it->deco_all_view) evas_object_raise(it->deco_all_view);
         else evas_object_raise(VIEW(it));
+//FIXME: group raise
+#if 0
         if ((it->item->group_item) && (it->item->group_item->realized))
           evas_object_raise(it->item->VIEW(group_item));
+#endif
      }
    it->highlighted = EINA_TRUE;
 }
@@ -730,13 +742,13 @@ _item_unhighlight(Elm_Gen_Item *it)
      {
        if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
          {
-            if (it->deco_all_view) evas_object_lower(it->deco_all_view);
-            else evas_object_lower(VIEW(it));
+             if (it->deco_all_view) evas_object_lower(it->deco_all_view);
+             else evas_object_lower(VIEW(it));
          }
        else
          {
-            if (it->deco_all_view) evas_object_raise(it->deco_all_view);
-            else evas_object_raise(VIEW(it));
+             if (it->deco_all_view) evas_object_raise(it->deco_all_view);
+             else evas_object_raise(VIEW(it));
          }
      }
    it->highlighted = EINA_FALSE;
@@ -772,12 +784,16 @@ _item_block_del(Elm_Gen_Item *it)
 {
    Eina_Inlist *il;
    Item_Block *itb = it->item->block;
+   Eina_Bool block_changed;
 
    itb->items = eina_list_remove(itb->items, it);
    itb->count--;
    itb->changed = EINA_TRUE;
-   if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
-   it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
+   if (!it->wd->reorder_deleted)
+     {
+        if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
+        it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
+     }
    if (itb->count < 1)
      {
         il = EINA_INLIST_GET(itb);
@@ -815,6 +831,7 @@ _item_block_del(Elm_Gen_Item *it)
                   it->wd->blocks = eina_inlist_remove(it->wd->blocks,
                                                       EINA_INLIST_GET(itb));
                   free(itb);
+                  block_changed = EINA_TRUE;
                }
              else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
                {
@@ -834,9 +851,17 @@ _item_block_del(Elm_Gen_Item *it)
                   it->wd->blocks =
                     eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
                   free(itb);
+                  block_changed = EINA_TRUE;
                }
           }
      }
+   if (block_changed)
+     {
+        it->wd->pan_changed = EINA_TRUE;
+        evas_object_smart_changed(it->wd->pan_smart);
+        if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
+        it->wd->calc_job = NULL;
+     }
 }
 
 static void
@@ -1033,14 +1058,14 @@ _mouse_move(void        *data,
              ecore_timer_del(it->long_timer);
              it->long_timer = NULL;
           }
-        if (!it->wd->wasselected)
+        if ((!it->wd->wasselected) && (!it->flipped))
           {
              _item_unhighlight(it);
              _item_unselect(it);
           }
         if (dy < 0)
           {
-             if (ady > adx)
+             if ((ady > adx) && (!it->wd->drag_started))
                evas_object_smart_callback_call(WIDGET(it),
                                                SIG_DRAG_START_UP, it);
              else
@@ -1055,7 +1080,7 @@ _mouse_move(void        *data,
           }
         else
           {
-             if (ady > adx)
+             if ((ady > adx) && (!it->wd->drag_started))
                evas_object_smart_callback_call(WIDGET(it),
                                                SIG_DRAG_START_DOWN, it);
              else
@@ -1100,6 +1125,18 @@ _long_press(void *data)
           {
              if (it != it_tmp) _item_unselect(it_tmp);
           }
+        if (it->item->items)
+          {
+             EINA_LIST_FOREACH(it->item->items, l, it_tmp)
+               {
+                  if (elm_genlist_item_expanded_get((Elm_Object_Item *) it_tmp))
+                    {
+                       elm_genlist_item_expanded_set((Elm_Object_Item *)it_tmp,
+                                                     EINA_FALSE);
+                       return ECORE_CALLBACK_RENEW;
+                    }
+               }
+          }
         if (elm_genlist_item_expanded_get((Elm_Object_Item *)it))
           {
              elm_genlist_item_expanded_set((Elm_Object_Item *)it, EINA_FALSE);
@@ -1299,8 +1336,29 @@ _mouse_down(void        *data,
    Elm_Gen_Item *it = data;
    Evas_Event_Mouse_Down *ev = event_info;
    Evas_Coord x, y;
+   Eina_List *l;
+   Evas_Object *item_obj;
 
    if (ev->button != 1) return;
+   if (!it->can_focus)
+     {
+        EINA_LIST_FOREACH(it->content_objs, l, item_obj)
+          {
+             elm_widget_tree_unfocusable_set(item_obj, EINA_FALSE);
+          }
+        if (elm_widget_type_get(obj) == _genlist)
+          {
+             EINA_LIST_FOREACH(it->item->flip_content_objs, l, item_obj)
+               {
+                  elm_widget_tree_unfocusable_set(item_obj, EINA_FALSE);
+               }
+             EINA_LIST_FOREACH(it->item->deco_all_content_objs, l, item_obj)
+               {
+                  elm_widget_tree_unfocusable_set(item_obj, EINA_FALSE);
+               }
+          }
+        it->can_focus = EINA_TRUE;
+     }
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
      {
         it->wd->on_hold = EINA_TRUE;
@@ -1333,9 +1391,9 @@ _mouse_down(void        *data,
           evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
           evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
        }
+   if (it->long_timer) ecore_timer_del(it->long_timer);
    if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
    it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
-   if (it->long_timer) ecore_timer_del(it->long_timer);
    if (it->realized)
      it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
                                       it);
@@ -1413,6 +1471,7 @@ _mouse_up(void        *data,
              if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
              it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
           }
+        it->wd->reorder_deleted = EINA_FALSE;
         edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
         it->wd->reorder_it = it->wd->reorder_rel = NULL;
         elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
@@ -1522,6 +1581,66 @@ _item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view)
                                        _multi_move, it);
 }
 
+
+static void
+_mouse_down_scroller(void        *data,
+                     Evas        *evas __UNUSED__,
+                     Evas_Object *obj __UNUSED__,
+                     void        *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd) return;
+   wd->drag_started = EINA_FALSE;
+}
+
+static void
+_mouse_up_scroller(void        *data,
+                   Evas        *evas __UNUSED__,
+                   Evas_Object *obj __UNUSED__,
+                   void        *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+
+   if (!wd) return;
+   wd->drag_started = EINA_FALSE;
+}
+
+static void
+_mouse_move_scroller(void        *data,
+                     Evas        *evas __UNUSED__,
+                     Evas_Object *obj __UNUSED__,
+                     void        *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Coord minw = 0, minh = 0, dx, dy, adx, ady;
+
+   if (!wd) return;
+   if (wd->drag_started) return;
+
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   dx = ev->cur.canvas.x - ev->prev.canvas.x;
+   dy = ev->cur.canvas.y - ev->prev.canvas.y;
+   adx = dx;
+   ady = dy;
+   if (adx < 0) adx = -dx;
+   if (ady < 0) ady = -dy;
+   if (((ady < minh) && (ady > minh / 2)) && (ady > adx))
+     {
+        if (dy < 0)
+          {
+             evas_object_smart_callback_call(data, SIG_DRAG_START_UP, NULL);
+             wd->drag_started = EINA_TRUE;
+          }
+        else
+          {
+             evas_object_smart_callback_call(data, SIG_DRAG_START_DOWN, NULL);
+             wd->drag_started = EINA_TRUE;
+          }
+     }
+}
+
 static void
 _signal_expand_toggle(void        *data,
                       Evas_Object *obj __UNUSED__,
@@ -1586,8 +1705,11 @@ _decorate_item_finished_signal_cb(void        *data,
    evas_event_freeze(te);
    it->item->nocache_once = EINA_FALSE;
    _decorate_item_unrealize(it);
+//FIXME: group raise
+#if 0
    if (it->item->group_item)
      evas_object_raise(it->item->VIEW(group_item));
+#endif
    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->decorate_it_type);
    edje_object_signal_callback_del_full(obj, buf, "elm", _decorate_item_finished_signal_cb, it);
    evas_event_thaw(te);
@@ -1801,7 +1923,6 @@ _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
                edje_object_signal_emit(it->deco_all_view,
                                        "elm,state,selected", "elm");
           }
-
         if (elm_widget_item_disabled_get(it))
           {
              edje_object_signal_emit(VIEW(it),
@@ -1821,7 +1942,22 @@ _elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
      }
 }
 
-static Eina_List*
+static void
+_content_focused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Gen_Item *it = data;
+   if (it) it->defer_unrealize = EINA_TRUE;
+}
+
+static void
+_content_unfocused(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Elm_Gen_Item *it = data;
+   if (it) it->defer_unrealize = EINA_FALSE;
+}
+
+
+static Eina_List *
 _item_mode_content_realize(Elm_Gen_Item *it,
                            Evas_Object *target,
                            Eina_List **source,
@@ -1834,14 +1970,15 @@ _item_mode_content_realize(Elm_Gen_Item *it,
      {
         const Eina_List *l;
         const char *key;
+        Evas_Object *ic;
 
         EINA_LIST_FOREACH(*source, l, key)
           {
              if (parts && fnmatch(parts, key, FNM_PERIOD))
                continue;
 
-             Evas_Object *ic = it->itc->func.content_get
-                ((void *)it->base.data, WIDGET(it), l->data);
+             ic = it->itc->func.content_get
+               ((void *)it->base.data, WIDGET(it), key);
 
              if (ic)
                {
@@ -1849,11 +1986,15 @@ _item_mode_content_realize(Elm_Gen_Item *it,
                   edje_object_part_swallow(target, key, ic);
                   evas_object_show(ic);
                   elm_widget_sub_object_add(WIDGET(it), ic);
-                  if (it->item->deco_it_view || it->wd->decorate_all_mode)
+                  if (it->flipped)
                     {
-                       if (elm_widget_item_disabled_get(it))
-                         elm_widget_disabled_set(ic, EINA_TRUE);
+                       // FIXME: if entry calcuates its cursor position correctly and conformant works,
+                       //        genlist does not need to handle this focus thing.
+                       evas_object_smart_callback_add(ic, "focused", _content_focused, it);
+                       evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
                     }
+                  if (elm_widget_item_disabled_get(it))
+                    elm_widget_disabled_set(ic, EINA_TRUE);
                }
           }
      }
@@ -2000,6 +2141,17 @@ _item_content_realize(Elm_Gen_Item *it,
                   edje_object_part_swallow(target, key, ic);
                   evas_object_show(ic);
                   elm_widget_sub_object_add(WIDGET(it), ic);
+                  evas_object_event_callback_add(ic,
+                                                 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                                 _changed_size_hints, it);
+                  if (it->flipped)
+                    {
+                       // FIXME: if entry calcuates its cursor position correctly and conformant works,
+                       //        genlist does not need to handle this focus thing.
+                       evas_object_smart_callback_add(ic, "focused", _content_focused, it);
+                       evas_object_smart_callback_add(ic, "unfocused", _content_unfocused, it);
+                    }
+
                   if (elm_widget_item_disabled_get(it))
                     elm_widget_disabled_set(ic, EINA_TRUE);
                }
@@ -2047,8 +2199,8 @@ _item_state_realize(Elm_Gen_Item *it,
 
 static void
 _item_realize(Elm_Gen_Item *it,
-              int               in,
-              Eina_Bool         calc)
+              int           in,
+              Eina_Bool     calc)
 {
    const char *treesize;
    char buf[1024];
@@ -2072,7 +2224,7 @@ _item_realize(Elm_Gen_Item *it,
      }
    it->item->order_num_in = in;
 
-   if (it->item->nocache_once)
+   if ((it->item->nocache_once) && (!it->flipped))
      it->item->nocache_once = EINA_FALSE;
    else if (!it->item->nocache)
      itc = _item_cache_find(it);
@@ -2192,7 +2344,7 @@ _item_realize(Elm_Gen_Item *it,
                                           &it->item->flip_content_objs);
           }
 
-        if (!it->item->mincalcd)
+        if (!it->item->mincalcd || ((it->wd->mode == ELM_LIST_COMPRESS) && (it->item->w != it->item->minw)))
           {
              Evas_Coord mw = -1, mh = -1;
 
@@ -2465,7 +2617,10 @@ _reorder_move_animator_cb(void *data)
      _item_position(it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
    else
      _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
+//FIXME : group raise
+#if 0
    _group_items_recalc(it->wd);
+#endif
 
    if ((it->wd->reorder_pan_move) ||
        (down && it->item->old_scrl_y >= it->item->scrl_y) ||
@@ -2502,9 +2657,13 @@ _item_block_position(Item_Block *itb,
 {
    const Eina_List *l;
    Elm_Gen_Item *it;
+//FIXME : group raise
+#if 0
    Elm_Gen_Item *git;
+#endif
    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
    Eina_Bool vis = EINA_FALSE;
+   Evas_Coord minh = 0;
 
    evas_event_freeze(evas_object_evas_get(itb->wd->obj));
    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
@@ -2522,7 +2681,10 @@ _item_block_position(Item_Block *itb,
 
         vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
                                    cvx, cvy, cvw, cvh));
+//FIXME : group raise
+#if 0
         if (!it->group)
+#endif
           {
              if ((itb->realized) && (!it->realized))
                {
@@ -2534,6 +2696,8 @@ _item_block_position(Item_Block *itb,
                     {
                        if (it->wd->reorder_mode)
                          y += _get_space_for_reorder_item(it);
+//FIXME : group raise
+#if 0
                        git = it->item->group_item;
                        if (git)
                          {
@@ -2543,6 +2707,7 @@ _item_block_position(Item_Block *itb,
                               git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
                             git->item->want_realize = EINA_TRUE;
                          }
+#endif
                        if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
                          {
                             if (!it->item->move_effect_enabled)
@@ -2580,21 +2745,31 @@ _item_block_position(Item_Block *itb,
                   else
                     {
                        if (!it->wd->tree_effect_animator)
-                         _elm_genlist_item_unrealize(it, EINA_FALSE);
+                         {
+                            it->want_unrealize = EINA_TRUE;
+                            _elm_genlist_item_unrealize(it, EINA_FALSE);
+                         }
                     }
                }
              in++;
           }
+//FIXME : group raise
+#if 0
         else
           {
              if (vis) it->item->want_realize = EINA_TRUE;
           }
+#endif
         y += it->item->h;
+        minh += it->item->minh;
      }
+   if (!itb->wd->reorder_it) itb->minh = minh;
    evas_event_thaw(evas_object_evas_get(itb->wd->obj));
    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
 }
 
+//FIXME: group raise
+#if 0
 static void
 _group_items_recalc(void *data)
 {
@@ -2623,6 +2798,19 @@ _group_items_recalc(void *data)
    evas_event_thaw(evas_object_evas_get(wd->obj));
    evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
+#endif
+
+static void
+_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __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;
+   if (it->wd->changed_job) ecore_job_del(it->wd->changed_job);
+   it->wd->changed_job = ecore_job_add(_changed_job, it->wd);
+}
 
 static Eina_Bool
 _must_recalc_idler(void *data)
@@ -2638,7 +2826,10 @@ static void
 _scroll_item(Widget_Data *wd)
 {
    Elm_Gen_Item *it = NULL;
+//FIXME: group raise
+#if 0
    Evas_Coord gith = 0;
+#endif
    Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
    if (!wd->show_item) return;
 
@@ -2651,8 +2842,11 @@ _scroll_item(Widget_Data *wd)
    switch (wd->scrollto_type)
      {
       case ELM_GENLIST_ITEM_SCROLLTO_TOP:
+//FIXME: group raise
+#if 0
          if (it->item->group_item) gith = it->item->group_item->item->h;
          dy -= gith;
+#endif
          break;
       case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
          dy += ((it->item->h / 2) - (oh / 2));
@@ -2664,16 +2858,24 @@ _scroll_item(Widget_Data *wd)
               - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
            {
               it = wd->expanded_item;
+              dx = it->x + it->item->block->x;
+              dy = it->y + it->item->block->y;
+//FIXME: group raise
+#if 0
               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;
+#endif
               dw = it->item->block->w;
            }
          else
            {
+//FIXME: group raise
+#if 0
               if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
                 gith = it->item->group_item->item->h;
               dy -= gith;
+#endif
               dh = it->item->h;
            }
          break;
@@ -2864,7 +3066,6 @@ _update_job(void *data)
                   itminw = it->item->minw;
                   itminh = it->item->minh;
 
-                  it->item->updateme = EINA_FALSE;
                   if (it->realized)
                     {
                        _elm_genlist_item_unrealize(it, EINA_FALSE);
@@ -2878,6 +3079,7 @@ _update_job(void *data)
                     }
                   if ((it->item->minw != itminw) || (it->item->minh != itminh))
                     recalc = EINA_TRUE;
+                  it->item->updateme = EINA_FALSE;
                }
              num++;
           }
@@ -2900,6 +3102,95 @@ _update_job(void *data)
 }
 
 static void
+_changed_job(void *data)
+{
+   Widget_Data *wd = data; Eina_List *l2;
+   Item_Block *itb;
+   int num, num0, position = 0;
+   Eina_Bool width_changed = EINA_FALSE, height_changed = EINA_FALSE;
+   if (!wd) return;
+   wd->changed_job = NULL;
+   num = 0;
+   EINA_INLIST_FOREACH(wd->blocks, itb)
+     {
+        Evas_Coord itminw, itminh;
+        Elm_Gen_Item *it;
+
+        if (!itb->changeme)
+          {
+             num += itb->count;
+             if (position)
+               _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))
+               {
+                  Evas_Coord mw = -1, mh = -1;
+                  itminw = it->item->minw;
+                  itminh = it->item->minh;
+
+                  if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->w;
+                  if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
+                    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+                  if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
+                  edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
+                  if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
+                    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
+                  if (mw > itb->w)
+                    width_changed = EINA_TRUE;
+                  else
+                    mw = itb->w;
+                  it->item->w = it->item->minw = mw;
+                  it->item->h = it->item->minh = mh;
+                  it->item->mincalcd = EINA_TRUE;
+
+                  //if ((it->item->minw != itminw) || (it->item->minh != itminh))
+                  //if ((it->item->minh != itminh))
+                  //  recalc = 1;
+                  if ((it->item->minw != itminw))
+                    width_changed = EINA_TRUE;
+                  if ((it->item->minh != itminh))
+                    height_changed = EINA_TRUE;
+
+                  if ((!it->wd->group_item_width) && (it->group))
+                    {
+                       it->wd->group_item_width = mw;
+                       it->wd->group_item_height = mh;
+                    }
+                  else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
+                    {
+                       it->wd->item_width = mw;
+                       it->wd->item_height = mh;
+                    }
+               }
+             num++;
+          }
+        itb->changeme = EINA_FALSE;
+        // TODO: why this is separated.
+        if (height_changed)
+          {
+             position = 1;
+             itb->changed = EINA_TRUE;
+             _item_block_recalc(itb, num0, 0);
+             _item_block_position(itb, num0);
+          }
+        else if (width_changed)
+          {
+             _item_block_position(itb, num0);
+          }
+     }
+   if (position)
+     {
+        if (wd->calc_job) ecore_job_del(wd->calc_job);
+        wd->calc_job = ecore_job_add(_calc_job, wd);
+     }
+}
+
+static void
 _pan_set(Evas_Object *obj,
          Evas_Coord   x,
          Evas_Coord   y)
@@ -2908,6 +3199,16 @@ _pan_set(Evas_Object *obj,
    Item_Block *itb;
 
    if (!sd) return;
+   //   Evas_Coord ow, oh;
+   //   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+   //   ow = sd->wd->minw - ow;
+   //   if (ow < 0) ow = 0;
+   //   oh = sd->wd->minh - oh;
+   //   if (oh < 0) oh = 0;
+   //   if (x < 0) x = 0;
+   //   if (y < 0) y = 0;
+   //   if (x > ow) x = ow;
+   //   if (y > oh) y = oh;
    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
    sd->wd->pan_x = x;
    sd->wd->pan_y = y;
@@ -3053,8 +3354,11 @@ _pan_calculate(Evas_Object *obj)
    Item_Block *itb;
    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
    int in = 0;
+//FIXME: group raise
+#if 0
    Elm_Gen_Item *git;
    Eina_List *l;
+#endif
 
    if (!sd) return;
    evas_event_freeze(evas_object_evas_get(obj));
@@ -3066,11 +3370,15 @@ _pan_calculate(Evas_Object *obj)
      }
 
    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
+   sd->wd->prev_viewport_w = ow;
    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
+//FIXME: group raise
+#if 0
    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
      {
         git->item->want_realize = EINA_FALSE;
      }
+#endif
 
    if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
      {
@@ -3093,7 +3401,13 @@ _pan_calculate(Evas_Object *obj)
                                 cvx, cvy, cvw, cvh))
           {
              if ((!itb->realized) || (itb->changed))
-               _item_block_realize(itb);
+               {
+                  _item_block_realize(itb);
+
+                  if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
+                  sd->wd->calc_job = NULL;
+                  _calc_job(sd->wd);
+               }
              _item_block_position(itb, in);
           }
         else
@@ -3102,8 +3416,11 @@ _pan_calculate(Evas_Object *obj)
           }
         in += itb->count;
      }
+//FIXME: group raise
+#if 0
    if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
       _group_items_recalc(sd->wd);
+#endif
    if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
      {
         if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
@@ -3443,7 +3760,7 @@ _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
    if (it->flipped) edje_object_signal_emit(it->deco_all_view, "elm,state,flip,enabled", "elm");
    if (!it->item->deco_all_contents)
      it->item->deco_all_contents =
-        elm_widget_stringlist_get(edje_object_data_get(it->deco_all_view, "contents"));
+        elm_widget_stringlist_get(edje_object_data_get(it->deco_all_view, "decorate_contents"));
    it->item->deco_all_content_objs =
      _item_mode_content_realize(it, it->deco_all_view,
                                 &it->item->deco_all_contents, NULL,
@@ -3556,6 +3873,12 @@ elm_genlist_add(Evas_Object *parent)
 
    wd->generation = 1;
    wd->scr = elm_smart_scroller_add(e);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _mouse_down_scroller, obj);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_UP,
+                                  _mouse_up_scroller, obj);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_MOUSE_MOVE,
+                                  _mouse_move_scroller, obj);
    elm_smart_scroller_widget_set(wd->scr, obj);
    elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
                                        elm_widget_style_get(obj));
@@ -3578,6 +3901,7 @@ elm_genlist_add(Evas_Object *parent)
    wd->item_cache_max = wd->max_items_per_block * 2;
    wd->longpress_timeout = _elm_config->longpress_timeout;
    wd->highlight = EINA_TRUE;
+   wd->tree_effect_enabled = _elm_config->effect_enable;
 
    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
@@ -3606,7 +3930,9 @@ elm_genlist_add(Evas_Object *parent)
 void
 _item_select(Elm_Gen_Item *it)
 {
+   Eina_List *l;
    Evas_Object *obj = WIDGET(it);
+   Evas_Object *item_obj;
 
    if ((it->generation < it->wd->generation) || (it->decorate_it_set) ||
        (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
@@ -3622,6 +3948,31 @@ _item_select(Elm_Gen_Item *it)
    evas_object_ref(obj);
    it->walking++;
    it->wd->walking++;
+   if (it->wd->last_selected_item &&
+       (it != (Elm_Gen_Item *) it->wd->last_selected_item))
+     {
+        Elm_Gen_Item *_lsit = (Elm_Gen_Item *)it->wd->last_selected_item;
+
+        EINA_LIST_FOREACH(_lsit->content_objs, l, item_obj)
+          {
+             elm_widget_focused_object_clear(item_obj);
+             elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
+          }
+        if (elm_widget_type_get(obj) == _genlist)
+          {
+             EINA_LIST_FOREACH(_lsit->item->flip_content_objs, l, item_obj)
+               {
+                  elm_widget_focused_object_clear(item_obj);
+                  elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
+               }
+             EINA_LIST_FOREACH(_lsit->item->deco_all_content_objs, l, item_obj)
+               {
+                  elm_widget_focused_object_clear(item_obj);
+                  elm_widget_tree_unfocusable_set(item_obj, EINA_TRUE);
+               }
+          }
+        _lsit->can_focus = EINA_FALSE;
+     }
    if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
    if (it->generation == it->wd->generation)
      evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
@@ -3651,6 +4002,27 @@ _item_content_get_hook(Elm_Gen_Item *it, const char *part)
    return edje_object_part_swallow_get(VIEW(it), part);
 }
 
+static void
+_item_content_set_hook(Elm_Gen_Item *it, const char *part, Evas_Object *content)
+{
+   if (content && part)
+     {
+        it->content_objs = eina_list_append(it->content_objs, content);
+        edje_object_part_swallow(VIEW(it), part, content);
+     }
+}
+
+static Evas_Object *
+_item_content_unset_hook(Elm_Gen_Item *it, const char *part)
+{
+   Evas_Object *obj;
+   obj = edje_object_part_swallow_get(VIEW(it), part);
+   if (!obj) return NULL;
+   it->content_objs = eina_list_remove(it->content_objs, obj);
+   edje_object_part_unswallow(VIEW(it), obj);
+   return obj;
+}
+
 static const char *
 _item_text_get_hook(Elm_Gen_Item *it, const char *part)
 {
@@ -3747,6 +4119,8 @@ _elm_genlist_item_new(Widget_Data              *wd,
    it->func.func = func;
    it->func.data = func_data;
    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
+   elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
+   elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
    elm_widget_item_disable_hook_set(it, _item_disable_hook);
    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
@@ -3777,6 +4151,8 @@ _item_new(Widget_Data                  *wd,
    if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
    it->item->expanded_depth = 0;
    ELM_GEN_ITEM_SETUP(it);
+   it->mouse_cursor = NULL;
+   it->can_focus = EINA_TRUE;
    if (it->parent)
      {
         if (it->parent->group)
@@ -4896,6 +5272,35 @@ elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
    return ((Elm_Gen_Item *)it)->item->expanded_depth;
 }
 
+EINA_DEPRECATED EAPI void
+elm_genlist_item_display_only_set(Elm_Object_Item  *it,
+                                  Eina_Bool         display_only)
+{
+   ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
+   display_only = !!display_only;
+
+   if (display_only)
+     elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
+   else
+     {
+        Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
+        if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
+          elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DEFAULT);
+     }
+}
+
+EINA_DEPRECATED EAPI Eina_Bool
+elm_genlist_item_display_only_get(const Elm_Object_Item *it)
+{
+   ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
+   Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
+   if (_it->generation < _it->wd->generation) return EINA_FALSE;
+   Elm_Object_Select_Mode oldmode = elm_genlist_item_select_mode_get(it);
+   if (oldmode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
+     return EINA_TRUE;
+   return EINA_FALSE;
+}
+
 static Eina_Bool
 _elm_genlist_item_compute_coordinates(Elm_Object_Item *it,
                                       Elm_Genlist_Item_Scrollto_Type type,
@@ -5876,6 +6281,7 @@ _elm_genlist_item_unrealize(Elm_Gen_Item *it,
 
    if (!it->realized) return;
    if (it->wd->reorder_it == it) return;
+   if (it->defer_unrealize && !it->item->updateme) return;
 
    evas_event_freeze(evas_object_evas_get(WIDGET(it)));
    if (!calc)