wearable/rotary_selector: make item drag and drop more stable in editmode 96/203896/1
authorTaehyub Kim <taehyub.kim@samsung.com>
Fri, 1 Jun 2018 02:44:11 +0000 (11:44 +0900)
committerTaehyub Kim <taehyub.kim@samsung.com>
Thu, 18 Apr 2019 05:43:16 +0000 (14:43 +0900)
                          (sometimes, item is deleted when item is animating)

Change-Id: I2205e469aaa0d1303022c85d5040dcab6cf6588c

inc/wearable/efl_extension_common_private.h
src/wearable/efl_extension_rotary_selector.c

index 364756ff36a654e44e7785b88443e7c2157a16db..e340d48f7a23b3994b22d09376ad36454c88ded0 100644 (file)
@@ -166,6 +166,7 @@ struct _Eext_Rotary_Selector_Data {
    Ecore_Animator *del_item_move_animator;
    double item_move_start_time;
    Eina_Bool item_move_started;
+   Eina_Bool is_item_animating;
    Eext_Rotary_Selector_Item *tmp_drag_item;
    Eina_Bool drag_done;
    int del_item_index;
index eb0b931a66ddebffd37932465783aaf8bb856f56..5e0d892c939729b46c41116a574ba0666ce68372 100644 (file)
@@ -412,7 +412,6 @@ _dnd_enter_cb(void *data, Evas_Object *obj)
 static void
 _dnd_leave_cb(void *data, Evas_Object *obj)
 {
-
    Eext_Rotary_Selector_Data *rsd = data;
 
    rsd->drag_done = EINA_TRUE;
@@ -421,16 +420,27 @@ _dnd_leave_cb(void *data, Evas_Object *obj)
         ecore_timer_del(rsd->stand_timer);
         rsd->stand_timer = NULL;
      }
+
+   if (!rsd->tmp_drag_item)
+     return;
+
    if (rsd->drop_item_index != _ROTARY_SELECTOR_PRESSED_ITEM_INDEX_INVALID &&
        rsd->drop_item_index != rsd->drag_item_index)
      {
         //move item to new pos
         Eext_Rotary_Selector_Item *item;
 
-        item = eina_list_nth(rsd->item_list, rsd->drag_item_index);
-        rsd->item_list = eina_list_remove(rsd->item_list, item);
+        if (rsd->is_item_animating)
+          {
+             item = eina_list_nth(rsd->item_list, rsd->drag_item_index);
+             rsd->item_list = eina_list_prepend_relative(rsd->item_list, rsd->tmp_drag_item, item);
+             rsd->is_item_animating = EINA_FALSE;
+          }
+
+        rsd->item_list = eina_list_remove(rsd->item_list, rsd->tmp_drag_item);
         //delete tmp_item
-        evas_object_del(item->base.obj);
+        evas_object_del(rsd->tmp_drag_item->base.obj);
+        rsd->tmp_drag_item = NULL;
 
         item = eina_list_nth(rsd->item_list, rsd->drop_item_index);
         rsd->item_list = eina_list_prepend_relative(rsd->item_list, rsd->drag_item, item);
@@ -439,7 +449,6 @@ _dnd_leave_cb(void *data, Evas_Object *obj)
         _item_rearrange(rsd, rsd->selected_index);
         _items_transformation_update(rsd);
         _items_invalidate(rsd);
-
         _item_update_animation_run(rsd);
      }
    else
@@ -449,9 +458,8 @@ _dnd_leave_cb(void *data, Evas_Object *obj)
           {
              Eext_Rotary_Selector_Item *tmp_item;
 
-             tmp_item = eina_list_nth(rsd->item_list, rsd->drag_item_index);
-             rsd->item_list = eina_list_prepend_relative(rsd->item_list, rsd->drag_item, tmp_item);
-             rsd->item_list = eina_list_remove(rsd->item_list, tmp_item);
+             rsd->item_list = eina_list_prepend_relative(rsd->item_list, rsd->drag_item, rsd->tmp_drag_item);
+             rsd->item_list = eina_list_remove(rsd->item_list, rsd->tmp_drag_item);
 
              evas_object_show(rsd->drag_item->base.obj);
 
@@ -460,13 +468,27 @@ _dnd_leave_cb(void *data, Evas_Object *obj)
              _items_invalidate(rsd);
              _item_update_animation_run(rsd);
              //delete tmp_item
-             evas_object_del(tmp_item->base.obj);
+             evas_object_del(rsd->tmp_drag_item->base.obj);
+             rsd->tmp_drag_item = NULL;
           }
         else
           {
              ERR("drag item is NULL");
           }
      }
