From: Seunggyun Kim <sgyun.kim@samsung.com>
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 2 Jun 2011 03:10:11 +0000 (03:10 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 2 Jun 2011 03:10:11 +0000 (03:10 +0000)
Subject: [E-devel] [Patch] elm_genlist - added new feature : genlist
reorder mode

I introduce a new feature "reorder mode" of genlist.
Using this feature, user can reoder genlist items dynamically.

[API]
==================================================================
- EAPI Eina_Bool   elm_genlist_item_rename_mode_get(Elm_Genlist_Item *it)
Get the rename mode state of an item. This gets the rename mode state
of an item

- EAPI void   elm_genlist_reorder_mode_set(Evas_Object *obj, Eina_Bool reorder_mode)
Set genlist reorder mode. This enables the item is moved to another
item.
==================================================================

After set this reorder api, if user press an item (long press), the item can
be moved another position.
Then if the user releases the item, the item will be reodered in genlist.
When the user releases the holding item, Elm_Genlist_Item_Class.func.moved
callback is also called.
If needed, the application can add some logic in that callback function.

git-svn-id: https://svn.enlightenment.org/svn/e/trunk/elementary@59883 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/test.c
src/bin/test_genlist.c
src/lib/Elementary.h.in
src/lib/elm_genlist.c

index bf0bae4..0c60835 100644 (file)
@@ -69,6 +69,7 @@ void test_genlist7(void *data, Evas_Object *obj, void *event_info);
 void test_genlist8(void *data, Evas_Object *obj, void *event_info);
 void test_genlist9(void *data, Evas_Object *obj, void *event_info);
 void test_genlist10(void *data, Evas_Object *obj, void *event_info);
+void test_genlist11(void *data, Evas_Object *obj, void *event_info);
 void test_table(void *data, Evas_Object *obj, void *event_info);
 void test_table2(void *data, Evas_Object *obj, void *event_info);
 void test_table3(void *data, Evas_Object *obj, void *event_info);
@@ -339,6 +340,7 @@ my_win_main(char *autorun)
    ADD_TEST("Genlist Group", test_genlist8);
    ADD_TEST("Genlist Group Tree", test_genlist9);
    ADD_TEST("Genlist Mode", test_genlist10);
+   ADD_TEST("Genlist Reorder Mode", test_genlist11);
 #ifdef HAVE_EIO
    ADD_TEST("Genlist Eio", test_eio);
 #endif
index 91aa177..e736948 100644 (file)
@@ -1782,4 +1782,120 @@ test_genlist10(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_i
    evas_object_resize(win, 520, 520);
    evas_object_show(win);
 }
+
+/*************/
+
+static Elm_Genlist_Item_Class itc11;
+
+char *gl11_label_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+   char buf[256];
+   snprintf(buf, sizeof(buf), "Item # %i", (int)(long)data);
+   return strdup(buf);
+}
+
+Evas_Object *gl11_icon_get(void *data __UNUSED__, Evas_Object *obj, const char *part)
+{
+   char buf[PATH_MAX];
+   Evas_Object *ic = elm_icon_add(obj);
+   if (!strcmp(part, "elm.swallow.end"))
+     snprintf(buf, sizeof(buf), "%s/images/bubble.png", PACKAGE_DATA_DIR);
+   else
+     snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
+   elm_icon_file_set(ic, buf, NULL);
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+   return ic;
+}
+
+static void
+_reorder_tg_changed(void *data, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   elm_genlist_reorder_mode_set(data, elm_toggle_state_get(obj));
+}
+
+/**
+ * gl_moved is called after an item was reordered.
+ * This is only called when reorder mode is enabled.
+ *
+ * @param obj          :  the genlist object.
+ * @param item         :  the moved item.
+ * @param rel_item     :  the relative item.
+ * @param move_after   :  whether or not the rel_item is after item.
+ *
+ * If the move_after is true,
+ *  the item(*item) had been moved after the given relative item(*rel_item) in list.
+ * If the move_after is false,
+ *  the item(*item) had been moved before the given relative item(*rel_item) in list.
+ *
+ */
+static void _gl_moved(Evas_Object *obj, Elm_Genlist_Item *item, Elm_Genlist_Item *rel_item, Eina_Bool move_after)
+{
+   // if needed, add application logic.
+}
+
+void
+test_genlist11(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *win, *bg, *fr, *lb, *bx, *tg, *gl;
+   int i;
+
+   win = elm_win_add(NULL, "genlist11", ELM_WIN_BASIC);
+   elm_win_title_set(win, "Genlist Reorder Mode");
+   elm_win_autodel_set(win, 1);
+
+   bg = elm_bg_add(win);
+   elm_win_resize_object_add(win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, bx);
+   evas_object_show(bx);
+
+   fr = elm_frame_add(win);
+
+   elm_frame_label_set(fr, "Reorder Mode");
+   elm_box_pack_end(bx, fr);
+   evas_object_show(fr);
+
+   lb = elm_label_add(win);
+   elm_label_label_set(lb,
+                       "Enable reorder mode if you want to move item.<br>"
+                       "Then long press and drag item.");
+   elm_frame_content_set(fr, lb);
+   evas_object_show(lb);
+
+   gl = elm_genlist_add(win);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(gl);
+
+   tg = elm_toggle_add(win);
+   elm_toggle_label_set(tg, "Reorder Mode:");
+   elm_toggle_state_set(tg, elm_mirrored_get());
+   evas_object_smart_callback_add(tg, "changed", _reorder_tg_changed, gl);
+   elm_box_pack_end(bx, tg);
+   evas_object_show(tg);
+
+   itc10.item_style     = "default";
+   itc10.func.label_get = gl11_label_get;
+   itc10.func.icon_get  = gl11_icon_get;
+   itc10.func.state_get = gl_state_get;
+   itc10.func.del       = gl_del;
+
+   for (i = 0; i < 50; i++)
+     elm_genlist_item_append(gl,
+                             &itc10,
+                             (void *)(1 + i)/* item data */,
+                             NULL/* parent */,
+                             ELM_GENLIST_ITEM_NONE/* flags */,
+                             NULL/* func */,
+                             NULL/* func data */);
+
+   elm_box_pack_end(bx, gl);
+
+   evas_object_resize(win, 400, 500);
+   evas_object_show(win);
+}
 #endif