+
+    //FIXME: Sometimes, _dnd_leave_cb function is called unexpectely during drag item moving.
+    //       At that time, _dnd_done_cb function will not be called and also drag window is not removed abnormaly.
+    //       To prevent this wrong behavior, we should cancel drag and drop process using elm_drag_cancel()
+    //       and make drag window removed forcely.
+    //       After elm_drag_cancel is called, _dnd_done_cb still will not be called but the wrong behavior will not occur.
+    //
+    elm_drag_cancel(obj);
+    if (rsd->drag_item)
+      {
+         evas_object_smart_callback_call(rsd->rotary_selector, "item,reordered", (void*)rsd->drag_item);
+         rsd->drag_item = NULL;
+      }
 }
 
 static Eina_Bool
@@ -505,7 +527,11 @@ _drag_item_move_animator_cb(void *data)
    double v[4] = {_ROTARY_SELECTOR_CUBIC_BEZIER_P1_X, _ROTARY_SELECTOR_CUBIC_BEZIER_P1_Y,
                   _ROTARY_SELECTOR_CUBIC_BEZIER_P2_X, _ROTARY_SELECTOR_CUBIC_BEZIER_P2_Y};
 
-   if (rsd->drag_done) return ECORE_CALLBACK_CANCEL;
+   if (rsd->drag_done)
+     {
+        rsd->is_item_animating = EINA_FALSE;
+        return ECORE_CALLBACK_CANCEL;
+     }
 
    last_index = (rsd->current_page + 1) * _ROTARY_SELECTOR_PAGE_ITEM_MAX - 1;
    if (idx1 > idx2)
@@ -572,6 +598,7 @@ _drag_item_move_animator_cb(void *data)
              i++;
           }
      }
+
    if (p >= 1.0f)
      {
         Eext_Rotary_Selector_Item *pos_item;
@@ -584,6 +611,7 @@ _drag_item_move_animator_cb(void *data)
         _items_transformation_update(rsd);
         _items_invalidate(rsd);
         rsd->drag_item_index = eina_list_data_idx(rsd->item_list, rsd->tmp_drag_item);
+        rsd->is_item_animating = EINA_FALSE;
 
         return ECORE_CALLBACK_CANCEL;
      }
@@ -597,10 +625,12 @@ _drag_item_move(void *data)
    Eext_Rotary_Selector_Data *rsd = data;
 
    rsd->stand_timer = NULL;
-   rsd->tmp_drag_item = eina_list_nth(rsd->item_list, rsd->drag_item_index);
+
    if (!rsd->tmp_drag_item)
      return ECORE_CALLBACK_CANCEL;
 
+   rsd->is_item_animating = EINA_TRUE;
+
    evas_object_hide(rsd->tmp_drag_item->base.obj);
    rsd->item_list = eina_list_remove(rsd->item_list, rsd->tmp_drag_item);
    rsd->item_move_start_time = ecore_loop_time_get();
@@ -721,6 +751,8 @@ _image_create_icon(void *data, Evas_Object *parent, Evas_Coord *xoff, Evas_Coord
      return NULL;
    evas_object_show(tmp_item->base.obj);
 
+   rsd->tmp_drag_item = tmp_item;
+
    item = eina_list_nth(rsd->item_list, rsd->pressed_item_index);
    rsd->drag_item = item;
    tmp_item->index = item->index;
@@ -819,21 +851,14 @@ static void
 _drag_done_cb(void *data, Evas_Object *obj)
 {
    Eext_Rotary_Selector_Data *rsd = data;
-   if (rsd->drag_done)
-     {
-        evas_object_smart_callback_call(rsd->rotary_selector, "item,reordered", (void*)rsd->drag_item);
-        rsd->drag_item = NULL;
-        return;
-     }
    //there was no dnd pos, leave, done at drop side
    //add back item
-   if (rsd->drag_item)
+   if (rsd->drag_item && rsd->tmp_drag_item)
      {
         Eext_Rotary_Selector_Item *tmp_item;
 
-        tmp_item = eina_list_nth(rsd->item_list, rsd->drag_item_index);
-        rsd->item_list = eina_list_prepend_relative(rsd->item_list, rsd->drag_item, tmp_item);
-        rsd->item_list = eina_list_remove(rsd->item_list, tmp_item);
+        rsd->item_list = eina_list_prepend_relative(rsd->item_list, rsd->drag_item, rsd->tmp_drag_item);
+        rsd->item_list = eina_list_remove(rsd->item_list, rsd->tmp_drag_item);
 
         evas_object_show(rsd->drag_item->base.obj);
 
@@ -842,8 +867,9 @@ _drag_done_cb(void *data, Evas_Object *obj)
         _items_invalidate(rsd);
         _item_update_animation_run(rsd);
         //delete tmp_item
-        evas_object_del(tmp_item->base.obj);
+        evas_object_del(rsd->tmp_drag_item->base.obj);
         rsd->drag_item = NULL;
+        rsd->tmp_drag_item = NULL;
      }
    else
      {