index 86393c6..1e9b685 100644 (file)
@@ -1859,6 +1859,7 @@ extern "C" {
    typedef Evas_Object *(*GenlistItemIconGetFunc)  (void *data, Evas_Object *obj, const char *part);
    typedef Eina_Bool    (*GenlistItemStateGetFunc) (void *data, Evas_Object *obj, const char *part);
    typedef void         (*GenlistItemDelFunc)      (void *data, Evas_Object *obj);
+   typedef void         (*GenlistItemMovedFunc)    (void *data, Elm_Genlist_Item *item, Elm_Genlist_Item *rel_item, Eina_Bool move_after);
 
    struct _Elm_Genlist_Item_Class
      {
@@ -1869,6 +1870,7 @@ extern "C" {
              GenlistItemIconGetFunc   icon_get;
              GenlistItemStateGetFunc  state_get;
              GenlistItemDelFunc       del;
+             GenlistItemMovedFunc     moved;
           } func;
         const char                *mode_item_style;
      };
index 2f1cb94..539bcb3 100644 (file)
@@ -6,6 +6,7 @@
 
 #define SWIPE_MOVES         12
 #define MAX_ITEMS_PER_BLOCK 32
+#define REORDER_EFFECT_TIME 0.5
 
 /**
  * @defgroup Genlist Genlist
@@ -203,17 +204,19 @@ struct _Widget_Data
    Eina_Inlist      *items, *blocks;
    Eina_List        *group_items;
    Pan              *pan;
-   Evas_Coord        pan_x, pan_y, w, h, minw, minh, realminw, prev_viewport_w;
+   Evas_Coord        pan_x, pan_y, old_pan_y, w, h, minw, minh, realminw, prev_viewport_w;
    Ecore_Job        *calc_job, *update_job;
    Ecore_Idle_Enterer *queue_idle_enterer;
    Ecore_Idler        *must_recalc_idler;
    Eina_List        *queue, *selected;
-   Elm_Genlist_Item *show_item, *last_selected_item, *anchor_item, *mode_item;
+   Elm_Genlist_Item *show_item, *last_selected_item, *anchor_item, *mode_item, *reorder_it, *reorder_rel;
    Eina_Inlist      *item_cache;
-   Evas_Coord        anchor_y;
+   Evas_Coord        anchor_y, reorder_start_y;
    Elm_List_Mode     mode;
    Ecore_Timer      *multi_timer, *scr_hold_timer;
+   Ecore_Animator   *item_moving_effect_timer;
    const char       *mode_type;
+   unsigned int      start_time;
    Evas_Coord        prev_x, prev_y, prev_mx, prev_my;
    Evas_Coord        cur_x, cur_y, cur_mx, cur_my;
    Eina_Bool         mouse_down : 1;
@@ -232,6 +235,8 @@ struct _Widget_Data
    Eina_Bool         homogeneous : 1;
    Eina_Bool         clear_me : 1;
    Eina_Bool         swipe : 1;
+   Eina_Bool         reorder_mode : 1;
+   Eina_Bool         reorder_pan_move : 1;
    struct
    {
       Evas_Coord x, y;
@@ -254,6 +259,7 @@ struct _Item_Block
    EINA_INLIST;
    int          count;
    int          num;
+   int          reorder_offset;
    Widget_Data *wd;
    Eina_List   *items;
    Evas_Coord   x, y, w, h, minw, minh;
@@ -289,7 +295,7 @@ struct _Elm_Genlist_Item
    Ecore_Timer                  *long_timer;
    Ecore_Timer                  *swipe_timer;
    Evas_Coord                    dx, dy;
-   Evas_Coord                    scrl_x, scrl_y;
+   Evas_Coord                    scrl_x, scrl_y, old_scrl_x, old_scrl_y;
 
    Elm_Genlist_Item             *rel;
    Evas_Object                  *mode_view;
@@ -329,6 +335,7 @@ struct _Elm_Genlist_Item
    Eina_Bool                     nocache : 1;
    Eina_Bool                     stacking_even : 1;
    Eina_Bool                     nostacking : 1;
+   Eina_Bool                     move_effect_enabled : 1;
 };
 
 struct _Item_Cache
@@ -383,11 +390,14 @@ static void      _signal_emit_hook(Evas_Object *obj,
                                    const char *source);
 static Eina_Bool _deselect_all_items(Widget_Data *wd);
 static void      _pan_calculate(Evas_Object *obj);
-static void      _item_position(Elm_Genlist_Item *it, Evas_Object *obj);
+static void      _item_position(Elm_Genlist_Item *it, Evas_Object *obj, Evas_Coord it_x, Evas_Coord it_y);
 static void      _mode_item_realize(Elm_Genlist_Item *it);
 static void      _mode_item_unrealize(Elm_Genlist_Item *it);
 static void      _item_mode_set(Elm_Genlist_Item *it);
 static void      _item_mode_unset(Widget_Data *wd);
+static void      _group_items_recalc(void *data);
+static void      _item_move_after(Elm_Genlist_Item *it, Elm_Genlist_Item *after);
+static void      _item_move_before(Elm_Genlist_Item *it, Elm_Genlist_Item *before);
 
 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
 
@@ -892,12 +902,12 @@ _item_block_del(Elm_Genlist_Item *it)
      }
    else
      {
-        if (itb->count < 16)
+        if (itb->count < itb->wd->max_items_per_block/2)
           {
              il = EINA_INLIST_GET(itb);
              Item_Block *itbp = (Item_Block *)(il->prev);
              Item_Block *itbn = (Item_Block *)(il->next);
-             if ((itbp) && ((itbp->count + itb->count) < 48))
+             if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
                {
                   Elm_Genlist_Item *it2;
 
@@ -912,7 +922,7 @@ _item_block_del(Elm_Genlist_Item *it)
                                                       EINA_INLIST_GET(itb));
                   free(itb);
                }
-             else if ((itbn) && ((itbn->count + itb->count) < 48))
+             else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
                {
                   while (itb->items)
                     {
@@ -1023,6 +1033,7 @@ _mouse_move(void        *data,
    Elm_Genlist_Item *it = data;
    Evas_Event_Mouse_Move *ev = event_info;
    Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
+   Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
 
    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
      {
@@ -1070,6 +1081,24 @@ _mouse_move(void        *data,
              ecore_timer_del(it->long_timer);
              it->long_timer = NULL;
           }
+        if ((it->wd->reorder_mode) && (it->wd->reorder_it))
+          {
+             evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
+             it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
+
+             if (!it->wd->reorder_start_y)
+               it->wd->reorder_start_y = it->block->y + it->y;
+
+             if (it_scrl_y < oy) y_pos = oy;
+             else if (it_scrl_y + it->wd->reorder_it->h > oy+oh)
+                y_pos = oy + oh - it->wd->reorder_it->h;
+             else y_pos = it_scrl_y;
+
+             _item_position(it, it->base.view, it->scrl_x, y_pos);
+
+             if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
+             it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
+          }
         return;
      }
    if (!it->display_only)
@@ -1134,13 +1163,33 @@ _mouse_move(void        *data,
 static Eina_Bool
 _long_press(void *data)
 {
-   Elm_Genlist_Item *it = data;
+   Elm_Genlist_Item *it = data, *it_tmp;
+   Eina_List *list, *l;
 
    it->long_timer = NULL;
    if ((it->disabled) || (it->dragging) || (it->display_only))
      return ECORE_CALLBACK_CANCEL;
    it->wd->longpressed = EINA_TRUE;
    evas_object_smart_callback_call(it->base.widget, SIG_LONGPRESSED, it);
+   if ((it->wd->reorder_mode) && (it->flags != ELM_GENLIST_ITEM_GROUP))
+     {
+        it->wd->reorder_it = it;
+        it->wd->reorder_start_y = 0;
+
+        evas_object_raise(it->base.view);
+        elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
+
+        list = elm_genlist_realized_items_get(it->wd->obj);
+        EINA_LIST_FOREACH(list, l, it_tmp)
+          {
+             if (it != it_tmp) _item_unselect(it_tmp);
+          }
+        if (elm_genlist_item_expanded_get(it))
+          {
+             elm_genlist_item_expanded_set(it, EINA_FALSE);
+             return ECORE_CALLBACK_RENEW;
+          }
+     }
    return ECORE_CALLBACK_CANCEL;
 }
 
@@ -1426,6 +1475,28 @@ _mouse_up(void        *data,
         it->wd->on_hold = EINA_FALSE;
         return;
      }
+   if ((it->wd->reorder_mode) && (it->wd->reorder_it))
+     {
+        Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
+
+        if (it->wd->reorder_rel)
+          {
+             if (it->wd->reorder_it->parent == it->wd->reorder_rel->parent)
+               {
+                  if (it_scrl_y <= it->wd->reorder_rel->scrl_y)
+                     _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
+                  else
+                     _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
+               }
+             else
+               {
+                  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_it = it->wd->reorder_rel = NULL;
+        elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
+     }
    if (it->wd->longpressed)
      {
         it->wd->longpressed = EINA_FALSE;
@@ -2042,6 +2113,7 @@ _item_unrealize(Elm_Genlist_Item *it, Eina_Bool calc)
    Evas_Object *icon;
 
    if (!it->realized) return;
+   if (it->wd->reorder_it == it) return;
    evas_event_freeze(evas_object_evas_get(it->wd->obj));
    if (!calc) evas_object_smart_callback_call(it->base.widget, SIG_UNREALIZED, it);
    if (it->long_timer)
@@ -2185,15 +2257,97 @@ _item_block_unrealize(Item_Block *itb)
    evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
 }
 
+static int
+_get_space_for_reorder_item(Elm_Genlist_Item *it)
+{
+   Evas_Coord rox, roy, row, roh, oy, oh;
+   Eina_Bool top = EINA_FALSE;
+   Elm_Genlist_Item *reorder_it = it->wd->reorder_it;
+   if (!reorder_it) return 0;
+   
+   evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
+   evas_object_geometry_get(it->wd->reorder_it->base.view, &rox, &roy, &row, &roh);
+   
+   if ((it->wd->reorder_start_y < it->block->y) && 
+       (roy - oy + (roh / 2) >= it->block->y - it->wd->pan_y))
+     {
+        it->block->reorder_offset = it->wd->reorder_it->h * -1;
+        if (it->block->count == 1)
+           it->wd->reorder_rel = it;
+     }
+   else if ((it->wd->reorder_start_y >= it->block->y) && 
+            (roy - oy + (roh / 2) <= it->block->y - it->wd->pan_y))
+     {
+        it->block->reorder_offset = it->wd->reorder_it->h;
+     }
+   else
+      it->block->reorder_offset = 0;
+   
+   it->scrl_y += it->block->reorder_offset;
+   
+   top = (ELM_RECTS_INTERSECT(it->scrl_x, it->scrl_y, it->w, it->h,
+                              rox, roy + (roh / 2), row, 1));
+   if (top)
+     {
+        it->wd->reorder_rel = it;
+        it->scrl_y += it->wd->reorder_it->h;
+        return it->wd->reorder_it->h;
+     }
+   else
+      return 0;
+}
+
+static Eina_Bool
+_reorder_item_moving_effect_timer_cb(void *data)
+{
+   Elm_Genlist_Item *it = data;
+   Eina_Bool down = EINA_FALSE;
+   double time, t;
+   int y, dy = it->h / 10 * _elm_config->scale, diff;
+   time = REORDER_EFFECT_TIME;
+   
+   t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
+   
+   if (t <= time) y = (1 * sin((t / time) * (M_PI / 2)) * dy);
+   else y = dy;
+   
+   diff = abs(it->old_scrl_y - it->scrl_y);
+   if (diff > it->h) y = diff / 2;
+   
+   if (it->old_scrl_y < it->scrl_y)
+     {
+        it->old_scrl_y += y;
+        down = EINA_TRUE;
+     }
+   else if (it->old_scrl_y > it->scrl_y)
+     {
+        it->old_scrl_y -= y;
+        down = EINA_FALSE;
+     }
+   _item_position(it, it->base.view, it->scrl_x, it->old_scrl_y);
+   _group_items_recalc(it->wd);
+   
+   if ((it->wd->reorder_pan_move) ||
+       (down && it->old_scrl_y >= it->scrl_y) || 
+       (!down && it->old_scrl_y <= it->scrl_y))
+     {
+        it->old_scrl_y = it->scrl_y;
+        it->move_effect_enabled = EINA_FALSE;
+        it->wd->item_moving_effect_timer = NULL;
+        return ECORE_CALLBACK_CANCEL;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
 static void
-_item_position(Elm_Genlist_Item *it, Evas_Object *view)
+_item_position(Elm_Genlist_Item *it, Evas_Object *view, Evas_Coord it_x, Evas_Coord it_y)
 {
    if (!it) return;
    if (!view) return;
 
    evas_event_freeze(evas_object_evas_get(it->wd->obj));
    evas_object_resize(view, it->w, it->h);
-   evas_object_move(view, it->scrl_x, it->scrl_y);
+   evas_object_move(view, it_x, it_y);
    evas_object_show(view);
    evas_event_thaw(evas_object_evas_get(it->wd->obj));
    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
@@ -2216,6 +2370,7 @@ _item_block_position(Item_Block *itb,
    EINA_LIST_FOREACH(itb->items, l, it)
      {
         if (it->delete_me) continue;
+        else if (it->wd->reorder_it == it) continue;
         it->x = 0;
         it->y = y;
         it->w = itb->w;
@@ -2234,6 +2389,8 @@ _item_block_position(Item_Block *itb,
                {
                   if (vis)
                     {
+                       if (it->wd->reorder_mode)
+                          y += _get_space_for_reorder_item(it);
                        git = it->group_item;
                        if (git)
                          {
@@ -2243,10 +2400,25 @@ _item_block_position(Item_Block *itb,
                               git->scrl_y = (it->scrl_y + it->h) - git->h;
                             git->want_realize = EINA_TRUE;
                          }
-                       if (it->mode_view)
-                          _item_position(it, it->mode_view);
-                       else
-                          _item_position(it, it->base.view);
+                       if ((it->wd->reorder_it) && (it->old_scrl_y != it->scrl_y))
+                         {
+                            if (!it->move_effect_enabled)
+                              {
+                                 it->move_effect_enabled = EINA_TRUE;
+                                 it->wd->item_moving_effect_timer = ecore_animator_add(_reorder_item_moving_effect_timer_cb, it);
+                              }
+                         }
+                       if (!it->move_effect_enabled)
+                          {
+                             {
+                                if (it->mode_view)
+                                   _item_position(it, it->mode_view, it->scrl_x, it->scrl_y);
+                                else
+                                   _item_position(it, it->base.view, it->scrl_x, it->scrl_y);
+                             }
+                           it->old_scrl_x = it->scrl_x;
+                           it->old_scrl_y = it->scrl_y;
+                          }
                     }
                   else
                     {
@@ -2543,7 +2715,7 @@ _pan_set(Evas_Object *obj,
           }
      }
 done:
-   evas_object_smart_changed(obj);
+   if(!sd->wd->item_moving_effect_timer) evas_object_smart_changed(obj);
 }
 
 static void
@@ -2685,7 +2857,17 @@ _pan_calculate(Evas_Object *obj)
           }
         in += itb->count;
      }
-   _group_items_recalc(sd->wd);
+   if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
+      _group_items_recalc(sd->wd);
+   if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
+     {
+        if (sd->wd->pan_y != sd->wd->old_pan_y)
+           sd->wd->reorder_pan_move = EINA_TRUE;
+        else sd->wd->reorder_pan_move = EINA_FALSE;
+        evas_object_raise(sd->wd->reorder_it->base.view);
+        sd->wd->old_pan_y = sd->wd->pan_y;
+        sd->wd->start_time = ecore_loop_time_get();
+     }
    evas_event_thaw(evas_object_evas_get(obj));
    evas_event_thaw_eval(evas_object_evas_get(obj));
 }
@@ -2882,7 +3064,7 @@ _item_mode_set(Elm_Genlist_Item *it)
 
    evas_event_freeze(evas_object_evas_get(it->wd->obj));
    _mode_item_realize(it);
-   _item_position(it, it->mode_view);
+   _item_position(it, it->mode_view, it->scrl_x, it->scrl_y);
    evas_event_thaw(evas_object_evas_get(it->wd->obj));
    evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
 
@@ -3278,6 +3460,45 @@ _elm_genlist_item_compare(const void *data, const void *data1)
    return _elm_genlist_item_compare_cb(item->base.data, item1->base.data);
 }
 
+static void
+_item_move_after(Elm_Genlist_Item *it, Elm_Genlist_Item *after)
+{
+   if (!it) return;
+   if (!after) return;
+
+   it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
+   _item_block_del(it);
+
+   it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
+   it->rel = after;
+   it->rel->relcount++;
+   it->before = EINA_FALSE;
+   if (after->group_item) it->group_item = after->group_item;
+   _item_queue(it->wd, it);
+
+   if (it->itc->func.moved)
+     it->itc->func.moved(it->base.widget, it, after, EINA_TRUE);
+}
+
+static void
+_item_move_before(Elm_Genlist_Item *it, Elm_Genlist_Item *before)
+{
+   if (!it) return;
+   if (!before) return;
+
+   it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
+   _item_block_del(it);
+   it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
+   it->rel = before;
+   it->rel->relcount++;
+   it->before = EINA_TRUE;
+   if (before->group_item) it->group_item = before->group_item;
+   _item_queue(it->wd, it);
+
+   if (it->itc->func.moved)
+     it->itc->func.moved(it->base.widget, it, before, EINA_FALSE);
+}
+
 /**
  * Append item to the end of the genlist
  *
@@ -3634,9 +3855,15 @@ elm_genlist_clear(Evas_Object *obj)
         eina_list_free(wd->selected);
         wd->selected = NULL;
      }
+   if (wd->item_moving_effect_timer)
+     {
+        ecore_animator_del(wd->item_moving_effect_timer);
+        wd->item_moving_effect_timer = NULL;
+     }
    wd->show_item = NULL;
    wd->pan_x = 0;
    wd->pan_y = 0;
+   wd->old_pan_y = 0;
    wd->minw = 0;
    wd->minh = 0;
    if (wd->pan_smart)
@@ -5454,3 +5681,40 @@ elm_genlist_mode_item_get(const Evas_Object *obj)
    if (!wd) return NULL;
    return wd->mode_item;
 }
+
+/**
+ * Set reorder mode
+ *
+ * @param obj The genlist object
+ * @param reorder_mode The reorder mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI void
+elm_genlist_reorder_mode_set(Evas_Object *obj,
+                             Eina_Bool    reorder_mode)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->reorder_mode = reorder_mode;
+}
+
+/**
+ * Get the reorder mode
+ *
+ * @param obj The genlist object
+ * @return The reorder mode
+ * (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Genlist
+ */
+EAPI Eina_Bool
+elm_genlist_reorder_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->reorder_mode;
+}